Showing
17 changed files
with
735 additions
and
275 deletions
... | ... | @@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = / |
6 | 6 | |
7 | 7 | # Cross-domain proxy, you can configure multiple |
8 | 8 | # Please note that no line breaks |
9 | -VITE_PROXY = [["/api","http://192.168.10.120:8082/api"],["/upload","http://192.168.10.120:3300/upload"]] | |
9 | +VITE_PROXY = [["/api","http://192.168.10.116:8082/api"],["/upload","http://192.168.10.116:3300/upload"]] | |
10 | 10 | # VITE_PROXY=[["/api","https://vvbin.cn/test"]] |
11 | 11 | |
12 | 12 | # Delete console | ... | ... |
... | ... | @@ -15,6 +15,8 @@ enum DeviceManagerApi { |
15 | 15 | * 设备配置URL |
16 | 16 | */ |
17 | 17 | DEVICE_PROFILE_URL = '/deviceProfile', |
18 | + | |
19 | + DEVICE_PROFILE_URL_ME = '/deviceProfile/me', | |
18 | 20 | } |
19 | 21 | |
20 | 22 | export const devicePage = (params: DeviceQueryParam) => { |
... | ... | @@ -59,3 +61,20 @@ export const deleteDevice = (ids: string[]) => { |
59 | 61 | }, |
60 | 62 | }); |
61 | 63 | }; |
64 | + | |
65 | +/** | |
66 | + * 查询设备配置 | |
67 | + * @param params pageSize page name | |
68 | + */ | |
69 | +export const deviceProfile = () => { | |
70 | + return defHttp.get({ | |
71 | + url: DeviceManagerApi.DEVICE_PROFILE_URL_ME, | |
72 | + }); | |
73 | +}; | |
74 | + | |
75 | +export const createOrEditDevice = (data) => { | |
76 | + return defHttp.post({ | |
77 | + url: DeviceManagerApi.DEVICE_URL, | |
78 | + data, | |
79 | + }); | |
80 | +}; | ... | ... |
... | ... | @@ -4,8 +4,9 @@ |
4 | 4 | width="55rem" |
5 | 5 | @register="register" |
6 | 6 | :title="getTitle" |
7 | - @visible-change="handleVisibleChange" | |
8 | 7 | @cancel="handleCancel" |
8 | + @ok="handleOk" | |
9 | + centered | |
9 | 10 | > |
10 | 11 | <div class="step-form-form"> |
11 | 12 | <a-steps :current="current"> |
... | ... | @@ -14,8 +15,9 @@ |
14 | 15 | </a-steps> |
15 | 16 | </div> |
16 | 17 | <div class="mt-5"> |
17 | - <DeviceStep1 @next="handleStep1Next" v-show="current === 0" /> | |
18 | + <DeviceStep1 @next="handleStep1Next" v-show="current === 0" ref="DeviceStep1Ref" /> | |
18 | 19 | <DeviceStep2 |
20 | + ref="DeviceStep2Ref" | |
19 | 21 | @prev="handleStepPrev" |
20 | 22 | @next="handleStep2Next" |
21 | 23 | v-show="current === 1" |
... | ... | @@ -25,11 +27,13 @@ |
25 | 27 | </BasicModal> |
26 | 28 | </template> |
27 | 29 | <script lang="ts"> |
28 | - import { defineComponent, ref, nextTick, computed, unref, reactive, toRefs } from 'vue'; | |
30 | + import { defineComponent, ref, computed, unref, reactive, toRefs } from 'vue'; | |
29 | 31 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
32 | + import { createOrEditDevice } from '/@/api/device/deviceManager'; | |
30 | 33 | import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; |
31 | 34 | import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; |
32 | 35 | import { Steps } from 'ant-design-vue'; |
36 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
33 | 37 | export default defineComponent({ |
34 | 38 | name: 'DeviceModal', |
35 | 39 | components: { |
... | ... | @@ -42,72 +46,87 @@ |
42 | 46 | props: { |
43 | 47 | userData: { type: Object }, |
44 | 48 | }, |
45 | - setup(props) { | |
49 | + setup(_, { emit }) { | |
50 | + const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); | |
51 | + const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); | |
52 | + const { createMessage } = useMessage(); | |
46 | 53 | const state = reactive({ |
47 | 54 | initStep2: false, |
48 | 55 | }); |
49 | 56 | const current = ref(0); |
50 | 57 | const isUpdate = ref(true); |
51 | - const modelRef = ref({}); | |
52 | 58 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); |
53 | - | |
54 | - const [register] = useModalInner((data) => { | |
59 | + // 所有参数 | |
60 | + let stepState = ref(); | |
61 | + // 编辑回显 | |
62 | + const [register, { closeModal }] = useModalInner((data) => { | |
63 | + if (data.isUpdate) { | |
64 | + DeviceStep1Ref.value?.parentSetFieldsValue(data.record); | |
65 | + DeviceStep1Ref.value?.parentSetFieldsValue({ | |
66 | + profile: data.record.deviceProfile.name, | |
67 | + remark: data.record.deviceInfo.description, | |
68 | + profileId: data.record.profileId, | |
69 | + }); | |
70 | + } | |
55 | 71 | isUpdate.value = !!data?.isUpdate; |
56 | - data && onDataReceive(data); | |
57 | 72 | }); |
58 | 73 | |
74 | + // 上一步 | |
59 | 75 | function handleStepPrev() { |
60 | 76 | current.value--; |
61 | 77 | } |
78 | + // 下一步 | |
62 | 79 | function handleStep1Next(step1Values: any) { |
63 | 80 | current.value++; |
64 | 81 | state.initStep2 = true; |
65 | - console.log(step1Values); | |
82 | + stepState = { ...step1Values }; | |
66 | 83 | } |
84 | + // | |
67 | 85 | function handleStep2Next(step2Values: any) { |
68 | - current.value++; | |
69 | - console.log(step2Values); | |
70 | - } | |
71 | - function handleRedo() { | |
72 | - current.value = 0; | |
73 | - state.initStep2 = false; | |
86 | + stepState = { ...stepState, ...step2Values }; | |
74 | 87 | } |
75 | 88 | function handleCancel() { |
76 | - console.log('关闭了弹框'); | |
77 | - } | |
78 | - | |
79 | - function onDataReceive(data) { | |
80 | - console.log('Data Received', data); | |
81 | - // 方式1; | |
82 | - // setFieldsValue({ | |
83 | - // field2: data.data, | |
84 | - // field1: data.info, | |
85 | - // }); | |
86 | - | |
87 | - // // 方式2 | |
88 | - modelRef.value = { field2: data.data, field1: data.info }; | |
89 | - | |
90 | - // setProps({ | |
91 | - // model:{ field2: data.data, field1: data.info } | |
92 | - // }) | |
89 | + current.value = 0; | |
90 | + DeviceStep1Ref?.value?.resetFields(); | |
91 | + DeviceStep2Ref?.value?.resetFields(); | |
93 | 92 | } |
93 | + // 提交 | |
94 | + async function handleOk() { | |
95 | + if (current.value === 0) { | |
96 | + // 验证 | |
97 | + const valid = await DeviceStep1Ref.value?.parentValidate(); | |
98 | + if (!valid) return; | |
94 | 99 | |
95 | - function handleVisibleChange(v) { | |
96 | - v && props.userData && nextTick(() => onDataReceive(props.userData)); | |
100 | + stepState.value = DeviceStep1Ref?.value?.parentGetFieldsValue(); | |
101 | + handleCancel(); | |
102 | + closeModal(); | |
103 | + } else { | |
104 | + if (!DeviceStep2Ref?.value?.creaentialsPassword.isCreaentials) { | |
105 | + const valid = await DeviceStep2Ref?.value?.validate(); | |
106 | + if (!valid) return; | |
107 | + // 第二页验证通过情况 | |
108 | + handleCancel(); | |
109 | + closeModal(); | |
110 | + } | |
111 | + } | |
112 | + // 验证成功 --掉新增或者编辑接口 | |
113 | + const msg = computed(() => (stepState.value.id ? '更新设备成功' : '新增设备成功')); | |
114 | + await createOrEditDevice(stepState.value); | |
115 | + createMessage.success(msg.value); | |
116 | + emit('reload'); | |
97 | 117 | } |
98 | - | |
99 | 118 | return { |
100 | 119 | register, |
101 | - model: modelRef, | |
102 | 120 | getTitle, |
103 | - handleVisibleChange, | |
104 | 121 | current, |
122 | + DeviceStep1Ref, | |
123 | + DeviceStep2Ref, | |
105 | 124 | ...toRefs(state), |
106 | 125 | handleStepPrev, |
107 | 126 | handleStep1Next, |
108 | 127 | handleStep2Next, |
109 | 128 | handleCancel, |
110 | - handleRedo, | |
129 | + handleOk, | |
111 | 130 | }; |
112 | 131 | }, |
113 | 132 | }); | ... | ... |
1 | 1 | import { BasicColumn } from '/@/components/Table'; |
2 | 2 | import { FormSchema } from '/@/components/Table'; |
3 | -import { findDictItemByCode } from '/@/api/system/dict'; | |
4 | 3 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; |
4 | +// 表格列数据 | |
5 | 5 | export const columns: BasicColumn[] = [ |
6 | 6 | { |
7 | 7 | title: '设备名称', |
... | ... | @@ -45,6 +45,7 @@ export const columns: BasicColumn[] = [ |
45 | 45 | }, |
46 | 46 | ]; |
47 | 47 | |
48 | +// 查询字段 | |
48 | 49 | export const searchFormSchema: FormSchema[] = [ |
49 | 50 | { |
50 | 51 | field: 'deviceType', |
... | ... | @@ -79,48 +80,3 @@ export const searchFormSchema: FormSchema[] = [ |
79 | 80 | colProps: { span: 8 }, |
80 | 81 | }, |
81 | 82 | ]; |
82 | - | |
83 | -export const formSchema: FormSchema[] = [ | |
84 | - { | |
85 | - field: 'icon', | |
86 | - label: '设备图片: ', | |
87 | - slot: 'iconSelect', | |
88 | - component: 'Input', | |
89 | - }, | |
90 | - { | |
91 | - field: 'name', | |
92 | - label: '设备名称', | |
93 | - required: true, | |
94 | - component: 'Input', | |
95 | - componentProps: { | |
96 | - maxLength: 30, | |
97 | - }, | |
98 | - }, | |
99 | - { | |
100 | - field: 'deviceType', | |
101 | - label: '设备类型', | |
102 | - required: true, | |
103 | - component: 'ApiSelect', | |
104 | - componentProps: { | |
105 | - api: findDictItemByCode, | |
106 | - params: { | |
107 | - dictCode: 'device_type', | |
108 | - }, | |
109 | - labelField: 'itemText', | |
110 | - valueField: 'itemValue', | |
111 | - }, | |
112 | - }, | |
113 | - { | |
114 | - field: 'label', | |
115 | - label: '设备标签', | |
116 | - component: 'Input', | |
117 | - componentProps: { | |
118 | - maxLength: 255, | |
119 | - }, | |
120 | - }, | |
121 | - { | |
122 | - label: '备注', | |
123 | - field: 'remark', | |
124 | - component: 'InputTextArea', | |
125 | - }, | |
126 | -]; | ... | ... |
... | ... | @@ -65,16 +65,13 @@ |
65 | 65 | /> |
66 | 66 | </template> |
67 | 67 | </BasicTable> |
68 | - <!-- <ConfigDrawer @register="registerDrawer" @success="handleSuccess" /> --> | |
69 | - <DeviceModal @register="registerModal" @success="handleSuccess" /> | |
68 | + <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" /> | |
70 | 69 | </PageWrapper> |
71 | 70 | </template> |
72 | 71 | <script lang="ts"> |
73 | 72 | import { defineComponent, reactive } from 'vue'; |
74 | 73 | import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
75 | 74 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
76 | - // import { useDrawer } from '/@/components/Drawer'; | |
77 | - // import ConfigDrawer from './DeviceDrawer.vue'; | |
78 | 75 | import { columns, searchFormSchema } from './device.data'; |
79 | 76 | import { Tag } from 'ant-design-vue'; |
80 | 77 | import { useMessage } from '/@/hooks/web/useMessage'; |
... | ... | @@ -90,17 +87,16 @@ |
90 | 87 | name: 'DeviceManagement', |
91 | 88 | components: { |
92 | 89 | BasicTable, |
93 | - // ConfigDrawer, | |
94 | 90 | PageWrapper, |
95 | 91 | TableAction, |
96 | 92 | OrganizationIdTree, |
97 | 93 | Tag, |
98 | 94 | DeviceModal, |
99 | 95 | }, |
100 | - setup() { | |
101 | - // const [registerDrawer, { openDrawer }] = useDrawer(); | |
96 | + setup(_) { | |
102 | 97 | const { createMessage } = useMessage(); |
103 | 98 | const go = useGo(); |
99 | + | |
104 | 100 | const searchInfo = reactive<Recordable>({}); |
105 | 101 | const [registerModal, { openModal }] = useModal(); |
106 | 102 | const [registerTable, { reload }] = useTable({ |
... | ... | @@ -124,6 +120,9 @@ |
124 | 120 | fixed: undefined, |
125 | 121 | }, |
126 | 122 | }); |
123 | + const handleReload = () => { | |
124 | + handleSuccess(); | |
125 | + }; | |
127 | 126 | |
128 | 127 | function handleCreate() { |
129 | 128 | openModal(true, { |
... | ... | @@ -158,7 +157,6 @@ |
158 | 157 | } |
159 | 158 | return { |
160 | 159 | registerTable, |
161 | - // registerDrawer, | |
162 | 160 | handleCreate, |
163 | 161 | handleEdit, |
164 | 162 | handleDelete, |
... | ... | @@ -169,6 +167,7 @@ |
169 | 167 | handleSelect, |
170 | 168 | searchInfo, |
171 | 169 | registerModal, |
170 | + handleReload, | |
172 | 171 | }; |
173 | 172 | }, |
174 | 173 | }); | ... | ... |
... | ... | @@ -7,7 +7,7 @@ |
7 | 7 | width="500px" |
8 | 8 | @ok="handleSubmit" |
9 | 9 | > |
10 | - <BasicForm @register="registerForm" /> | |
10 | + <BasicForm @register="registerForm"/> | |
11 | 11 | </BasicDrawer> |
12 | 12 | </template> |
13 | 13 | <script lang="ts"> |
... | ... | @@ -15,8 +15,8 @@ |
15 | 15 | import { BasicForm, useForm } from '/@/components/Form'; |
16 | 16 | import { formSchema } from './device.profile.data'; |
17 | 17 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
18 | - import { saveOrEditMessageConfig } from '/@/api/message/config'; | |
19 | - import { useMessage } from '/@/hooks/web/useMessage'; | |
18 | + import { saveOrEditMessageConfig } from "/@/api/message/config"; | |
19 | + import { useMessage } from "/@/hooks/web/useMessage"; | |
20 | 20 | |
21 | 21 | export default defineComponent({ |
22 | 22 | name: 'DeviceProfileDrawer', |
... | ... | @@ -25,7 +25,7 @@ |
25 | 25 | setup(_, { emit }) { |
26 | 26 | const isUpdate = ref(true); |
27 | 27 | |
28 | - const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({ | |
28 | + const [registerForm, { validate,setFieldsValue,resetFields }] = useForm({ | |
29 | 29 | labelWidth: 120, |
30 | 30 | schemas: formSchema, |
31 | 31 | showActionButtonGroup: false, |
... | ... | @@ -37,8 +37,8 @@ |
37 | 37 | isUpdate.value = !!data?.isUpdate; |
38 | 38 | if (unref(isUpdate)) { |
39 | 39 | const config = data.record.config; |
40 | - for (const key in config) { | |
41 | - Reflect.set(data.record, key + '', config[key]); | |
40 | + for (const key in config){ | |
41 | + Reflect.set(data.record, key+'', config[key]); | |
42 | 42 | } |
43 | 43 | await setFieldsValue({ |
44 | 44 | ...data.record, |
... | ... | @@ -53,27 +53,27 @@ |
53 | 53 | const values = await validate(); |
54 | 54 | const { createMessage } = useMessage(); |
55 | 55 | setDrawerProps({ confirmLoading: true }); |
56 | - let config = {}; | |
57 | - if (values.messageType === 'PHONE_MESSAGE') { | |
58 | - config = { | |
59 | - accessKeyId: values.accessKeyId, | |
60 | - accessKeySecret: values.accessKeySecret, | |
61 | - }; | |
62 | - } else if (values.messageType === 'EMAIL_MESSAGE') { | |
63 | - config = { | |
64 | - host: values.host, | |
65 | - port: values.port, | |
66 | - username: values.username, | |
67 | - password: values.password, | |
68 | - }; | |
56 | + let config={}; | |
57 | + if(values.messageType === 'PHONE_MESSAGE'){ | |
58 | + config ={ | |
59 | + "accessKeyId":values.accessKeyId, | |
60 | + "accessKeySecret":values.accessKeySecret, | |
61 | + } | |
62 | + }else if(values.messageType === 'EMAIL_MESSAGE'){ | |
63 | + config ={ | |
64 | + "host":values.host, | |
65 | + "port":values.port, | |
66 | + "username":values.username, | |
67 | + "password":values.password, | |
68 | + } | |
69 | 69 | } |
70 | 70 | Reflect.set(values, 'config', config); |
71 | - let saveMessage = '添加成功'; | |
72 | - let updateMessage = '修改成功'; | |
71 | + let saveMessage = "添加成功"; | |
72 | + let updateMessage = "修改成功"; | |
73 | 73 | await saveOrEditMessageConfig(values, unref(isUpdate)); |
74 | 74 | closeDrawer(); |
75 | 75 | emit('success'); |
76 | - createMessage.success(unref(isUpdate) ? updateMessage : saveMessage); | |
76 | + createMessage.success(unref(isUpdate)?updateMessage:saveMessage); | |
77 | 77 | } finally { |
78 | 78 | setDrawerProps({ confirmLoading: false }); |
79 | 79 | } | ... | ... |
1 | +<template> | |
2 | + <BasicModal | |
3 | + v-bind="$attrs" | |
4 | + width="55rem" | |
5 | + @register="register" | |
6 | + :title=getTitle | |
7 | + @visible-change="handleVisibleChange" | |
8 | + > | |
9 | + <div class="step-form-form"> | |
10 | + <a-steps :current="current"> | |
11 | + <a-step title="设备配置" /> | |
12 | + <a-step title="传输配置" /> | |
13 | + <a-step title="告警配置" /> | |
14 | + </a-steps> | |
15 | + </div> | |
16 | + <div class="mt-5"> | |
17 | + <DeviceProfileStep1 @next="handleStep1Next" v-show="current === 0" /> | |
18 | + <DeviceProfileStep2 | |
19 | + @prev="handleStepPrev" | |
20 | + @next="handleStep2Next" | |
21 | + v-show="current === 1" | |
22 | + v-if="initStep2" | |
23 | + /> | |
24 | + <DeviceProfileStep3 v-show="current === 2" @redo="handleRedo" v-if="initStep3" /> | |
25 | + </div> | |
26 | + </BasicModal> | |
27 | +</template> | |
28 | +<script lang="ts"> | |
29 | + import { defineComponent, ref, nextTick, computed, unref, reactive, toRefs} from 'vue'; | |
30 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | |
31 | + import { BasicForm, FormSchema, useForm } from '/@/components/Form'; | |
32 | + import DeviceProfileStep1 from "/@/views/device/profile/step/DeviceProfileStep1.vue"; | |
33 | + import DeviceProfileStep2 from "/@/views/device/profile/step/DeviceProfileStep2.vue"; | |
34 | + import DeviceProfileStep3 from "/@/views/device/profile/step/DeviceProfileStep3.vue"; | |
35 | + import { Steps } from "ant-design-vue"; | |
36 | + const schemas: FormSchema[] = [ | |
37 | + { | |
38 | + field: 'field1', | |
39 | + component: 'Input', | |
40 | + label: '字段1', | |
41 | + colProps: { | |
42 | + span: 24, | |
43 | + }, | |
44 | + defaultValue: '111', | |
45 | + }, | |
46 | + { | |
47 | + field: 'field2', | |
48 | + component: 'Input', | |
49 | + label: '字段2', | |
50 | + colProps: { | |
51 | + span: 24, | |
52 | + }, | |
53 | + }, | |
54 | + ]; | |
55 | + export default defineComponent({ | |
56 | + name:'DeviceModal', | |
57 | + components: { BasicModal, BasicForm, DeviceProfileStep1, DeviceProfileStep2, DeviceProfileStep3, | |
58 | + [Steps.name]: Steps, | |
59 | + [Steps.Step.name]: Steps.Step, }, | |
60 | + props: { | |
61 | + userData: { type: Object }, | |
62 | + }, | |
63 | + setup(props) { | |
64 | + const state = reactive({ | |
65 | + initStep2: false, | |
66 | + initStep3: false, | |
67 | + }); | |
68 | + const current = ref(0); | |
69 | + const isUpdate = ref(true); | |
70 | + const modelRef = ref({}); | |
71 | + const getTitle = computed(() => (!unref(isUpdate) ? '新增设备配置' : '编辑设备配置')); | |
72 | + const [ | |
73 | + registerForm, | |
74 | + { | |
75 | + // setFieldsValue, | |
76 | + // setProps | |
77 | + }, | |
78 | + ] = useForm({ | |
79 | + labelWidth: 120, | |
80 | + schemas, | |
81 | + showActionButtonGroup: false, | |
82 | + actionColOptions: { | |
83 | + span: 24, | |
84 | + }, | |
85 | + }); | |
86 | + | |
87 | + const [register] = useModalInner((data) => { | |
88 | + isUpdate.value = !!data?.isUpdate; | |
89 | + data && onDataReceive(data); | |
90 | + }); | |
91 | + | |
92 | + function handleStepPrev() { | |
93 | + current.value--; | |
94 | + } | |
95 | + function handleStep1Next(step1Values: any) { | |
96 | + current.value++; | |
97 | + state.initStep2 = true; | |
98 | + console.log(step1Values); | |
99 | + } | |
100 | + function handleStep2Next(step2Values: any) { | |
101 | + current.value++; | |
102 | + state.initStep3 = true; | |
103 | + console.log(step2Values); | |
104 | + } | |
105 | + function handleRedo() { | |
106 | + current.value = 0; | |
107 | + state.initStep2 = false; | |
108 | + state.initStep3 = false; | |
109 | + } | |
110 | + | |
111 | + | |
112 | + function onDataReceive(data) { | |
113 | + console.log('Data Received', data); | |
114 | + // 方式1; | |
115 | + // setFieldsValue({ | |
116 | + // field2: data.data, | |
117 | + // field1: data.info, | |
118 | + // }); | |
119 | + | |
120 | + // // 方式2 | |
121 | + modelRef.value = { field2: data.data, field1: data.info }; | |
122 | + | |
123 | + // setProps({ | |
124 | + // model:{ field2: data.data, field1: data.info } | |
125 | + // }) | |
126 | + } | |
127 | + | |
128 | + function handleVisibleChange(v) { | |
129 | + v && props.userData && nextTick(() => onDataReceive(props.userData)); | |
130 | + } | |
131 | + | |
132 | + return { register, schemas, registerForm, model: modelRef, getTitle,handleVisibleChange, | |
133 | + current, ...toRefs(state), handleStepPrev, handleStep1Next, handleStep2Next, handleRedo}; | |
134 | + }, | |
135 | + }); | |
136 | +</script> | ... | ... |
... | ... | @@ -8,40 +8,40 @@ |
8 | 8 | <TableAction |
9 | 9 | :actions="[ |
10 | 10 | { |
11 | - label: '编辑', | |
11 | + label:'编辑', | |
12 | 12 | icon: 'clarity:note-edit-line', |
13 | 13 | onClick: handleEdit.bind(null, record), |
14 | 14 | }, |
15 | 15 | { |
16 | - label: '删除', | |
16 | + label:'删除', | |
17 | 17 | icon: 'ant-design:delete-outlined', |
18 | 18 | color: 'error', |
19 | 19 | popConfirm: { |
20 | 20 | title: '是否确认删除', |
21 | 21 | confirm: handleDelete.bind(null, record), |
22 | - }, | |
22 | + } | |
23 | 23 | }, |
24 | 24 | ]" |
25 | 25 | /> |
26 | 26 | </template> |
27 | 27 | </BasicTable> |
28 | - <DeviceProfileDrawer @register="registerDrawer" @success="handleSuccess" /> | |
28 | + <DeviceProfileModal @register="registerModal" @success="handleSuccess"/> | |
29 | 29 | </div> |
30 | 30 | </template> |
31 | 31 | <script lang="ts"> |
32 | 32 | import { defineComponent } from 'vue'; |
33 | 33 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
34 | - import { useDrawer } from '/@/components/Drawer'; | |
35 | - import DeviceProfileDrawer from './DeviceProfile.vue'; | |
36 | 34 | import { columns, searchFormSchema } from './device.profile.data'; |
37 | - import { useMessage } from '/@/hooks/web/useMessage'; | |
38 | - import { deviceProfilePage, deleteDeviceProfile } from '/@/api/device/deviceManager'; | |
35 | + import { useMessage } from "/@/hooks/web/useMessage"; | |
36 | + import { deviceProfilePage, deleteDeviceProfile } from "/@/api/device/deviceManager"; | |
37 | + import { useModal } from "/@/components/Modal"; | |
38 | + import DeviceProfileModal from "/@/views/device/profile/DeviceProfileModal.vue"; | |
39 | 39 | export default defineComponent({ |
40 | 40 | name: 'DeviceProfileManagement', |
41 | - components: { BasicTable, DeviceProfileDrawer, TableAction }, | |
41 | + components: { BasicTable, DeviceProfileModal, TableAction}, | |
42 | 42 | setup() { |
43 | - const [registerDrawer, { openDrawer }] = useDrawer(); | |
44 | - const { createMessage } = useMessage(); | |
43 | + const {createMessage} = useMessage(); | |
44 | + const [registerModal, { openModal }] = useModal(); | |
45 | 45 | const [registerTable, { reload }] = useTable({ |
46 | 46 | title: '设备配置列表', |
47 | 47 | api: deviceProfilePage, |
... | ... | @@ -63,13 +63,13 @@ |
63 | 63 | }); |
64 | 64 | |
65 | 65 | function handleCreate() { |
66 | - openDrawer(true, { | |
66 | + openModal(true, { | |
67 | 67 | isUpdate: false, |
68 | 68 | }); |
69 | 69 | } |
70 | 70 | |
71 | 71 | function handleEdit(record: Recordable) { |
72 | - openDrawer(true, { | |
72 | + openModal(true, { | |
73 | 73 | record, |
74 | 74 | isUpdate: true, |
75 | 75 | }); |
... | ... | @@ -77,9 +77,9 @@ |
77 | 77 | |
78 | 78 | function handleDelete(record: Recordable) { |
79 | 79 | let ids = [record.id]; |
80 | - deleteDeviceProfile(ids).then(() => { | |
81 | - createMessage.success('删除设备配置成功'); | |
82 | - handleSuccess(); | |
80 | + deleteDeviceProfile(ids).then(()=>{ | |
81 | + createMessage.success("删除设备配置成功") | |
82 | + handleSuccess() | |
83 | 83 | }); |
84 | 84 | } |
85 | 85 | |
... | ... | @@ -88,11 +88,11 @@ |
88 | 88 | } |
89 | 89 | return { |
90 | 90 | registerTable, |
91 | - registerDrawer, | |
92 | 91 | handleCreate, |
93 | 92 | handleEdit, |
94 | 93 | handleDelete, |
95 | 94 | handleSuccess, |
95 | + registerModal, | |
96 | 96 | }; |
97 | 97 | }, |
98 | 98 | }); | ... | ... |
1 | +<template> | |
2 | + <div class="step1"> | |
3 | + <div class="step1-form"> | |
4 | + <BasicForm @register="register"> </BasicForm> | |
5 | + </div> | |
6 | + </div> | |
7 | +</template> | |
8 | +<script lang="ts"> | |
9 | + import { defineComponent, ref } from 'vue'; | |
10 | + import { BasicForm, useForm } from '/@/components/Form'; | |
11 | + import { step1Schemas } from './data'; | |
12 | + import { Select, Input, Divider } from 'ant-design-vue'; | |
13 | + export default defineComponent({ | |
14 | + components: { | |
15 | + BasicForm, | |
16 | + [Select.name]: Select, | |
17 | + ASelectOption: Select.Option, | |
18 | + [Input.name]: Input, | |
19 | + [Input.Group.name]: Input.Group, | |
20 | + [Divider.name]: Divider, | |
21 | + }, | |
22 | + emits: ['next'], | |
23 | + setup(_, { emit }) { | |
24 | + const devicePic = ref(''); | |
25 | + const [register, { validate }] = useForm({ | |
26 | + labelWidth: 100, | |
27 | + schemas: step1Schemas, | |
28 | + actionColOptions: { | |
29 | + span: 14, | |
30 | + }, | |
31 | + showResetButton: false, | |
32 | + submitButtonOptions: { | |
33 | + text: '下一步', | |
34 | + }, | |
35 | + submitFunc: customSubmitFunc, | |
36 | + }); | |
37 | + | |
38 | + async function customSubmitFunc() { | |
39 | + try { | |
40 | + const values = await validate(); | |
41 | + emit('next', values); | |
42 | + } catch (error) {} | |
43 | + } | |
44 | + return { register, devicePic }; | |
45 | + }, | |
46 | + }); | |
47 | +</script> | |
48 | +<style lang="less" scoped> | |
49 | + .step1 { | |
50 | + &-form { | |
51 | + width: 450px; | |
52 | + margin: 0 auto; | |
53 | + } | |
54 | + | |
55 | + h3 { | |
56 | + margin: 0 0 12px; | |
57 | + font-size: 16px; | |
58 | + line-height: 32px; | |
59 | + color: @text-color; | |
60 | + } | |
61 | + | |
62 | + h4 { | |
63 | + margin: 0 0 4px; | |
64 | + font-size: 14px; | |
65 | + line-height: 22px; | |
66 | + color: @text-color; | |
67 | + } | |
68 | + | |
69 | + p { | |
70 | + color: @text-color; | |
71 | + } | |
72 | + } | |
73 | + | |
74 | + .pay-select { | |
75 | + width: 20%; | |
76 | + } | |
77 | + | |
78 | + .pay-input { | |
79 | + width: 70%; | |
80 | + } | |
81 | +</style> | ... | ... |
1 | +<template> | |
2 | + <div class="step2"> | |
3 | + <BasicForm @register="register" /> | |
4 | + </div> | |
5 | +</template> | |
6 | +<script lang="ts"> | |
7 | + import { defineComponent } from 'vue'; | |
8 | + import { BasicForm, useForm } from '/@/components/Form'; | |
9 | + import { step2Schemas } from './data'; | |
10 | + import { Alert, Divider, Descriptions } from 'ant-design-vue'; | |
11 | + | |
12 | + export default defineComponent({ | |
13 | + components: { | |
14 | + BasicForm, | |
15 | + [Alert.name]: Alert, | |
16 | + [Divider.name]: Divider, | |
17 | + [Descriptions.name]: Descriptions, | |
18 | + [Descriptions.Item.name]: Descriptions.Item, | |
19 | + }, | |
20 | + emits: ['next', 'prev'], | |
21 | + setup(_, { emit }) { | |
22 | + const [register, { validate}] = useForm({ | |
23 | + labelWidth: 80, | |
24 | + schemas: step2Schemas, | |
25 | + actionColOptions: { | |
26 | + span: 14, | |
27 | + }, | |
28 | + resetButtonOptions: { | |
29 | + text: '上一步', | |
30 | + }, | |
31 | + submitButtonOptions: { | |
32 | + text: '下一步', | |
33 | + }, | |
34 | + resetFunc: customResetFunc, | |
35 | + submitFunc: customSubmitFunc, | |
36 | + }); | |
37 | + | |
38 | + async function customResetFunc() { | |
39 | + emit('prev'); | |
40 | + } | |
41 | + | |
42 | + async function customSubmitFunc() { | |
43 | + try { | |
44 | + const values = await validate(); | |
45 | + emit('next', values); | |
46 | + } catch (error) {} | |
47 | + } | |
48 | + | |
49 | + return { register }; | |
50 | + }, | |
51 | + }); | |
52 | +</script> | |
53 | +<style lang="less" scoped> | |
54 | + .step2 { | |
55 | + width: 450px; | |
56 | + margin: 0 auto; | |
57 | + } | |
58 | +</style> | ... | ... |
1 | +<template> | |
2 | + <div class="step2"> | |
3 | + <BasicForm @register="register" /> | |
4 | + </div> | |
5 | +</template> | |
6 | +<script lang="ts"> | |
7 | +import { defineComponent } from 'vue'; | |
8 | +import { BasicForm, useForm } from '/@/components/Form'; | |
9 | +import { step3Schemas } from './data'; | |
10 | +import { Alert, Divider, Descriptions } from 'ant-design-vue'; | |
11 | + | |
12 | +export default defineComponent({ | |
13 | + components: { | |
14 | + BasicForm, | |
15 | + [Alert.name]: Alert, | |
16 | + [Divider.name]: Divider, | |
17 | + [Descriptions.name]: Descriptions, | |
18 | + [Descriptions.Item.name]: Descriptions.Item, | |
19 | + }, | |
20 | + emits: ['next', 'prev'], | |
21 | + setup(_, { emit }) { | |
22 | + const [register, { validate, setProps }] = useForm({ | |
23 | + labelWidth: 80, | |
24 | + schemas: step3Schemas, | |
25 | + actionColOptions: { | |
26 | + span: 14, | |
27 | + }, | |
28 | + resetButtonOptions: { | |
29 | + text: '上一步', | |
30 | + }, | |
31 | + submitButtonOptions: { | |
32 | + text: '提交', | |
33 | + }, | |
34 | + resetFunc: customResetFunc, | |
35 | + submitFunc: customSubmitFunc, | |
36 | + }); | |
37 | + | |
38 | + async function customResetFunc() { | |
39 | + emit('prev'); | |
40 | + } | |
41 | + | |
42 | + async function customSubmitFunc() { | |
43 | + try { | |
44 | + const values = await validate(); | |
45 | + setProps({ | |
46 | + submitButtonOptions: { | |
47 | + loading: true, | |
48 | + }, | |
49 | + }); | |
50 | + setTimeout(() => { | |
51 | + setProps({ | |
52 | + submitButtonOptions: { | |
53 | + loading: false, | |
54 | + }, | |
55 | + }); | |
56 | + emit('next', values); | |
57 | + }, 1500); | |
58 | + } catch (error) {} | |
59 | + } | |
60 | + | |
61 | + return { register }; | |
62 | + }, | |
63 | +}); | |
64 | +</script> | |
65 | +<style lang="less" scoped> | |
66 | +.step2 { | |
67 | + width: 450px; | |
68 | + margin: 0 auto; | |
69 | +} | |
70 | +</style> | ... | ... |
src/views/device/profile/step/data.tsx
0 → 100644
1 | +import { FormSchema } from '/@/components/Form'; | |
2 | +import {findDictItemByCode} from "/@/api/system/dict"; | |
3 | + | |
4 | +export const step1Schemas: FormSchema[] = [ | |
5 | + { | |
6 | + field: 'name', | |
7 | + label: '配置名称', | |
8 | + required: true, | |
9 | + component:'Input', | |
10 | + componentProps:{ | |
11 | + maxLength:30 | |
12 | + } | |
13 | + }, | |
14 | + { | |
15 | + field: 'deviceType', | |
16 | + label: '队列优先级', | |
17 | + component: 'ApiSelect', | |
18 | + componentProps: { | |
19 | + api:findDictItemByCode, | |
20 | + params:{ | |
21 | + dictCode:"queen_execute_sequence" | |
22 | + }, | |
23 | + labelField:'itemText', | |
24 | + valueField:'itemValue', | |
25 | + }, | |
26 | + }, | |
27 | + { | |
28 | + label: '备注', | |
29 | + field: 'remark', | |
30 | + component: 'InputTextArea', | |
31 | + } | |
32 | +]; | |
33 | + | |
34 | +export const step2Schemas: FormSchema[] = [ | |
35 | + { | |
36 | + field: 'transportType', | |
37 | + component: 'Select', | |
38 | + label: '传输方式', | |
39 | + defaultValue: 'DEFAULT', | |
40 | + componentProps:{ | |
41 | + options: [ | |
42 | + {label: '默认', value: "DEFAULT"}, | |
43 | + ], | |
44 | + } | |
45 | + }, | |
46 | +]; | |
47 | + | |
48 | +export const step3Schemas: FormSchema[] = [ | |
49 | + { | |
50 | + field: 'transportType', | |
51 | + component: 'Select', | |
52 | + label: '报警规则', | |
53 | + defaultValue: 'DEFAULT', | |
54 | + componentProps:{ | |
55 | + options: [ | |
56 | + {label: '默认', value: "DEFAULT"}, | |
57 | + ], | |
58 | + } | |
59 | + }, | |
60 | +]; | ... | ... |
... | ... | @@ -19,7 +19,7 @@ |
19 | 19 | </div> |
20 | 20 | </Upload> |
21 | 21 | </template> |
22 | - <template #devicePosition> | |
22 | + <template #deviceAddress> | |
23 | 23 | <Input disabled v-model:value="positionState.address"> |
24 | 24 | <template #addonAfter> |
25 | 25 | <EnvironmentTwoTone @click="selectPosition" /> |
... | ... | @@ -28,10 +28,17 @@ |
28 | 28 | </template> |
29 | 29 | </BasicForm> |
30 | 30 | </div> |
31 | - <Modal v-model:visible="visible" title="设备位置" @ok="handleOk" width="800px"> | |
31 | + <Modal | |
32 | + v-model:visible="visible" | |
33 | + title="设备位置" | |
34 | + @ok="handleOk" | |
35 | + width="800px" | |
36 | + @cancel="handleCancel" | |
37 | + centered | |
38 | + > | |
32 | 39 | <div> |
33 | 40 | <a-form :label-col="labelCol"> |
34 | - <a-row :gutter="20"> | |
41 | + <a-row :gutter="20" class="pt-4 pl-6"> | |
35 | 42 | <a-col :span="8"> |
36 | 43 | <a-form-item label="经度"> |
37 | 44 | <Input type="input" v-model:value="positionState.lng" disabled /> |
... | ... | @@ -56,10 +63,9 @@ |
56 | 63 | import { useScript } from '/@/hooks/web/useScript'; |
57 | 64 | import { ScrollActionType } from '/@/components/Container/index'; |
58 | 65 | import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue'; |
59 | - import { EnvironmentTwoTone, LoadingOutlined, PlusOutlined } from '@ant-design/icons-vue'; | |
66 | + import { EnvironmentTwoTone, PlusOutlined } from '@ant-design/icons-vue'; | |
60 | 67 | import { upload } from '/@/api/oss/ossFileUploader'; |
61 | 68 | import { FileItem } from '/@/components/Upload/src/typing'; |
62 | - | |
63 | 69 | export default defineComponent({ |
64 | 70 | components: { |
65 | 71 | BasicForm, |
... | ... | @@ -79,34 +85,35 @@ |
79 | 85 | emits: ['next'], |
80 | 86 | setup(_, { emit }) { |
81 | 87 | const devicePic = ref(''); |
82 | - const positionState = reactive({ | |
88 | + let positionState = reactive({ | |
83 | 89 | lng: '', |
84 | 90 | lat: '', |
85 | 91 | address: '', |
86 | 92 | }); |
87 | - const [register, { validate }] = useForm({ | |
93 | + const [register, { validate, resetFields, setFieldsValue, getFieldsValue }] = useForm({ | |
88 | 94 | labelWidth: 100, |
89 | 95 | schemas: step1Schemas, |
90 | 96 | actionColOptions: { |
91 | 97 | span: 14, |
92 | 98 | }, |
99 | + labelAlign: 'left', | |
93 | 100 | showResetButton: false, |
94 | 101 | submitButtonOptions: { |
95 | 102 | text: '下一步', |
96 | 103 | }, |
97 | 104 | submitFunc: customSubmitFunc, |
98 | 105 | }); |
99 | - | |
100 | 106 | async function customSubmitFunc() { |
101 | 107 | try { |
102 | 108 | let values = await validate(); |
103 | 109 | values = { devicePic: devicePic.value, ...positionState, ...values }; |
104 | 110 | delete values.icon; |
105 | - delete values.devicePosition; | |
111 | + delete values.deviceAddress; | |
106 | 112 | emit('next', values); |
107 | 113 | // 获取输入的数据 |
108 | - } catch (error) {} | |
114 | + } catch (e) {} | |
109 | 115 | } |
116 | + | |
110 | 117 | // 图片上传 |
111 | 118 | async function customUpload({ file }) { |
112 | 119 | if (beforeUpload(file)) { |
... | ... | @@ -150,12 +157,30 @@ |
150 | 157 | const BMap = (window as any).BMap; |
151 | 158 | if (!wrapEl) return; |
152 | 159 | const map = new BMap.Map(wrapEl); |
153 | - map.addEventListener('click', () => { | |
160 | + const point = new BMap.Point(104.04813399999999, 30.54348986021446); | |
161 | + map.centerAndZoom(point, 15); | |
162 | + map.enableScrollWheelZoom(true); | |
163 | + let preMarker = null; | |
164 | + map.addEventListener('click', (e) => { | |
154 | 165 | const { lat, lng } = map.he; |
155 | 166 | positionState.lat = lat + ''; |
156 | 167 | positionState.lng = lng + ''; |
157 | 168 | let gc = new BMap.Geocoder(); |
158 | 169 | let newPoint = new BMap.Point(lng, lat); |
170 | + if (!e.overlay) { | |
171 | + let myIcon = new BMap.Icon( | |
172 | + 'http://api.map.baidu.com/img/markers.png', | |
173 | + new BMap.Size(40, 25), | |
174 | + { | |
175 | + offset: new BMap.Size(0, 0), // 指定定位位置 | |
176 | + imageOffset: new BMap.Size(20, -260), // 设置图片偏移 | |
177 | + } | |
178 | + ); | |
179 | + let marker = new BMap.Marker(e.point, { icon: myIcon }); | |
180 | + map.removeOverlay(preMarker); | |
181 | + map.addOverlay(marker); | |
182 | + preMarker = marker; | |
183 | + } | |
159 | 184 | gc.getLocation(newPoint, (rs) => { |
160 | 185 | let addComp = rs.addressComponents; |
161 | 186 | //获取详细的地址,精确到街道的名称 |
... | ... | @@ -163,15 +188,33 @@ |
163 | 188 | positionState.address = addrname; |
164 | 189 | }); |
165 | 190 | }); |
166 | - const point = new BMap.Point(104.04813399999999, 30.54348986021446); | |
167 | - map.centerAndZoom(point, 15); | |
168 | - map.enableScrollWheelZoom(true); | |
169 | 191 | } |
170 | 192 | // 确定选择的位置 |
171 | 193 | const handleOk = () => { |
172 | 194 | visible.value = false; |
173 | 195 | }; |
196 | + // 取消选择位置 | |
197 | + const handleCancel = () => { | |
198 | + for (let key in positionState) { | |
199 | + positionState[key] = ''; | |
200 | + } | |
201 | + }; | |
202 | + // 父组件调用更新字段值的方法 | |
203 | + function parentSetFieldsValue(data) { | |
204 | + setFieldsValue(data); | |
205 | + } | |
206 | + | |
207 | + function parentGetFieldsValue() { | |
208 | + return getFieldsValue(); | |
209 | + } | |
210 | + | |
211 | + async function parentValidate() { | |
212 | + const valid = await validate(); | |
213 | + return valid; | |
214 | + } | |
215 | + | |
174 | 216 | return { |
217 | + resetFields, | |
175 | 218 | positionState, |
176 | 219 | register, |
177 | 220 | beforeUpload, |
... | ... | @@ -181,8 +224,12 @@ |
181 | 224 | visible, |
182 | 225 | scrollRef, |
183 | 226 | handleOk, |
227 | + handleCancel, | |
184 | 228 | wrapRef, |
185 | 229 | labelCol: { style: { width: '40px' } }, |
230 | + parentSetFieldsValue, | |
231 | + parentGetFieldsValue, | |
232 | + parentValidate, | |
186 | 233 | }; |
187 | 234 | }, |
188 | 235 | }); | ... | ... |
1 | 1 | <template> |
2 | 2 | <div class="step2"> |
3 | - <div><input type="checkbox" v-model="isCreaentials" @click="checked" /> 添加凭证 </div> | |
4 | - | |
5 | - <a-form :label-col="labelCol" :wrapper-col="wrapperCol" v-if="isCreaentials"> | |
6 | - <a-form-item label="凭据类型"> | |
3 | + <div | |
4 | + ><input type="checkbox" v-model="creaentialsPassword.isCreaentials" @click="checked" /> | |
5 | + 添加凭证 | |
6 | + </div> | |
7 | + <a-form | |
8 | + ref="formRef" | |
9 | + :rules="rules" | |
10 | + :label-col="labelCol" | |
11 | + :wrapper-col="wrapperCol" | |
12 | + v-show="creaentialsPassword.isCreaentials" | |
13 | + :model="creaentialsPassword" | |
14 | + labelAlign="left" | |
15 | + > | |
16 | + <a-form-item label="凭据类型" name="creaentialsType"> | |
7 | 17 | <a-select |
8 | - v-model:value="creaentialsType" | |
18 | + v-model:value="creaentialsPassword.creaentialsType" | |
9 | 19 | style="width: 200px" |
10 | 20 | @change="handleChange" |
11 | 21 | placeholder="请选择凭据类型" |
12 | 22 | :options="options" |
13 | 23 | /> |
14 | 24 | </a-form-item> |
15 | - <div v-if="creaentialsType === 'Access token'"> | |
16 | - <a-form-item label="访问令牌"> | |
17 | - <a-input type="input" style="width: 200px" v-model:value="token" /> | |
25 | + <div v-if="creaentialsPassword.creaentialsType === 'Access token'"> | |
26 | + <a-form-item label="访问令牌" name="token"> | |
27 | + <a-input type="password" style="width: 200px" v-model:value="creaentialsPassword.token" /> | |
18 | 28 | </a-form-item> |
19 | 29 | </div> |
20 | - <div v-else-if="creaentialsType === 'X.509'"> | |
21 | - <a-form-item label="RSA公钥"> | |
22 | - <a-input type="input" style="width: 200px" v-model:value="publicKey" /> | |
30 | + <div v-else-if="creaentialsPassword.creaentialsType === 'X.509'"> | |
31 | + <a-form-item label="RSA公钥" name="publicKey"> | |
32 | + <a-input | |
33 | + type="password" | |
34 | + style="width: 200px" | |
35 | + v-model:value="creaentialsPassword.publicKey" | |
36 | + /> | |
23 | 37 | </a-form-item> |
24 | 38 | </div> |
25 | 39 | <div v-else> |
26 | - <a-form-item label="客户端ID"> | |
27 | - <a-input type="input" style="width: 200px" v-model:value="clientId" /> | |
40 | + <a-form-item label="客户端ID" name="clientId"> | |
41 | + <a-input type="input" style="width: 200px" v-model:value="creaentialsPassword.clientId" /> | |
28 | 42 | </a-form-item> |
29 | - <a-form-item label="用户名"> | |
30 | - <a-input type="input" style="width: 200px" v-model:value="username" /> | |
43 | + <a-form-item label="用户名" name="username"> | |
44 | + <a-input type="input" style="width: 200px" v-model:value="creaentialsPassword.username" /> | |
31 | 45 | </a-form-item> |
32 | - <a-form-item label="密码"> | |
33 | - <a-input type="password" style="width: 200px" v-model:value="password" /> | |
46 | + <a-form-item label="密码" name="password"> | |
47 | + <a-input | |
48 | + type="password" | |
49 | + style="width: 200px" | |
50 | + v-model:value="creaentialsPassword.password" | |
51 | + /> | |
34 | 52 | </a-form-item> |
35 | 53 | </div> |
36 | 54 | </a-form> |
37 | - | |
38 | 55 | <div class="flex justify-start"> |
39 | 56 | <a-button class="mr-5" @click="prevStep">上一步</a-button> |
40 | 57 | </div> |
41 | 58 | </div> |
42 | 59 | </template> |
43 | 60 | <script lang="ts"> |
44 | - import { defineComponent, reactive, ref, toRefs } from 'vue'; | |
61 | + import { defineComponent, reactive, ref, watch } from 'vue'; | |
45 | 62 | |
46 | - import { Input, Form, Select, Button, SelectProps } from 'ant-design-vue'; | |
63 | + import { Input, Form, Select, Button } from 'ant-design-vue'; | |
47 | 64 | export default defineComponent({ |
48 | 65 | components: { |
49 | 66 | [Form.name]: Form, |
... | ... | @@ -52,18 +69,26 @@ |
52 | 69 | [Select.name]: Select, |
53 | 70 | [Button.name]: Button, |
54 | 71 | }, |
55 | - emits: ['prev'], | |
72 | + | |
73 | + emits: ['prev', 'next'], | |
56 | 74 | setup(_, { emit }) { |
57 | - const isCreaentials = ref(false); | |
58 | - const creaentialsType = ref('Access token'); | |
75 | + const formRef = ref(); | |
59 | 76 | const creaentialsPassword = reactive({ |
77 | + isCreaentials: false, | |
78 | + creaentialsType: 'Access token', | |
60 | 79 | token: '', |
61 | 80 | publicKey: '', |
62 | 81 | clientId: '', |
63 | 82 | username: '', |
64 | 83 | password: '', |
65 | 84 | }); |
66 | - const options = ref<SelectProps['options']>([ | |
85 | + const rules = { | |
86 | + token: [{ required: true, message: '请输入访问令牌', trigger: 'blur' }], | |
87 | + publicKey: [{ required: true, message: '请输入RSA公钥', trigger: 'blur' }], | |
88 | + clientId: [{ required: true, message: '请输入客户端ID', trigger: 'blur' }], | |
89 | + username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], | |
90 | + }; | |
91 | + const options = ref([ | |
67 | 92 | { |
68 | 93 | value: 'Access token', |
69 | 94 | label: 'Access token', |
... | ... | @@ -78,41 +103,76 @@ |
78 | 103 | label: 'MQTT Basic', |
79 | 104 | }, |
80 | 105 | ]); |
106 | + // 切换是否添加凭证 | |
81 | 107 | const checked = () => { |
82 | - isCreaentials.value = !isCreaentials.value; | |
108 | + creaentialsPassword.isCreaentials = !creaentialsPassword.isCreaentials; | |
109 | + formRef.value.resetFields(); | |
110 | + creaentialsPassword.creaentialsType = 'Access token'; | |
83 | 111 | }; |
84 | 112 | const prevStep = () => { |
85 | 113 | emit('prev'); |
86 | 114 | }; |
115 | + watch(creaentialsPassword, (newValue) => { | |
116 | + emit('next', newValue); | |
117 | + }); | |
118 | + | |
87 | 119 | // 切换凭证类型时,重置字段 |
88 | 120 | const handleChange = (value) => { |
89 | 121 | if (value === 'Access token') { |
90 | - creaentialsPassword.token = ''; | |
122 | + resetCreantialsType(); | |
91 | 123 | } else if (value === 'X.509') { |
92 | - creaentialsPassword.publicKey = ''; | |
124 | + resetCreantialsType(); | |
93 | 125 | } else { |
94 | - creaentialsPassword.clientId = ''; | |
95 | - creaentialsPassword.username = ''; | |
96 | - creaentialsPassword.password = ''; | |
126 | + resetCreantialsType(); | |
97 | 127 | } |
98 | 128 | }; |
129 | + // 切换凭证类型时,重置字段 | |
130 | + function resetCreantialsType() { | |
131 | + creaentialsPassword.token = ''; | |
132 | + creaentialsPassword.publicKey = ''; | |
133 | + creaentialsPassword.clientId = ''; | |
134 | + creaentialsPassword.username = ''; | |
135 | + creaentialsPassword.password = ''; | |
136 | + } | |
137 | + | |
138 | + // 重置所有字段 | |
139 | + function resetFields() { | |
140 | + creaentialsPassword.isCreaentials = false; | |
141 | + creaentialsPassword.creaentialsType = 'Access token'; | |
142 | + creaentialsPassword.token = ''; | |
143 | + creaentialsPassword.publicKey = ''; | |
144 | + creaentialsPassword.clientId = ''; | |
145 | + creaentialsPassword.username = ''; | |
146 | + creaentialsPassword.password = ''; | |
147 | + formRef.value.resetFields(); | |
148 | + } | |
149 | + | |
150 | + // 表单验证 | |
151 | + function validate() { | |
152 | + if (creaentialsPassword.isCreaentials) { | |
153 | + return formRef.value.validate(); | |
154 | + } | |
155 | + return true; | |
156 | + } | |
99 | 157 | return { |
100 | - ...toRefs(creaentialsPassword), | |
101 | - creaentialsType, | |
102 | - isCreaentials, | |
103 | 158 | options, |
159 | + formRef, | |
160 | + creaentialsPassword, | |
104 | 161 | handleChange, |
105 | 162 | prevStep, |
106 | 163 | checked, |
107 | 164 | labelCol: { style: { width: '150px' } }, |
108 | 165 | wrapperCol: { span: 18 }, |
166 | + resetFields, | |
167 | + validate, | |
168 | + rules, | |
109 | 169 | }; |
110 | 170 | }, |
111 | 171 | }); |
112 | 172 | </script> |
113 | 173 | <style lang="less" scoped> |
114 | 174 | .step2 { |
115 | - width: 500px; | |
175 | + width: 700px; | |
116 | 176 | margin: 0 auto; |
117 | 177 | } |
118 | 178 | </style> | ... | ... |
src/views/device/step/StepIndexDemo.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <PageWrapper | |
3 | - title="分步表单" | |
4 | - contentBackground | |
5 | - content=" 将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。" | |
6 | - contentClass="p-4" | |
7 | - > | |
8 | - <div class="step-form-form"> | |
9 | - <a-steps :current="current"> | |
10 | - <a-step title="填写转账信息" /> | |
11 | - <a-step title="确认转账信息" /> | |
12 | - <a-step title="完成" /> | |
13 | - </a-steps> | |
14 | - </div> | |
15 | - <div class="mt-5"> | |
16 | - <Step1 @next="handleStep1Next" v-show="current === 0" /> | |
17 | - <Step2 | |
18 | - @prev="handleStepPrev" | |
19 | - @next="handleStep2Next" | |
20 | - v-show="current === 1" | |
21 | - v-if="initSetp2" | |
22 | - /> | |
23 | - </div> | |
24 | - </PageWrapper> | |
25 | -</template> | |
26 | -<script lang="ts"> | |
27 | - import { defineComponent, ref, reactive, toRefs } from 'vue'; | |
28 | - import Step1 from './DeviceStep1.vue'; | |
29 | - import Step2 from './DeviceStep2.vue'; | |
30 | - import { PageWrapper } from '/@/components/Page'; | |
31 | - import { Steps } from 'ant-design-vue'; | |
32 | - | |
33 | - export default defineComponent({ | |
34 | - name: 'FormStepPage', | |
35 | - components: { | |
36 | - Step1, | |
37 | - Step2, | |
38 | - | |
39 | - PageWrapper, | |
40 | - [Steps.name]: Steps, | |
41 | - [Steps.Step.name]: Steps.Step, | |
42 | - }, | |
43 | - setup() { | |
44 | - const current = ref(1); | |
45 | - | |
46 | - const state = reactive({ | |
47 | - initSetp2: false, | |
48 | - }); | |
49 | - | |
50 | - function handleStep1Next(step1Values: any) { | |
51 | - current.value++; | |
52 | - state.initSetp2 = true; | |
53 | - console.log(step1Values); | |
54 | - } | |
55 | - | |
56 | - function handleStepPrev() { | |
57 | - current.value--; | |
58 | - } | |
59 | - | |
60 | - function handleStep2Next(step2Values: any) { | |
61 | - current.value++; | |
62 | - console.log(step2Values); | |
63 | - } | |
64 | - | |
65 | - function handleRedo() { | |
66 | - current.value = 0; | |
67 | - state.initSetp2 = false; | |
68 | - } | |
69 | - | |
70 | - return { | |
71 | - current, | |
72 | - handleStep1Next, | |
73 | - handleStep2Next, | |
74 | - handleRedo, | |
75 | - handleStepPrev, | |
76 | - ...toRefs(state), | |
77 | - }; | |
78 | - }, | |
79 | - }); | |
80 | -</script> | |
81 | -<style lang="less" scoped> | |
82 | - .step-form-content { | |
83 | - padding: 24px; | |
84 | - background-color: @component-background; | |
85 | - } | |
86 | - | |
87 | - .step-form-form { | |
88 | - width: 750px; | |
89 | - margin: 0 auto; | |
90 | - } | |
91 | -</style> |
1 | 1 | import { FormSchema } from '/@/components/Form'; |
2 | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
3 | - | |
3 | +import { deviceProfile } from '/@/api/device/deviceManager'; | |
4 | +import { getOrganizationList } from '/@/api/system/system'; | |
5 | +import { copyTransFun } from '/@/utils/fnUtils'; | |
6 | +// 第一步的表单 | |
4 | 7 | export const step1Schemas: FormSchema[] = [ |
5 | 8 | { |
6 | 9 | field: 'icon', |
... | ... | @@ -32,6 +35,30 @@ export const step1Schemas: FormSchema[] = [ |
32 | 35 | }, |
33 | 36 | }, |
34 | 37 | { |
38 | + field: 'profileId', | |
39 | + label: '设备配置', | |
40 | + required: true, | |
41 | + component: 'ApiSelect', | |
42 | + componentProps: { | |
43 | + api: deviceProfile, | |
44 | + labelField: 'name', | |
45 | + valueField: 'id', | |
46 | + }, | |
47 | + }, | |
48 | + { | |
49 | + field: 'organizationId', | |
50 | + required: true, | |
51 | + label: '所属组织', | |
52 | + component: 'ApiTreeSelect', | |
53 | + componentProps: { | |
54 | + api: async () => { | |
55 | + const data = await getOrganizationList(); | |
56 | + copyTransFun(data as any as any[]); | |
57 | + return data; | |
58 | + }, | |
59 | + }, | |
60 | + }, | |
61 | + { | |
35 | 62 | field: 'label', |
36 | 63 | label: '设备标签', |
37 | 64 | component: 'Input', |
... | ... | @@ -40,14 +67,32 @@ export const step1Schemas: FormSchema[] = [ |
40 | 67 | }, |
41 | 68 | }, |
42 | 69 | { |
43 | - field: 'devicePosition', | |
70 | + field: 'deviceAddress', | |
44 | 71 | label: '设备位置', |
45 | 72 | component: 'Input', |
46 | - slot: 'devicePosition', | |
73 | + slot: 'deviceAddress', | |
47 | 74 | }, |
48 | 75 | { |
49 | - label: '备注', | |
50 | 76 | field: 'remark', |
77 | + label: '备注', | |
51 | 78 | component: 'InputTextArea', |
52 | 79 | }, |
80 | + { | |
81 | + field: 'id', | |
82 | + label: 'id', | |
83 | + component: 'Input', | |
84 | + show: false, | |
85 | + }, | |
86 | + { | |
87 | + field: 'profileId', | |
88 | + label: '设备配置id', | |
89 | + component: 'Input', | |
90 | + show: false, | |
91 | + }, | |
92 | + { | |
93 | + field: 'deviceToken', | |
94 | + label: '设备唯一token', | |
95 | + component: 'Input', | |
96 | + show: false, | |
97 | + }, | |
53 | 98 | ]; | ... | ... |