Commit 2e18f1e1517bc5ab149dbae8aabed8e76101d66b

Authored by sqy
1 parent 6897f6a0

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

... ... @@ -194,3 +194,9 @@ export const getChildDevicePage = (params: ChildDeviceParams) => {
194 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 23 },
24 24 },
25 25 {
  26 + field: 'sn',
  27 + label: 'SN码',
  28 + component: 'Input',
  29 + required: true,
  30 + slot: 'snCode',
  31 + },
  32 + {
26 33 field: 'deviceType',
27 34 label: '设备类型',
28 35 required: true,
... ...
... ... @@ -12,9 +12,11 @@ export const columns: BasicColumn[] = [
12 12 slots: { customRender: 'img' },
13 13 },
14 14 {
15   - title: '设备名称',
16 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 22 title: '设备类型',
... ...
... ... @@ -18,6 +18,12 @@
18 18 </div>
19 19 </Upload>
20 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 27 <template #deviceAddress>
22 28 <Input disabled v-model:value="positionState.address">
23 29 <template #addonAfter>
... ... @@ -83,7 +89,7 @@
83 89 import { upload } from '/@/api/oss/ossFileUploader';
84 90 import { FileItem } from '/@/components/Upload/src/typing';
85 91 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
86   -
  92 + import { generateSNCode } from '/@/api/device/deviceManager.ts';
87 93 import icon from '/@/assets/images/wz.png';
88 94 import { useDebounceFn } from '@vueuse/core';
89 95 export default defineComponent({
... ... @@ -281,6 +287,14 @@
281 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 299 const handleOk = () => {
286 300 visible.value = false;
... ... @@ -331,6 +345,7 @@
331 345 },
332 346 });
333 347 }
  348 +
334 349 return {
335 350 resetFields,
336 351 positionState,
... ... @@ -355,6 +370,7 @@
355 370 handleSelect,
356 371 dataSource,
357 372 debounceSearch,
  373 + generateSN,
358 374 };
359 375 },
360 376 });
... ...
... ... @@ -6,20 +6,14 @@
6 6 @select="handleSelect"
7 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 10 <template #toolbar>
17 11 <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> 新增设备 </a-button>
18 12 <a-button
19 13 color="error"
20 14 v-if="authBtn(role)"
21 15 @click="handleDeleteOrBatchDelete(null)"
22   - :disabled="disabled"
  16 + :disabled="hasBatchDelete"
23 17 >
24 18 批量删除
25 19 </a-button>
... ... @@ -38,6 +32,31 @@
38 32 "
39 33 />
40 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 60 <template #deviceProfile="{ record }">
42 61 <a-button type="link" class="ml-2" @click="goDeviceProfile(record.deviceProfile.name)">
43 62 {{ record.deviceProfile.name }}
... ... @@ -122,16 +141,16 @@
122 141 </BasicTable>
123 142 <DeviceDetailDrawer @register="registerDetailDrawer" />
124 143 <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleSuccess" />
125   - <CustomerModal @register="registerCustomerModal" @reload="handleSuccess" />
  144 + <CustomerModal @register="registerCustomerModal" @reload="handleReload" />
126 145 </PageWrapper>
127 146 </div>
128 147 </template>
129 148 <script lang="ts">
130   - import { defineComponent, reactive, ref } from 'vue';
  149 + import { defineComponent, reactive, unref } from 'vue';
131 150 import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel';
132 151 import { BasicTable, useTable, TableAction, TableImg } from '/@/components/Table';
133 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 154 import {
136 155 deleteDevice,
137 156 devicePage,
... ... @@ -151,7 +170,9 @@
151 170 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
152 171 import { getAuthCache } from '/@/utils/auth';
153 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 176 export default defineComponent({
156 177 name: 'DeviceManagement',
157 178 components: {
... ... @@ -164,18 +185,30 @@
164 185 DeviceDetailDrawer,
165 186 CustomerModal,
166 187 TableImg,
  188 + Tooltip,
  189 + QuestionCircleOutlined,
  190 + Popover,
167 191 },
168 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 204 const { createMessage } = useMessage();
170   - let selectedRowKeys: any = [];
171   - const disabled = ref(true);
172 205 const go = useGo();
173 206 const searchInfo = reactive<Recordable>({});
174 207 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
175 208 const [registerModal, { openModal }] = useModal();
176 209 const [registerCustomerModal, { openModal: openCustomerModal }] = useModal();
177 210 const [registerDetailDrawer, { openDrawer }] = useDrawer();
178   - const [registerTable, { reload, getSelectRows, getSelectRowKeys }] = useTable({
  211 + const [registerTable, { reload, setSelectedRowKeys }] = useTable({
179 212 title: '设备列表',
180 213 api: devicePage,
181 214 columns,
... ... @@ -190,12 +223,14 @@
190 223 showIndexColumn: false,
191 224 rowKey: 'id',
192 225 searchInfo: searchInfo,
  226 + clickToRowSelect: false,
193 227 actionColumn: {
194 228 width: 300,
195 229 title: '操作',
196 230 slots: { customRender: 'action' },
197 231 fixed: 'right',
198 232 },
  233 + ...selectionOptions,
199 234 });
200 235
201 236 const userInfo: any = getAuthCache(USER_INFO_KEY);
... ... @@ -210,10 +245,15 @@
210 245 function handleDispatchCustomer(record: Recordable) {
211 246 openCustomerModal(true, record);
212 247 }
  248 + function handleReload() {
  249 + setSelectedRowKeys([]);
  250 + resetSelectedRowKeys();
  251 + handleSuccess();
  252 + }
213 253 // 取消分配客户
214 254 async function handleCancelDispatchCustomer(record: Recordable) {
215 255 await cancelDispatchCustomer(record);
216   - handleSuccess();
  256 + handleReload();
217 257 }
218 258
219 259 function handleDetail(record: Recordable) {
... ... @@ -244,42 +284,11 @@
244 284 function goDeviceProfile(e) {
245 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 311 registerCustomerModal,
303 312 authBtn,
304 313 role,
  314 + copySN,
  315 + hasBatchDelete,
305 316 handleDeleteOrBatchDelete,
306   - disabled,
307   - useSelectionChange,
  317 + handleReload,
308 318 };
309 319 },
310 320 });
... ...