Commit 84a20db34ee67623bd95778559f9fcffbc03afac

Authored by 黄 x
2 parents 11271a2e 04c4d5ef

Merge branch 'main' into ft-dev

@@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = / @@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = /
6 6
7 # Cross-domain proxy, you can configure multiple 7 # Cross-domain proxy, you can configure multiple
8 # Please note that no line breaks 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 # VITE_PROXY=[["/api","https://vvbin.cn/test"]] 10 # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
11 11
12 # Delete console 12 # Delete console
@@ -11,6 +11,7 @@ tests/server/static/upload @@ -11,6 +11,7 @@ tests/server/static/upload
11 # local env files 11 # local env files
12 .env.local 12 .env.local
13 .env.*.local 13 .env.*.local
  14 +.env.development
14 .eslintcache 15 .eslintcache
15 .package-lock.json 16 .package-lock.json
16 .yarn.lock 17 .yarn.lock
@@ -15,6 +15,8 @@ enum DeviceManagerApi { @@ -15,6 +15,8 @@ enum DeviceManagerApi {
15 * 设备配置URL 15 * 设备配置URL
16 */ 16 */
17 DEVICE_PROFILE_URL = '/deviceProfile', 17 DEVICE_PROFILE_URL = '/deviceProfile',
  18 +
  19 + DEVICE_PROFILE_URL_ME = '/deviceProfile/me',
18 } 20 }
19 21
20 export const devicePage = (params: DeviceQueryParam) => { 22 export const devicePage = (params: DeviceQueryParam) => {
@@ -59,3 +61,20 @@ export const deleteDevice = (ids: string[]) => { @@ -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,8 +4,9 @@
4 width="55rem" 4 width="55rem"
5 @register="register" 5 @register="register"
6 :title="getTitle" 6 :title="getTitle"
7 - @visible-change="handleVisibleChange"  
8 @cancel="handleCancel" 7 @cancel="handleCancel"
  8 + @ok="handleOk"
  9 + centered
9 > 10 >
10 <div class="step-form-form"> 11 <div class="step-form-form">
11 <a-steps :current="current"> 12 <a-steps :current="current">
@@ -14,8 +15,9 @@ @@ -14,8 +15,9 @@
14 </a-steps> 15 </a-steps>
15 </div> 16 </div>
16 <div class="mt-5"> 17 <div class="mt-5">
17 - <DeviceStep1 @next="handleStep1Next" v-show="current === 0" /> 18 + <DeviceStep1 @next="handleStep1Next" v-show="current === 0" ref="DeviceStep1Ref" />
18 <DeviceStep2 19 <DeviceStep2
  20 + ref="DeviceStep2Ref"
19 @prev="handleStepPrev" 21 @prev="handleStepPrev"
20 @next="handleStep2Next" 22 @next="handleStep2Next"
21 v-show="current === 1" 23 v-show="current === 1"
@@ -25,11 +27,13 @@ @@ -25,11 +27,13 @@
25 </BasicModal> 27 </BasicModal>
26 </template> 28 </template>
27 <script lang="ts"> 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 import { BasicModal, useModalInner } from '/@/components/Modal'; 31 import { BasicModal, useModalInner } from '/@/components/Modal';
  32 + import { createOrEditDevice } from '/@/api/device/deviceManager';
30 import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; 33 import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue';
31 import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; 34 import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue';
32 import { Steps } from 'ant-design-vue'; 35 import { Steps } from 'ant-design-vue';
  36 + import { useMessage } from '/@/hooks/web/useMessage';
33 export default defineComponent({ 37 export default defineComponent({
34 name: 'DeviceModal', 38 name: 'DeviceModal',
35 components: { 39 components: {
@@ -42,72 +46,87 @@ @@ -42,72 +46,87 @@
42 props: { 46 props: {
43 userData: { type: Object }, 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 const state = reactive({ 53 const state = reactive({
47 initStep2: false, 54 initStep2: false,
48 }); 55 });
49 const current = ref(0); 56 const current = ref(0);
50 const isUpdate = ref(true); 57 const isUpdate = ref(true);
51 - const modelRef = ref({});  
52 const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); 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 isUpdate.value = !!data?.isUpdate; 71 isUpdate.value = !!data?.isUpdate;
56 - data && onDataReceive(data);  
57 }); 72 });
58 73
  74 + // 上一步
59 function handleStepPrev() { 75 function handleStepPrev() {
60 current.value--; 76 current.value--;
61 } 77 }
  78 + // 下一步
62 function handleStep1Next(step1Values: any) { 79 function handleStep1Next(step1Values: any) {
63 current.value++; 80 current.value++;
64 state.initStep2 = true; 81 state.initStep2 = true;
65 - console.log(step1Values); 82 + stepState = { ...step1Values };
66 } 83 }
  84 + //
67 function handleStep2Next(step2Values: any) { 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 function handleCancel() { 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 return { 118 return {
100 register, 119 register,
101 - model: modelRef,  
102 getTitle, 120 getTitle,
103 - handleVisibleChange,  
104 current, 121 current,
  122 + DeviceStep1Ref,
  123 + DeviceStep2Ref,
105 ...toRefs(state), 124 ...toRefs(state),
106 handleStepPrev, 125 handleStepPrev,
107 handleStep1Next, 126 handleStep1Next,
108 handleStep2Next, 127 handleStep2Next,
109 handleCancel, 128 handleCancel,
110 - handleRedo, 129 + handleOk,
111 }; 130 };
112 }, 131 },
113 }); 132 });
1 import { BasicColumn } from '/@/components/Table'; 1 import { BasicColumn } from '/@/components/Table';
2 import { FormSchema } from '/@/components/Table'; 2 import { FormSchema } from '/@/components/Table';
3 -import { findDictItemByCode } from '/@/api/system/dict';  
4 import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; 3 import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel';
  4 +// 表格列数据
5 export const columns: BasicColumn[] = [ 5 export const columns: BasicColumn[] = [
6 { 6 {
7 title: '设备名称', 7 title: '设备名称',
@@ -45,6 +45,7 @@ export const columns: BasicColumn[] = [ @@ -45,6 +45,7 @@ export const columns: BasicColumn[] = [
45 }, 45 },
46 ]; 46 ];
47 47
  48 +// 查询字段
48 export const searchFormSchema: FormSchema[] = [ 49 export const searchFormSchema: FormSchema[] = [
49 { 50 {
50 field: 'deviceType', 51 field: 'deviceType',
@@ -79,48 +80,3 @@ export const searchFormSchema: FormSchema[] = [ @@ -79,48 +80,3 @@ export const searchFormSchema: FormSchema[] = [
79 colProps: { span: 8 }, 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,16 +65,13 @@
65 /> 65 />
66 </template> 66 </template>
67 </BasicTable> 67 </BasicTable>
68 - <!-- <ConfigDrawer @register="registerDrawer" @success="handleSuccess" /> -->  
69 - <DeviceModal @register="registerModal" @success="handleSuccess" /> 68 + <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" />
70 </PageWrapper> 69 </PageWrapper>
71 </template> 70 </template>
72 <script lang="ts"> 71 <script lang="ts">
73 import { defineComponent, reactive } from 'vue'; 72 import { defineComponent, reactive } from 'vue';
74 import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; 73 import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel';
75 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 74 import { BasicTable, useTable, TableAction } from '/@/components/Table';
76 - // import { useDrawer } from '/@/components/Drawer';  
77 - // import ConfigDrawer from './DeviceDrawer.vue';  
78 import { columns, searchFormSchema } from './device.data'; 75 import { columns, searchFormSchema } from './device.data';
79 import { Tag } from 'ant-design-vue'; 76 import { Tag } from 'ant-design-vue';
80 import { useMessage } from '/@/hooks/web/useMessage'; 77 import { useMessage } from '/@/hooks/web/useMessage';
@@ -90,17 +87,16 @@ @@ -90,17 +87,16 @@
90 name: 'DeviceManagement', 87 name: 'DeviceManagement',
91 components: { 88 components: {
92 BasicTable, 89 BasicTable,
93 - // ConfigDrawer,  
94 PageWrapper, 90 PageWrapper,
95 TableAction, 91 TableAction,
96 OrganizationIdTree, 92 OrganizationIdTree,
97 Tag, 93 Tag,
98 DeviceModal, 94 DeviceModal,
99 }, 95 },
100 - setup() {  
101 - // const [registerDrawer, { openDrawer }] = useDrawer(); 96 + setup(_) {
102 const { createMessage } = useMessage(); 97 const { createMessage } = useMessage();
103 const go = useGo(); 98 const go = useGo();
  99 +
104 const searchInfo = reactive<Recordable>({}); 100 const searchInfo = reactive<Recordable>({});
105 const [registerModal, { openModal }] = useModal(); 101 const [registerModal, { openModal }] = useModal();
106 const [registerTable, { reload }] = useTable({ 102 const [registerTable, { reload }] = useTable({
@@ -124,6 +120,9 @@ @@ -124,6 +120,9 @@
124 fixed: undefined, 120 fixed: undefined,
125 }, 121 },
126 }); 122 });
  123 + const handleReload = () => {
  124 + handleSuccess();
  125 + };
127 126
128 function handleCreate() { 127 function handleCreate() {
129 openModal(true, { 128 openModal(true, {
@@ -158,7 +157,6 @@ @@ -158,7 +157,6 @@
158 } 157 }
159 return { 158 return {
160 registerTable, 159 registerTable,
161 - // registerDrawer,  
162 handleCreate, 160 handleCreate,
163 handleEdit, 161 handleEdit,
164 handleDelete, 162 handleDelete,
@@ -169,6 +167,7 @@ @@ -169,6 +167,7 @@
169 handleSelect, 167 handleSelect,
170 searchInfo, 168 searchInfo,
171 registerModal, 169 registerModal,
  170 + handleReload,
172 }; 171 };
173 }, 172 },
174 }); 173 });
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 width="500px" 7 width="500px"
8 @ok="handleSubmit" 8 @ok="handleSubmit"
9 > 9 >
10 - <BasicForm @register="registerForm" /> 10 + <BasicForm @register="registerForm"/>
11 </BasicDrawer> 11 </BasicDrawer>
12 </template> 12 </template>
13 <script lang="ts"> 13 <script lang="ts">
@@ -15,8 +15,8 @@ @@ -15,8 +15,8 @@
15 import { BasicForm, useForm } from '/@/components/Form'; 15 import { BasicForm, useForm } from '/@/components/Form';
16 import { formSchema } from './device.profile.data'; 16 import { formSchema } from './device.profile.data';
17 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 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 export default defineComponent({ 21 export default defineComponent({
22 name: 'DeviceProfileDrawer', 22 name: 'DeviceProfileDrawer',
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 setup(_, { emit }) { 25 setup(_, { emit }) {
26 const isUpdate = ref(true); 26 const isUpdate = ref(true);
27 27
28 - const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({ 28 + const [registerForm, { validate,setFieldsValue,resetFields }] = useForm({
29 labelWidth: 120, 29 labelWidth: 120,
30 schemas: formSchema, 30 schemas: formSchema,
31 showActionButtonGroup: false, 31 showActionButtonGroup: false,
@@ -37,8 +37,8 @@ @@ -37,8 +37,8 @@
37 isUpdate.value = !!data?.isUpdate; 37 isUpdate.value = !!data?.isUpdate;
38 if (unref(isUpdate)) { 38 if (unref(isUpdate)) {
39 const config = data.record.config; 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 await setFieldsValue({ 43 await setFieldsValue({
44 ...data.record, 44 ...data.record,
@@ -53,27 +53,27 @@ @@ -53,27 +53,27 @@
53 const values = await validate(); 53 const values = await validate();
54 const { createMessage } = useMessage(); 54 const { createMessage } = useMessage();
55 setDrawerProps({ confirmLoading: true }); 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 Reflect.set(values, 'config', config); 70 Reflect.set(values, 'config', config);
71 - let saveMessage = '添加成功';  
72 - let updateMessage = '修改成功'; 71 + let saveMessage = "添加成功";
  72 + let updateMessage = "修改成功";
73 await saveOrEditMessageConfig(values, unref(isUpdate)); 73 await saveOrEditMessageConfig(values, unref(isUpdate));
74 closeDrawer(); 74 closeDrawer();
75 emit('success'); 75 emit('success');
76 - createMessage.success(unref(isUpdate) ? updateMessage : saveMessage); 76 + createMessage.success(unref(isUpdate)?updateMessage:saveMessage);
77 } finally { 77 } finally {
78 setDrawerProps({ confirmLoading: false }); 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,40 +8,40 @@
8 <TableAction 8 <TableAction
9 :actions="[ 9 :actions="[
10 { 10 {
11 - label: '编辑', 11 + label:'编辑',
12 icon: 'clarity:note-edit-line', 12 icon: 'clarity:note-edit-line',
13 onClick: handleEdit.bind(null, record), 13 onClick: handleEdit.bind(null, record),
14 }, 14 },
15 { 15 {
16 - label: '删除', 16 + label:'删除',
17 icon: 'ant-design:delete-outlined', 17 icon: 'ant-design:delete-outlined',
18 color: 'error', 18 color: 'error',
19 popConfirm: { 19 popConfirm: {
20 title: '是否确认删除', 20 title: '是否确认删除',
21 confirm: handleDelete.bind(null, record), 21 confirm: handleDelete.bind(null, record),
22 - }, 22 + }
23 }, 23 },
24 ]" 24 ]"
25 /> 25 />
26 </template> 26 </template>
27 </BasicTable> 27 </BasicTable>
28 - <DeviceProfileDrawer @register="registerDrawer" @success="handleSuccess" /> 28 + <DeviceProfileModal @register="registerModal" @success="handleSuccess"/>
29 </div> 29 </div>
30 </template> 30 </template>
31 <script lang="ts"> 31 <script lang="ts">
32 import { defineComponent } from 'vue'; 32 import { defineComponent } from 'vue';
33 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 33 import { BasicTable, useTable, TableAction } from '/@/components/Table';
34 - import { useDrawer } from '/@/components/Drawer';  
35 - import DeviceProfileDrawer from './DeviceProfile.vue';  
36 import { columns, searchFormSchema } from './device.profile.data'; 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 export default defineComponent({ 39 export default defineComponent({
40 name: 'DeviceProfileManagement', 40 name: 'DeviceProfileManagement',
41 - components: { BasicTable, DeviceProfileDrawer, TableAction }, 41 + components: { BasicTable, DeviceProfileModal, TableAction},
42 setup() { 42 setup() {
43 - const [registerDrawer, { openDrawer }] = useDrawer();  
44 - const { createMessage } = useMessage(); 43 + const {createMessage} = useMessage();
  44 + const [registerModal, { openModal }] = useModal();
45 const [registerTable, { reload }] = useTable({ 45 const [registerTable, { reload }] = useTable({
46 title: '设备配置列表', 46 title: '设备配置列表',
47 api: deviceProfilePage, 47 api: deviceProfilePage,
@@ -63,13 +63,13 @@ @@ -63,13 +63,13 @@
63 }); 63 });
64 64
65 function handleCreate() { 65 function handleCreate() {
66 - openDrawer(true, { 66 + openModal(true, {
67 isUpdate: false, 67 isUpdate: false,
68 }); 68 });
69 } 69 }
70 70
71 function handleEdit(record: Recordable) { 71 function handleEdit(record: Recordable) {
72 - openDrawer(true, { 72 + openModal(true, {
73 record, 73 record,
74 isUpdate: true, 74 isUpdate: true,
75 }); 75 });
@@ -77,9 +77,9 @@ @@ -77,9 +77,9 @@
77 77
78 function handleDelete(record: Recordable) { 78 function handleDelete(record: Recordable) {
79 let ids = [record.id]; 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,11 +88,11 @@
88 } 88 }
89 return { 89 return {
90 registerTable, 90 registerTable,
91 - registerDrawer,  
92 handleCreate, 91 handleCreate,
93 handleEdit, 92 handleEdit,
94 handleDelete, 93 handleDelete,
95 handleSuccess, 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>
  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,7 +19,7 @@
19 </div> 19 </div>
20 </Upload> 20 </Upload>
21 </template> 21 </template>
22 - <template #devicePosition> 22 + <template #deviceAddress>
23 <Input disabled v-model:value="positionState.address"> 23 <Input disabled v-model:value="positionState.address">
24 <template #addonAfter> 24 <template #addonAfter>
25 <EnvironmentTwoTone @click="selectPosition" /> 25 <EnvironmentTwoTone @click="selectPosition" />
@@ -28,10 +28,17 @@ @@ -28,10 +28,17 @@
28 </template> 28 </template>
29 </BasicForm> 29 </BasicForm>
30 </div> 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 <div> 39 <div>
33 <a-form :label-col="labelCol"> 40 <a-form :label-col="labelCol">
34 - <a-row :gutter="20"> 41 + <a-row :gutter="20" class="pt-4 pl-6">
35 <a-col :span="8"> 42 <a-col :span="8">
36 <a-form-item label="经度"> 43 <a-form-item label="经度">
37 <Input type="input" v-model:value="positionState.lng" disabled /> 44 <Input type="input" v-model:value="positionState.lng" disabled />
@@ -56,10 +63,9 @@ @@ -56,10 +63,9 @@
56 import { useScript } from '/@/hooks/web/useScript'; 63 import { useScript } from '/@/hooks/web/useScript';
57 import { ScrollActionType } from '/@/components/Container/index'; 64 import { ScrollActionType } from '/@/components/Container/index';
58 import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue'; 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 import { upload } from '/@/api/oss/ossFileUploader'; 67 import { upload } from '/@/api/oss/ossFileUploader';
61 import { FileItem } from '/@/components/Upload/src/typing'; 68 import { FileItem } from '/@/components/Upload/src/typing';
62 -  
63 export default defineComponent({ 69 export default defineComponent({
64 components: { 70 components: {
65 BasicForm, 71 BasicForm,
@@ -79,34 +85,35 @@ @@ -79,34 +85,35 @@
79 emits: ['next'], 85 emits: ['next'],
80 setup(_, { emit }) { 86 setup(_, { emit }) {
81 const devicePic = ref(''); 87 const devicePic = ref('');
82 - const positionState = reactive({ 88 + let positionState = reactive({
83 lng: '', 89 lng: '',
84 lat: '', 90 lat: '',
85 address: '', 91 address: '',
86 }); 92 });
87 - const [register, { validate }] = useForm({ 93 + const [register, { validate, resetFields, setFieldsValue, getFieldsValue }] = useForm({
88 labelWidth: 100, 94 labelWidth: 100,
89 schemas: step1Schemas, 95 schemas: step1Schemas,
90 actionColOptions: { 96 actionColOptions: {
91 span: 14, 97 span: 14,
92 }, 98 },
  99 + labelAlign: 'left',
93 showResetButton: false, 100 showResetButton: false,
94 submitButtonOptions: { 101 submitButtonOptions: {
95 text: '下一步', 102 text: '下一步',
96 }, 103 },
97 submitFunc: customSubmitFunc, 104 submitFunc: customSubmitFunc,
98 }); 105 });
99 -  
100 async function customSubmitFunc() { 106 async function customSubmitFunc() {
101 try { 107 try {
102 let values = await validate(); 108 let values = await validate();
103 values = { devicePic: devicePic.value, ...positionState, ...values }; 109 values = { devicePic: devicePic.value, ...positionState, ...values };
104 delete values.icon; 110 delete values.icon;
105 - delete values.devicePosition; 111 + delete values.deviceAddress;
106 emit('next', values); 112 emit('next', values);
107 // 获取输入的数据 113 // 获取输入的数据
108 - } catch (error) {} 114 + } catch (e) {}
109 } 115 }
  116 +
110 // 图片上传 117 // 图片上传
111 async function customUpload({ file }) { 118 async function customUpload({ file }) {
112 if (beforeUpload(file)) { 119 if (beforeUpload(file)) {
@@ -150,12 +157,30 @@ @@ -150,12 +157,30 @@
150 const BMap = (window as any).BMap; 157 const BMap = (window as any).BMap;
151 if (!wrapEl) return; 158 if (!wrapEl) return;
152 const map = new BMap.Map(wrapEl); 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 const { lat, lng } = map.he; 165 const { lat, lng } = map.he;
155 positionState.lat = lat + ''; 166 positionState.lat = lat + '';
156 positionState.lng = lng + ''; 167 positionState.lng = lng + '';
157 let gc = new BMap.Geocoder(); 168 let gc = new BMap.Geocoder();
158 let newPoint = new BMap.Point(lng, lat); 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 gc.getLocation(newPoint, (rs) => { 184 gc.getLocation(newPoint, (rs) => {
160 let addComp = rs.addressComponents; 185 let addComp = rs.addressComponents;
161 //获取详细的地址,精确到街道的名称 186 //获取详细的地址,精确到街道的名称
@@ -163,15 +188,33 @@ @@ -163,15 +188,33 @@
163 positionState.address = addrname; 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 const handleOk = () => { 193 const handleOk = () => {
172 visible.value = false; 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 return { 216 return {
  217 + resetFields,
175 positionState, 218 positionState,
176 register, 219 register,
177 beforeUpload, 220 beforeUpload,
@@ -181,8 +224,12 @@ @@ -181,8 +224,12 @@
181 visible, 224 visible,
182 scrollRef, 225 scrollRef,
183 handleOk, 226 handleOk,
  227 + handleCancel,
184 wrapRef, 228 wrapRef,
185 labelCol: { style: { width: '40px' } }, 229 labelCol: { style: { width: '40px' } },
  230 + parentSetFieldsValue,
  231 + parentGetFieldsValue,
  232 + parentValidate,
186 }; 233 };
187 }, 234 },
188 }); 235 });
1 <template> 1 <template>
2 <div class="step2"> 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 <a-select 17 <a-select
8 - v-model:value="creaentialsType" 18 + v-model:value="creaentialsPassword.creaentialsType"
9 style="width: 200px" 19 style="width: 200px"
10 @change="handleChange" 20 @change="handleChange"
11 placeholder="请选择凭据类型" 21 placeholder="请选择凭据类型"
12 :options="options" 22 :options="options"
13 /> 23 />
14 </a-form-item> 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 </a-form-item> 28 </a-form-item>
19 </div> 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 </a-form-item> 37 </a-form-item>
24 </div> 38 </div>
25 <div v-else> 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 </a-form-item> 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 </a-form-item> 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 </a-form-item> 52 </a-form-item>
35 </div> 53 </div>
36 </a-form> 54 </a-form>
37 -  
38 <div class="flex justify-start"> 55 <div class="flex justify-start">
39 <a-button class="mr-5" @click="prevStep">上一步</a-button> 56 <a-button class="mr-5" @click="prevStep">上一步</a-button>
40 </div> 57 </div>
41 </div> 58 </div>
42 </template> 59 </template>
43 <script lang="ts"> 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 export default defineComponent({ 64 export default defineComponent({
48 components: { 65 components: {
49 [Form.name]: Form, 66 [Form.name]: Form,
@@ -52,18 +69,26 @@ @@ -52,18 +69,26 @@
52 [Select.name]: Select, 69 [Select.name]: Select,
53 [Button.name]: Button, 70 [Button.name]: Button,
54 }, 71 },
55 - emits: ['prev'], 72 +
  73 + emits: ['prev', 'next'],
56 setup(_, { emit }) { 74 setup(_, { emit }) {
57 - const isCreaentials = ref(false);  
58 - const creaentialsType = ref('Access token'); 75 + const formRef = ref();
59 const creaentialsPassword = reactive({ 76 const creaentialsPassword = reactive({
  77 + isCreaentials: false,
  78 + creaentialsType: 'Access token',
60 token: '', 79 token: '',
61 publicKey: '', 80 publicKey: '',
62 clientId: '', 81 clientId: '',
63 username: '', 82 username: '',
64 password: '', 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 value: 'Access token', 93 value: 'Access token',
69 label: 'Access token', 94 label: 'Access token',
@@ -78,41 +103,76 @@ @@ -78,41 +103,76 @@
78 label: 'MQTT Basic', 103 label: 'MQTT Basic',
79 }, 104 },
80 ]); 105 ]);
  106 + // 切换是否添加凭证
81 const checked = () => { 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 const prevStep = () => { 112 const prevStep = () => {
85 emit('prev'); 113 emit('prev');
86 }; 114 };
  115 + watch(creaentialsPassword, (newValue) => {
  116 + emit('next', newValue);
  117 + });
  118 +
87 // 切换凭证类型时,重置字段 119 // 切换凭证类型时,重置字段
88 const handleChange = (value) => { 120 const handleChange = (value) => {
89 if (value === 'Access token') { 121 if (value === 'Access token') {
90 - creaentialsPassword.token = ''; 122 + resetCreantialsType();
91 } else if (value === 'X.509') { 123 } else if (value === 'X.509') {
92 - creaentialsPassword.publicKey = ''; 124 + resetCreantialsType();
93 } else { 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 return { 157 return {
100 - ...toRefs(creaentialsPassword),  
101 - creaentialsType,  
102 - isCreaentials,  
103 options, 158 options,
  159 + formRef,
  160 + creaentialsPassword,
104 handleChange, 161 handleChange,
105 prevStep, 162 prevStep,
106 checked, 163 checked,
107 labelCol: { style: { width: '150px' } }, 164 labelCol: { style: { width: '150px' } },
108 wrapperCol: { span: 18 }, 165 wrapperCol: { span: 18 },
  166 + resetFields,
  167 + validate,
  168 + rules,
109 }; 169 };
110 }, 170 },
111 }); 171 });
112 </script> 172 </script>
113 <style lang="less" scoped> 173 <style lang="less" scoped>
114 .step2 { 174 .step2 {
115 - width: 500px; 175 + width: 700px;
116 margin: 0 auto; 176 margin: 0 auto;
117 } 177 }
118 </style> 178 </style>
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 import { FormSchema } from '/@/components/Form'; 1 import { FormSchema } from '/@/components/Form';
2 import { findDictItemByCode } from '/@/api/system/dict'; 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 export const step1Schemas: FormSchema[] = [ 7 export const step1Schemas: FormSchema[] = [
5 { 8 {
6 field: 'icon', 9 field: 'icon',
@@ -32,6 +35,30 @@ export const step1Schemas: FormSchema[] = [ @@ -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 field: 'label', 62 field: 'label',
36 label: '设备标签', 63 label: '设备标签',
37 component: 'Input', 64 component: 'Input',
@@ -40,14 +67,32 @@ export const step1Schemas: FormSchema[] = [ @@ -40,14 +67,32 @@ export const step1Schemas: FormSchema[] = [
40 }, 67 },
41 }, 68 },
42 { 69 {
43 - field: 'devicePosition', 70 + field: 'deviceAddress',
44 label: '设备位置', 71 label: '设备位置',
45 component: 'Input', 72 component: 'Input',
46 - slot: 'devicePosition', 73 + slot: 'deviceAddress',
47 }, 74 },
48 { 75 {
49 - label: '备注',  
50 field: 'remark', 76 field: 'remark',
  77 + label: '备注',
51 component: 'InputTextArea', 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 ];