Commit 2e18f1e1517bc5ab149dbae8aabed8e76101d66b

Authored by sqy
1 parent 6897f6a0

feat:[DEFECT-343]:新增设备列表的SN编码

@@ -194,3 +194,9 @@ export const getChildDevicePage = (params: ChildDeviceParams) => { @@ -194,3 +194,9 @@ export const getChildDevicePage = (params: ChildDeviceParams) => {
194 params, 194 params,
195 }); 195 });
196 }; 196 };
  197 +
  198 +export const generateSNCode = () => {
  199 + return defHttp.get({
  200 + url: '/device/sn',
  201 + });
  202 +};
@@ -23,6 +23,13 @@ export const step1Schemas: FormSchema[] = [ @@ -23,6 +23,13 @@ export const step1Schemas: FormSchema[] = [
23 }, 23 },
24 }, 24 },
25 { 25 {
  26 + field: 'sn',
  27 + label: 'SN码',
  28 + component: 'Input',
  29 + required: true,
  30 + slot: 'snCode',
  31 + },
  32 + {
26 field: 'deviceType', 33 field: 'deviceType',
27 label: '设备类型', 34 label: '设备类型',
28 required: true, 35 required: true,
@@ -12,9 +12,11 @@ export const columns: BasicColumn[] = [ @@ -12,9 +12,11 @@ export const columns: BasicColumn[] = [
12 slots: { customRender: 'img' }, 12 slots: { customRender: 'img' },
13 }, 13 },
14 { 14 {
15 - title: '设备名称',  
16 dataIndex: 'name', 15 dataIndex: 'name',
17 - width: 120, 16 + width: 200,
  17 + align: 'left',
  18 + slots: { customRender: 'name', title: 'deviceTitle' },
  19 + ellipsis: true,
18 }, 20 },
19 { 21 {
20 title: '设备类型', 22 title: '设备类型',
@@ -18,6 +18,12 @@ @@ -18,6 +18,12 @@
18 </div> 18 </div>
19 </Upload> 19 </Upload>
20 </template> 20 </template>
  21 + <template #snCode="{ model, field }">
  22 + <div class="flex">
  23 + <Input v-model:value="model[field]" />
  24 + <a-button type="link" @click="generateSN">自动生成</a-button>
  25 + </div>
  26 + </template>
21 <template #deviceAddress> 27 <template #deviceAddress>
22 <Input disabled v-model:value="positionState.address"> 28 <Input disabled v-model:value="positionState.address">
23 <template #addonAfter> 29 <template #addonAfter>
@@ -83,7 +89,7 @@ @@ -83,7 +89,7 @@
83 import { upload } from '/@/api/oss/ossFileUploader'; 89 import { upload } from '/@/api/oss/ossFileUploader';
84 import { FileItem } from '/@/components/Upload/src/typing'; 90 import { FileItem } from '/@/components/Upload/src/typing';
85 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; 91 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
86 - 92 + import { generateSNCode } from '/@/api/device/deviceManager.ts';
87 import icon from '/@/assets/images/wz.png'; 93 import icon from '/@/assets/images/wz.png';
88 import { useDebounceFn } from '@vueuse/core'; 94 import { useDebounceFn } from '@vueuse/core';
89 export default defineComponent({ 95 export default defineComponent({
@@ -281,6 +287,14 @@ @@ -281,6 +287,14 @@
281 positionState.map.panTo(option.point); //将地图的中心点更改为选定坐标点 287 positionState.map.panTo(option.point); //将地图的中心点更改为选定坐标点
282 } 288 }
283 289
  290 + const generateSN = async () => {
  291 + const data = await generateSNCode();
  292 + console.log(data);
  293 + setFieldsValue({
  294 + sn: data,
  295 + });
  296 + };
  297 +
284 // 确定选择的位置 298 // 确定选择的位置
285 const handleOk = () => { 299 const handleOk = () => {
286 visible.value = false; 300 visible.value = false;
@@ -331,6 +345,7 @@ @@ -331,6 +345,7 @@
331 }, 345 },
332 }); 346 });
333 } 347 }
  348 +
334 return { 349 return {
335 resetFields, 350 resetFields,
336 positionState, 351 positionState,
@@ -355,6 +370,7 @@ @@ -355,6 +370,7 @@
355 handleSelect, 370 handleSelect,
356 dataSource, 371 dataSource,
357 debounceSearch, 372 debounceSearch,
  373 + generateSN,
358 }; 374 };
359 }, 375 },
360 }); 376 });
@@ -6,20 +6,14 @@ @@ -6,20 +6,14 @@
6 @select="handleSelect" 6 @select="handleSelect"
7 ref="organizationIdTreeRef" 7 ref="organizationIdTreeRef"
8 /> 8 />
9 - <BasicTable  
10 - @selection-change="useSelectionChange"  
11 - :rowSelection="{ type: 'checkbox' }"  
12 - @register="registerTable"  
13 - class="w-5/6 xl:w-4/5"  
14 - :clickToRowSelect="false"  
15 - > 9 + <BasicTable @register="registerTable" class="w-5/6 xl:w-4/5">
16 <template #toolbar> 10 <template #toolbar>
17 <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> 新增设备 </a-button> 11 <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> 新增设备 </a-button>
18 <a-button 12 <a-button
19 color="error" 13 color="error"
20 v-if="authBtn(role)" 14 v-if="authBtn(role)"
21 @click="handleDeleteOrBatchDelete(null)" 15 @click="handleDeleteOrBatchDelete(null)"
22 - :disabled="disabled" 16 + :disabled="hasBatchDelete"
23 > 17 >
24 批量删除 18 批量删除
25 </a-button> 19 </a-button>
@@ -38,6 +32,31 @@ @@ -38,6 +32,31 @@
38 " 32 "
39 /> 33 />
40 </template> 34 </template>
  35 + <template #deviceTitle>
  36 + <div>
  37 + <span> 设备名称/设备SN</span>
  38 + <Popover title="帮助" placement="right">
  39 + <QuestionCircleOutlined class="ml-2" />
  40 + <template #content>
  41 + <ul>
  42 + <li>1.设备的SN码,为平台的唯一编码,对通过Modbus协议上报数据的设备,</li>
  43 + <li>&nbsp;&nbsp;&nbsp;平台将通过设备SN进行鉴定.</li>
  44 + <li>2.为了方便使用,设备SN可以点击复制.</li>
  45 + </ul>
  46 + </template>
  47 + </Popover>
  48 + </div>
  49 + </template>
  50 + <template #name="{ record }">
  51 + <div>
  52 + {{ record.name }}
  53 + </div>
  54 + <Tooltip title="设备SN码" placement="topRight">
  55 + <a-button type="link" @click="copySN(record.sn)" style="padding: 0">
  56 + {{ record.sn }}
  57 + </a-button>
  58 + </Tooltip>
  59 + </template>
41 <template #deviceProfile="{ record }"> 60 <template #deviceProfile="{ record }">
42 <a-button type="link" class="ml-2" @click="goDeviceProfile(record.deviceProfile.name)"> 61 <a-button type="link" class="ml-2" @click="goDeviceProfile(record.deviceProfile.name)">
43 {{ record.deviceProfile.name }} 62 {{ record.deviceProfile.name }}
@@ -122,16 +141,16 @@ @@ -122,16 +141,16 @@
122 </BasicTable> 141 </BasicTable>
123 <DeviceDetailDrawer @register="registerDetailDrawer" /> 142 <DeviceDetailDrawer @register="registerDetailDrawer" />
124 <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleSuccess" /> 143 <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleSuccess" />
125 - <CustomerModal @register="registerCustomerModal" @reload="handleSuccess" /> 144 + <CustomerModal @register="registerCustomerModal" @reload="handleReload" />
126 </PageWrapper> 145 </PageWrapper>
127 </div> 146 </div>
128 </template> 147 </template>
129 <script lang="ts"> 148 <script lang="ts">
130 - import { defineComponent, reactive, ref } from 'vue'; 149 + import { defineComponent, reactive, unref } from 'vue';
131 import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; 150 import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel';
132 import { BasicTable, useTable, TableAction, TableImg } from '/@/components/Table'; 151 import { BasicTable, useTable, TableAction, TableImg } from '/@/components/Table';
133 import { columns, searchFormSchema } from './config/device.data'; 152 import { columns, searchFormSchema } from './config/device.data';
134 - import { Tag } from 'ant-design-vue'; 153 + import { Tag, Tooltip, Popover } from 'ant-design-vue';
135 import { 154 import {
136 deleteDevice, 155 deleteDevice,
137 devicePage, 156 devicePage,
@@ -151,7 +170,9 @@ @@ -151,7 +170,9 @@
151 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 170 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
152 import { getAuthCache } from '/@/utils/auth'; 171 import { getAuthCache } from '/@/utils/auth';
153 import { authBtn } from '/@/enums/roleEnum'; 172 import { authBtn } from '/@/enums/roleEnum';
154 - 173 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
  174 + import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
  175 + import { QuestionCircleOutlined } from '@ant-design/icons-vue';
155 export default defineComponent({ 176 export default defineComponent({
156 name: 'DeviceManagement', 177 name: 'DeviceManagement',
157 components: { 178 components: {
@@ -164,18 +185,30 @@ @@ -164,18 +185,30 @@
164 DeviceDetailDrawer, 185 DeviceDetailDrawer,
165 CustomerModal, 186 CustomerModal,
166 TableImg, 187 TableImg,
  188 + Tooltip,
  189 + QuestionCircleOutlined,
  190 + Popover,
167 }, 191 },
168 setup(_) { 192 setup(_) {
  193 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions, resetSelectedRowKeys } =
  194 + useBatchDelete(deleteDevice, handleSuccess);
  195 + selectionOptions.rowSelection.getCheckboxProps = (record: Recordable) => {
  196 + // Demo:status为1的选择框禁用
  197 + if (record.customerId) {
  198 + return { disabled: true };
  199 + } else {
  200 + return { disabled: false };
  201 + }
  202 + };
  203 +
169 const { createMessage } = useMessage(); 204 const { createMessage } = useMessage();
170 - let selectedRowKeys: any = [];  
171 - const disabled = ref(true);  
172 const go = useGo(); 205 const go = useGo();
173 const searchInfo = reactive<Recordable>({}); 206 const searchInfo = reactive<Recordable>({});
174 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); 207 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
175 const [registerModal, { openModal }] = useModal(); 208 const [registerModal, { openModal }] = useModal();
176 const [registerCustomerModal, { openModal: openCustomerModal }] = useModal(); 209 const [registerCustomerModal, { openModal: openCustomerModal }] = useModal();
177 const [registerDetailDrawer, { openDrawer }] = useDrawer(); 210 const [registerDetailDrawer, { openDrawer }] = useDrawer();
178 - const [registerTable, { reload, getSelectRows, getSelectRowKeys }] = useTable({ 211 + const [registerTable, { reload, setSelectedRowKeys }] = useTable({
179 title: '设备列表', 212 title: '设备列表',
180 api: devicePage, 213 api: devicePage,
181 columns, 214 columns,
@@ -190,12 +223,14 @@ @@ -190,12 +223,14 @@
190 showIndexColumn: false, 223 showIndexColumn: false,
191 rowKey: 'id', 224 rowKey: 'id',
192 searchInfo: searchInfo, 225 searchInfo: searchInfo,
  226 + clickToRowSelect: false,
193 actionColumn: { 227 actionColumn: {
194 width: 300, 228 width: 300,
195 title: '操作', 229 title: '操作',
196 slots: { customRender: 'action' }, 230 slots: { customRender: 'action' },
197 fixed: 'right', 231 fixed: 'right',
198 }, 232 },
  233 + ...selectionOptions,
199 }); 234 });
200 235
201 const userInfo: any = getAuthCache(USER_INFO_KEY); 236 const userInfo: any = getAuthCache(USER_INFO_KEY);
@@ -210,10 +245,15 @@ @@ -210,10 +245,15 @@
210 function handleDispatchCustomer(record: Recordable) { 245 function handleDispatchCustomer(record: Recordable) {
211 openCustomerModal(true, record); 246 openCustomerModal(true, record);
212 } 247 }
  248 + function handleReload() {
  249 + setSelectedRowKeys([]);
  250 + resetSelectedRowKeys();
  251 + handleSuccess();
  252 + }
213 // 取消分配客户 253 // 取消分配客户
214 async function handleCancelDispatchCustomer(record: Recordable) { 254 async function handleCancelDispatchCustomer(record: Recordable) {
215 await cancelDispatchCustomer(record); 255 await cancelDispatchCustomer(record);
216 - handleSuccess(); 256 + handleReload();
217 } 257 }
218 258
219 function handleDetail(record: Recordable) { 259 function handleDetail(record: Recordable) {
@@ -244,42 +284,11 @@ @@ -244,42 +284,11 @@
244 function goDeviceProfile(e) { 284 function goDeviceProfile(e) {
245 go(PageEnum.DEVICE_PROFILE + '?name=' + String(e)); 285 go(PageEnum.DEVICE_PROFILE + '?name=' + String(e));
246 } 286 }
247 - const useSelectionChange = () => {  
248 - selectedRowKeys = getSelectRowKeys();  
249 - if (selectedRowKeys.length > 0) {  
250 - disabled.value = false;  
251 - }  
252 - const isJudge = getSelectRows().map((m) => {  
253 - return {  
254 - status: m.customerId,  
255 - id: m.id,  
256 - };  
257 - });  
258 - isJudge.some((s) => {  
259 - if (s.status != undefined) {  
260 - disabled.value = true;  
261 - }  
262 - });  
263 - };  
264 - // 删除或批量删除  
265 - const handleDeleteOrBatchDelete = async (record: Recordable | null) => {  
266 - if (record) {  
267 - try {  
268 - await deleteDevice([record.id]);  
269 - createMessage.success('删除成功');  
270 - handleSuccess();  
271 - } catch (e: any) {}  
272 - } else {  
273 - try {  
274 - await deleteDevice(selectedRowKeys);  
275 - createMessage.success('批量删除成功');  
276 - handleSuccess();  
277 - selectedRowKeys.length = 0;  
278 - } catch (e: any) {  
279 - selectedRowKeys.length = 0;  
280 - } finally {  
281 - selectedRowKeys.length = 0;  
282 - } 287 + const { clipboardRef } = useCopyToClipboard();
  288 + const copySN = (snCode: string) => {
  289 + clipboardRef.value = snCode;
  290 + if (unref(clipboardRef)) {
  291 + createMessage.success('复制成功~');
283 } 292 }
284 }; 293 };
285 294
@@ -302,9 +311,10 @@ @@ -302,9 +311,10 @@
302 registerCustomerModal, 311 registerCustomerModal,
303 authBtn, 312 authBtn,
304 role, 313 role,
  314 + copySN,
  315 + hasBatchDelete,
305 handleDeleteOrBatchDelete, 316 handleDeleteOrBatchDelete,
306 - disabled,  
307 - useSelectionChange, 317 + handleReload,
308 }; 318 };
309 }, 319 },
310 }); 320 });