Commit 3f7fc1aaa1f29c6a492d736e32f183c66a729528
Merge branch 'feat_device_access' into 'main_dev'
feat: 新增设备接入信息功能 See merge request yunteng/thingskit-front!1217
Showing
10 changed files
with
639 additions
and
0 deletions
src/api/device/deviceAccess.ts
0 → 100644
1 | +import { defHttp } from '/@/utils/http/axios'; | |
2 | + | |
3 | +enum Api { | |
4 | + DEVICE_PROFILE_ACCESS_INFORMATIION = '/device_profile/access_information', | |
5 | +} | |
6 | + | |
7 | +/** | |
8 | + * 新增设备接入信息 | |
9 | + */ | |
10 | +export const deviceProfileAccessInformation = (params) => { | |
11 | + return defHttp.post<any>({ | |
12 | + url: `${Api.DEVICE_PROFILE_ACCESS_INFORMATIION}`, | |
13 | + params, | |
14 | + }); | |
15 | +}; | |
16 | + | |
17 | +/** | |
18 | + * 获取设备接入信息列表 | |
19 | + */ | |
20 | +export const getDeviceAccessInformationList = (params) => { | |
21 | + return defHttp.get<any>({ | |
22 | + url: Api.DEVICE_PROFILE_ACCESS_INFORMATIION, | |
23 | + params, | |
24 | + }); | |
25 | +}; | |
26 | + | |
27 | +/** | |
28 | + * 删除设备接入信息 | |
29 | + */ | |
30 | +export const deleteDeviceAccessInformation = (params) => { | |
31 | + return defHttp.delete<any>({ | |
32 | + url: Api.DEVICE_PROFILE_ACCESS_INFORMATIION, | |
33 | + params, | |
34 | + }); | |
35 | +}; | ... | ... |
... | ... | @@ -41,6 +41,7 @@ import InputGroup from './components/InputGroup.vue'; |
41 | 41 | import RegisterAddressInput from '/@/views/task/center/components/PollCommandInput/RegisterAddressInput.vue'; |
42 | 42 | import DeviceProfileForm from '/@/components/Form/src/components/DeviceProfileForm/index.vue'; |
43 | 43 | import { Segmented } from './components/Segmented'; |
44 | +import FormInputGroup from './components/FormInputGroup.vue'; | |
44 | 45 | |
45 | 46 | const componentMap = new Map<ComponentType, Component>(); |
46 | 47 | |
... | ... | @@ -89,6 +90,7 @@ componentMap.set('ApiSelectScrollLoad', ApiSelectScrollLoad); |
89 | 90 | componentMap.set('InputGroup', InputGroup); |
90 | 91 | componentMap.set('RegisterAddressInput', RegisterAddressInput); |
91 | 92 | componentMap.set('DeviceProfileForm', DeviceProfileForm); |
93 | +componentMap.set('FormInputGroup', FormInputGroup); | |
92 | 94 | |
93 | 95 | export function add(compName: ComponentType, component: Component) { |
94 | 96 | componentMap.set(compName, component); | ... | ... |
1 | +<template> | |
2 | + <div class="form-input"> | |
3 | + <!-- 简易封装InputGroup --> | |
4 | + <!-- 待完善封装InputGroup --> | |
5 | + <InputGroup compact> | |
6 | + <Input | |
7 | + :placeholder="inputPlaceholder" | |
8 | + v-model:value="inputReactive.inputIp" | |
9 | + @change="emitChange" | |
10 | + style="width: 42%" | |
11 | + :maxlength="255" | |
12 | + /> | |
13 | + <InputNumber | |
14 | + :min="1" | |
15 | + :max="65535" | |
16 | + :placeholder="inputNumberPlaceholder" | |
17 | + v-model:value="inputReactive.inputPort" | |
18 | + @change="emitChange" | |
19 | + /> | |
20 | + </InputGroup> | |
21 | + </div> | |
22 | +</template> | |
23 | +<script lang="ts" setup> | |
24 | + import { PropType, reactive, watch } from 'vue'; | |
25 | + import { InputGroup, Input, InputNumber } from 'ant-design-vue'; | |
26 | + | |
27 | + interface inputReactive { | |
28 | + inputIp: string; | |
29 | + inputPort: number | string | undefined; | |
30 | + } | |
31 | + | |
32 | + const props = defineProps({ | |
33 | + value: Object as PropType<{}>, | |
34 | + inputPlaceholder: { | |
35 | + type: String, | |
36 | + default: '请输入ip', | |
37 | + }, | |
38 | + inputNumberPlaceholder: { | |
39 | + type: String, | |
40 | + default: '端口', | |
41 | + }, | |
42 | + }); | |
43 | + | |
44 | + const emits = defineEmits(['change', 'update:value']); | |
45 | + | |
46 | + const inputReactive = reactive<inputReactive>({ | |
47 | + inputIp: '', | |
48 | + inputPort: undefined, | |
49 | + }); | |
50 | + | |
51 | + watch( | |
52 | + () => props.value, | |
53 | + () => { | |
54 | + setValues(); | |
55 | + }, | |
56 | + { | |
57 | + immediate: true, | |
58 | + } | |
59 | + ); | |
60 | + | |
61 | + function setValues() { | |
62 | + if (props?.value) for (let i in props.value) Reflect.set(inputReactive, i, props.value[i]); | |
63 | + } | |
64 | + | |
65 | + function emitChange() { | |
66 | + emits('change', inputReactive); | |
67 | + emits('update:value', inputReactive); | |
68 | + } | |
69 | +</script> | |
70 | + | |
71 | +<style lang="less" scoped> | |
72 | + .form-input { | |
73 | + :deep .ant-input-number { | |
74 | + width: 29% !important; | |
75 | + } | |
76 | + } | |
77 | +</style> | ... | ... |
... | ... | @@ -208,6 +208,22 @@ export const CameraChannelNoRule: Rule[] = [ |
208 | 208 | }, |
209 | 209 | ]; |
210 | 210 | |
211 | +// 验证ip地址正则 | |
212 | +export const IpRule: Rule[] = [ | |
213 | + { | |
214 | + required: true, | |
215 | + validator: (_, value: string) => { | |
216 | + const ipRegex = | |
217 | + /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; | |
218 | + if (!ipRegex.test(value)) { | |
219 | + return Promise.reject('请输入正确格式的ip'); | |
220 | + } | |
221 | + return Promise.resolve(); | |
222 | + }, | |
223 | + validateTrigger: 'blur', | |
224 | + }, | |
225 | +]; | |
226 | + | |
211 | 227 | export const CameraVideoStreamUrl: Rule[] = [ |
212 | 228 | { |
213 | 229 | required: true, |
... | ... | @@ -423,3 +439,6 @@ export const MediaTypeValidate: Rule[] = [ |
423 | 439 | validateTrigger: 'blur', |
424 | 440 | }, |
425 | 441 | ]; |
442 | + | |
443 | +export const ipRegex = | |
444 | + /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; | ... | ... |
1 | +<template> | |
2 | + <BasicDrawer v-bind="$attrs" @register="registerDrawer" title="设备接入信息详情" width="25%"> | |
3 | + <Description :column="3" size="middle" @register="registeDesc" /> | |
4 | + </BasicDrawer> | |
5 | +</template> | |
6 | +<script lang="ts" setup> | |
7 | + import { detailSchema } from '../index'; | |
8 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | |
9 | + import { Description } from '/@/components/Description/index'; | |
10 | + import { useDescription } from '/@/components/Description'; | |
11 | + | |
12 | + defineEmits(['success', 'register']); | |
13 | + | |
14 | + const [registeDesc, { setDescProps }] = useDescription({ | |
15 | + schema: detailSchema, | |
16 | + column: 2, | |
17 | + layout: 'vertical', | |
18 | + }); | |
19 | + | |
20 | + const [registerDrawer, { setDrawerProps }] = useDrawerInner(async (data) => { | |
21 | + setDrawerProps({ confirmLoading: false }); | |
22 | + const dataValue = { | |
23 | + ...data, | |
24 | + ...data.sipExtend, | |
25 | + }; | |
26 | + setDescProps({ data: dataValue }); | |
27 | + }); | |
28 | +</script> | ... | ... |
1 | +<script setup lang="ts"> | |
2 | + import { computed, unref } from 'vue'; | |
3 | + import { ref } from 'vue'; | |
4 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | |
5 | + import { deleteFormField, schemas } from '../index'; | |
6 | + import { useForm, BasicForm } from '/@/components/Form'; | |
7 | + import { deviceProfileAccessInformation } from '/@/api/device/deviceAccess'; | |
8 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
9 | + import { ipRegex } from '/@/utils/rules'; | |
10 | + | |
11 | + const emit = defineEmits(['handleReload', 'register']); | |
12 | + | |
13 | + const isUpdate = ref<Boolean>(false); | |
14 | + | |
15 | + const getTitle = computed(() => (!unref(isUpdate) ? '新增设备接入信息' : '编辑设备接入信息')); | |
16 | + | |
17 | + const { createMessage } = useMessage(); | |
18 | + | |
19 | + const [registerForm, { getFieldsValue, setFieldsValue, validate }] = useForm({ | |
20 | + labelWidth: 150, | |
21 | + schemas, | |
22 | + actionColOptions: { | |
23 | + span: 14, | |
24 | + }, | |
25 | + showActionButtonGroup: false, | |
26 | + }); | |
27 | + | |
28 | + const recordInfo = ref<Recordable>({}); | |
29 | + | |
30 | + const [register, { closeModal, setModalProps }] = useModalInner(async (data) => { | |
31 | + setModalProps({ confirmLoading: false, loading: true }); | |
32 | + isUpdate.value = data?.isUpdate; | |
33 | + recordInfo.value = data?.record; | |
34 | + if (data?.record) { | |
35 | + const intranetIpAndPort = { | |
36 | + inputIp: data?.record.intranetIp, | |
37 | + inputPort: data?.record.intranetPort, | |
38 | + }; | |
39 | + const outerIpAndPort = { | |
40 | + inputIp: data?.record.outerNetIp, | |
41 | + inputPort: data?.record.outerNetPort, | |
42 | + }; | |
43 | + setFieldsValue(data?.record); | |
44 | + setFieldsValue({ ...data?.record?.sipExtend }); | |
45 | + setFieldsValue({ intranetIpAndPort, outerIpAndPort }); | |
46 | + } | |
47 | + setModalProps({ loading: false }); | |
48 | + }); | |
49 | + | |
50 | + const handleCancel = () => closeModal(); | |
51 | + | |
52 | + const handleOk = async () => { | |
53 | + await validate(); | |
54 | + let values = getFieldsValue(); | |
55 | + if (unref(isUpdate)) { | |
56 | + values = { ...values, id: unref(recordInfo).id }; | |
57 | + } | |
58 | + const { intranetIpAndPort, outerIpAndPort } = values; | |
59 | + values.intranetIp = intranetIpAndPort.inputIp; | |
60 | + values.intranetPort = intranetIpAndPort.inputPort; | |
61 | + values.outerNetIp = outerIpAndPort.inputIp; | |
62 | + values.outerNetPort = outerIpAndPort.inputPort; | |
63 | + if (!ipRegex.test(values.intranetIp)) { | |
64 | + return createMessage.error('请输入正确格式的ip'); | |
65 | + } | |
66 | + if (!ipRegex.test(values.outerNetIp)) { | |
67 | + return createMessage.error('请输入正确格式的ip'); | |
68 | + } | |
69 | + if (!values.intranetPort) { | |
70 | + return createMessage.error('请输入内网端口'); | |
71 | + } | |
72 | + if (!values.outerNetPort) { | |
73 | + return createMessage.error('请输入外网端口'); | |
74 | + } | |
75 | + const sipExtend = { | |
76 | + serverId: values['serverId'], | |
77 | + serverDomain: values['serverDomain'], | |
78 | + serverPassword: values['serverPassword'], | |
79 | + }; | |
80 | + values.sipExtend = sipExtend; | |
81 | + deleteFormField.forEach((deleteItem) => { | |
82 | + Reflect.deleteProperty(values, deleteItem); | |
83 | + }); | |
84 | + await deviceProfileAccessInformation(values); | |
85 | + createMessage.success('操作成功'); | |
86 | + emit('handleReload'); | |
87 | + handleCancel(); | |
88 | + }; | |
89 | +</script> | |
90 | + | |
91 | +<template> | |
92 | + <div> | |
93 | + <BasicModal | |
94 | + v-bind="$attrs" | |
95 | + width="35rem" | |
96 | + :title="getTitle" | |
97 | + @register="register" | |
98 | + @cancel="handleCancel" | |
99 | + @ok="handleOk" | |
100 | + destroyOnClose | |
101 | + > | |
102 | + <div> | |
103 | + <BasicForm @register="registerForm" /> | |
104 | + </div> | |
105 | + </BasicModal> | |
106 | + </div> | |
107 | +</template> | ... | ... |
src/views/device/deviceaccess/index.ts
0 → 100644
1 | +import { DescItem } from '/@/components/Description/src/typing'; | |
2 | +import { BasicColumn, FormSchema } from '/@/components/Table'; | |
3 | + | |
4 | +//设备接入信息权限标识枚举 | |
5 | +export enum DEVICE_ACCESS_PERMISSION_ENUM { | |
6 | + CREATE = 'api:yt:device_profile:access_information:post', | |
7 | + UPDATE = 'api:yt:device_profile:access_information:update', | |
8 | + DELETE = 'api:yt:device_profile:access_information:delete', | |
9 | + GET = 'api:yt:device_profile:access_information:get', | |
10 | +} | |
11 | + | |
12 | +//要删除的表单字段 | |
13 | +export const deleteFormField = [ | |
14 | + 'serverId', | |
15 | + 'serverDomain', | |
16 | + 'serverPassword', | |
17 | + 'intranetIpAndPort', | |
18 | + 'outerIpAndPort', | |
19 | +]; | |
20 | + | |
21 | +//表格字段 | |
22 | +export const columns: BasicColumn[] = [ | |
23 | + { | |
24 | + title: '内网ip', | |
25 | + dataIndex: 'intranetIp', | |
26 | + }, | |
27 | + { | |
28 | + title: '内网端口', | |
29 | + dataIndex: 'intranetPort', | |
30 | + }, | |
31 | + { | |
32 | + title: '外网ip', | |
33 | + dataIndex: 'outerNetIp', | |
34 | + }, | |
35 | + { | |
36 | + title: '外网端口', | |
37 | + dataIndex: 'outerNetPort', | |
38 | + }, | |
39 | + { | |
40 | + title: '接入协议', | |
41 | + dataIndex: 'deviceAgreement', | |
42 | + }, | |
43 | +]; | |
44 | + | |
45 | +//表单查询 | |
46 | +export const searchFormSchema: FormSchema[] = [ | |
47 | + { | |
48 | + field: 'intranetIp', | |
49 | + label: '内网ip', | |
50 | + component: 'Input', | |
51 | + colProps: { span: 6 }, | |
52 | + componentProps: { | |
53 | + maxLength: 255, | |
54 | + placeholder: '请输入内网ip', | |
55 | + }, | |
56 | + }, | |
57 | + { | |
58 | + field: 'outerNetIp', | |
59 | + label: '外网ip', | |
60 | + component: 'Input', | |
61 | + colProps: { span: 6 }, | |
62 | + componentProps: { | |
63 | + maxLength: 255, | |
64 | + placeholder: '请输入外网ip', | |
65 | + }, | |
66 | + }, | |
67 | + { | |
68 | + field: 'deviceAgreement', | |
69 | + label: '接入协议', | |
70 | + component: 'Select', | |
71 | + colProps: { span: 6 }, | |
72 | + componentProps() { | |
73 | + return { | |
74 | + options: [ | |
75 | + { label: '默认', value: 'DEFAULT' }, | |
76 | + { label: 'MQTT', value: 'MQTT' }, | |
77 | + { label: 'CoAP', value: 'COAP' }, | |
78 | + { label: 'TCP', value: 'TCP' }, | |
79 | + { label: 'GBT28181', value: 'GBT28181' }, | |
80 | + ], | |
81 | + getPopupContainer: () => document.body, | |
82 | + placeholder: '请选择接入协议', | |
83 | + }; | |
84 | + }, | |
85 | + }, | |
86 | +]; | |
87 | + | |
88 | +//表单字段 | |
89 | +export const schemas: FormSchema[] = [ | |
90 | + { | |
91 | + field: 'intranetIpAndPort', | |
92 | + label: '内网ip&端口', | |
93 | + component: 'FormInputGroup', | |
94 | + required: true, | |
95 | + componentProps: { | |
96 | + inputPlaceholder: '请输入内网ip', | |
97 | + inputNumberPlaceholder: '内网端口', | |
98 | + }, | |
99 | + colProps: { span: 24 }, | |
100 | + }, | |
101 | + { | |
102 | + field: 'outerIpAndPort', | |
103 | + label: '外网ip&端口', | |
104 | + component: 'FormInputGroup', | |
105 | + required: true, | |
106 | + componentProps: { | |
107 | + inputPlaceholder: '请输入外网ip', | |
108 | + inputNumberPlaceholder: '外网端口', | |
109 | + }, | |
110 | + colProps: { span: 24 }, | |
111 | + }, | |
112 | + { | |
113 | + field: 'deviceAgreement', | |
114 | + component: 'Select', | |
115 | + required: true, | |
116 | + label: '接入协议', | |
117 | + componentProps() { | |
118 | + return { | |
119 | + options: [ | |
120 | + { label: '默认', value: 'DEFAULT' }, | |
121 | + { label: 'MQTT', value: 'MQTT' }, | |
122 | + { label: 'CoAP', value: 'COAP' }, | |
123 | + { label: 'TCP', value: 'TCP' }, | |
124 | + { label: 'GBT28181', value: 'GBT28181' }, | |
125 | + ], | |
126 | + getPopupContainer: () => document.body, | |
127 | + placeholder: '请选择接入协议', | |
128 | + }; | |
129 | + }, | |
130 | + colProps: { span: 19 }, | |
131 | + }, | |
132 | + { | |
133 | + field: 'serverId', | |
134 | + label: '服务器ID', | |
135 | + required: false, | |
136 | + colProps: { span: 19 }, | |
137 | + component: 'Input', | |
138 | + componentProps: { | |
139 | + maxLength: 255, | |
140 | + placeholder: '请输入服务器ID', | |
141 | + }, | |
142 | + ifShow({ values }) { | |
143 | + return values.deviceAgreement === 'GBT28181'; | |
144 | + }, | |
145 | + }, | |
146 | + { | |
147 | + field: 'serverDomain', | |
148 | + label: '服务器域', | |
149 | + required: false, | |
150 | + colProps: { span: 19 }, | |
151 | + component: 'Input', | |
152 | + componentProps: { | |
153 | + maxLength: 255, | |
154 | + placeholder: '请输入服务器域', | |
155 | + }, | |
156 | + ifShow({ values }) { | |
157 | + return values.deviceAgreement === 'GBT28181'; | |
158 | + }, | |
159 | + }, | |
160 | + { | |
161 | + field: 'serverPassword', | |
162 | + label: '密码', | |
163 | + required: false, | |
164 | + colProps: { span: 19 }, | |
165 | + component: 'InputPassword', | |
166 | + componentProps: { | |
167 | + maxLength: 255, | |
168 | + placeholder: '请输入密码', | |
169 | + }, | |
170 | + ifShow({ values }) { | |
171 | + return values.deviceAgreement === 'GBT28181'; | |
172 | + }, | |
173 | + }, | |
174 | +]; | |
175 | + | |
176 | +//详情字段 | |
177 | +export const detailSchema: DescItem[] = [ | |
178 | + { | |
179 | + field: 'intranetIp', | |
180 | + label: '内网ip', | |
181 | + }, | |
182 | + { | |
183 | + field: 'intranetPort', | |
184 | + label: '内网端口', | |
185 | + }, | |
186 | + { | |
187 | + field: 'outerNetIp', | |
188 | + label: '外网ip', | |
189 | + }, | |
190 | + { | |
191 | + field: 'outerNetPort', | |
192 | + label: '外网端口', | |
193 | + }, | |
194 | + { | |
195 | + field: 'deviceAgreement', | |
196 | + label: '接入协议', | |
197 | + }, | |
198 | + { | |
199 | + field: 'serverId', | |
200 | + label: '服务器ID', | |
201 | + }, | |
202 | + { | |
203 | + field: 'serverDomain', | |
204 | + label: '服务器域', | |
205 | + }, | |
206 | + { | |
207 | + field: 'serverPassword', | |
208 | + label: '密码', | |
209 | + }, | |
210 | +]; | ... | ... |
src/views/device/deviceaccess/index.vue
0 → 100644
1 | +<script setup lang="ts" name="deviceAccess"> | |
2 | + import { columns, searchFormSchema, DEVICE_ACCESS_PERMISSION_ENUM } from '.'; | |
3 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | |
4 | + import { Button, Popconfirm } from 'ant-design-vue'; | |
5 | + import { useBatchOperation } from '/@/utils/useBatchOperation'; | |
6 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
7 | + import { Authority } from '/@/components/Authority'; | |
8 | + import { useModal } from '/@/components/Modal'; | |
9 | + import { deviceAccessModal, deviceAccessDetailDrawer } from './components/index'; | |
10 | + import { useDrawer } from '/@/components/Drawer'; | |
11 | + import { USER_INFO_KEY } from '/@/enums/cacheEnum'; | |
12 | + import { getAuthCache } from '/@/utils/auth'; | |
13 | + import { authBtn } from '/@/enums/roleEnum'; | |
14 | + import { | |
15 | + getDeviceAccessInformationList, | |
16 | + deleteDeviceAccessInformation, | |
17 | + } from '/@/api/device/deviceAccess'; | |
18 | + | |
19 | + const [ | |
20 | + registerTable, | |
21 | + { reload, setLoading, getSelectRowKeys, setSelectedRowKeys, getRowSelection }, | |
22 | + ] = useTable({ | |
23 | + title: '设备接入信息列表', | |
24 | + api: getDeviceAccessInformationList, | |
25 | + columns, | |
26 | + beforeFetch: (params) => { | |
27 | + for (let i in params) if (!params[i]) Reflect.deleteProperty(params, i); // 如果没有值,则此字段也不传 | |
28 | + return params; | |
29 | + }, | |
30 | + formConfig: { | |
31 | + labelWidth: 100, | |
32 | + schemas: searchFormSchema, | |
33 | + }, | |
34 | + immediate: true, | |
35 | + useSearchForm: true, | |
36 | + showTableSetting: true, | |
37 | + bordered: true, | |
38 | + showIndexColumn: false, | |
39 | + clickToRowSelect: false, | |
40 | + rowKey: 'id', | |
41 | + actionColumn: { | |
42 | + width: 230, | |
43 | + title: '操作', | |
44 | + slots: { customRender: 'action' }, | |
45 | + fixed: 'right', | |
46 | + }, | |
47 | + rowSelection: { | |
48 | + type: 'checkbox', | |
49 | + }, | |
50 | + }); | |
51 | + | |
52 | + const [registerModal, { openModal }] = useModal(); | |
53 | + | |
54 | + const [registerDetailDrawer, { openDrawer }] = useDrawer(); | |
55 | + | |
56 | + const { createMessage } = useMessage(); | |
57 | + | |
58 | + const { isExistOption } = useBatchOperation(getRowSelection, setSelectedRowKeys); | |
59 | + | |
60 | + const userInfo: Recordable = getAuthCache(USER_INFO_KEY); | |
61 | + | |
62 | + const role: string = userInfo.roles[0]; | |
63 | + | |
64 | + const handleReload = () => { | |
65 | + setSelectedRowKeys([]); | |
66 | + reload(); | |
67 | + }; | |
68 | + | |
69 | + //新增或编辑 | |
70 | + const handleCreateOrEdit = (record) => { | |
71 | + const data = { isUpdate: !record ? false : true, record }; | |
72 | + openModal(true, data); | |
73 | + }; | |
74 | + | |
75 | + const handleDetail = (record?: Recordable) => { | |
76 | + openDrawer(true, record); | |
77 | + }; | |
78 | + | |
79 | + // 删除 | |
80 | + const handleDelete = async (record?: Recordable) => { | |
81 | + let ids: string[] = []; | |
82 | + if (record) { | |
83 | + ids = [record.id]; | |
84 | + } else { | |
85 | + ids = getSelectRowKeys(); | |
86 | + } | |
87 | + try { | |
88 | + setLoading(true); | |
89 | + await deleteDeviceAccessInformation({ ids }); | |
90 | + createMessage.success('删除成功'); | |
91 | + handleReload(); | |
92 | + } catch (error) { | |
93 | + throw error; | |
94 | + } finally { | |
95 | + setLoading(false); | |
96 | + } | |
97 | + }; | |
98 | +</script> | |
99 | +<template> | |
100 | + <div> | |
101 | + <BasicTable style="flex: auto" @register="registerTable"> | |
102 | + <template #toolbar> | |
103 | + <Authority :value="DEVICE_ACCESS_PERMISSION_ENUM.CREATE"> | |
104 | + <Button type="primary" @click="handleCreateOrEdit(null)"> 新增设备接入信息 </Button> | |
105 | + </Authority> | |
106 | + <Authority :value="DEVICE_ACCESS_PERMISSION_ENUM.DELETE"> | |
107 | + <Popconfirm | |
108 | + title="您确定要批量删除数据" | |
109 | + ok-text="确定" | |
110 | + cancel-text="取消" | |
111 | + @confirm="handleDelete()" | |
112 | + > | |
113 | + <a-button color="error" :disabled="!isExistOption"> 批量删除 </a-button> | |
114 | + </Popconfirm> | |
115 | + </Authority> | |
116 | + </template> | |
117 | + <template #action="{ record }"> | |
118 | + <TableAction | |
119 | + :actions="[ | |
120 | + { | |
121 | + label: '详情', | |
122 | + icon: 'ant-design:eye-outlined', | |
123 | + auth: DEVICE_ACCESS_PERMISSION_ENUM.GET, | |
124 | + onClick: handleDetail.bind(null, record), | |
125 | + }, | |
126 | + { | |
127 | + label: '编辑', | |
128 | + auth: DEVICE_ACCESS_PERMISSION_ENUM.UPDATE, | |
129 | + icon: 'clarity:note-edit-line', | |
130 | + ifShow: authBtn(role), | |
131 | + onClick: handleCreateOrEdit.bind(null, record), | |
132 | + }, | |
133 | + { | |
134 | + label: '删除', | |
135 | + auth: DEVICE_ACCESS_PERMISSION_ENUM.DELETE, | |
136 | + icon: 'ant-design:delete-outlined', | |
137 | + ifShow: authBtn(role), | |
138 | + color: 'error', | |
139 | + popConfirm: { | |
140 | + title: '是否确认删除', | |
141 | + confirm: handleDelete.bind(null, record), | |
142 | + }, | |
143 | + }, | |
144 | + ]" | |
145 | + /> | |
146 | + </template> | |
147 | + </BasicTable> | |
148 | + <deviceAccessModal @register="registerModal" @handleReload="handleReload" /> | |
149 | + <deviceAccessDetailDrawer | |
150 | + title="设备接入信息详情" | |
151 | + @register="registerDetailDrawer" | |
152 | + width="40%" | |
153 | + destroy-on-close | |
154 | + /> | |
155 | + </div> | |
156 | +</template> | ... | ... |