Commit 505d2a8383e0b36b6d425746728919d9a5497917

Authored by sqy
1 parent cffe761b

'设备页面开发'

... ... @@ -11,6 +11,7 @@ tests/server/static/upload
11 11 # local env files
12 12 .env.local
13 13 .env.*.local
  14 +.env.development
14 15 .eslintcache
15 16
16 17 # Log files
... ...
... ... @@ -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 +};
... ...
... ... @@ -6,6 +6,7 @@
6 6 :title="getTitle"
7 7 @cancel="handleCancel"
8 8 @ok="handleOk"
  9 + centered
9 10 >
10 11 <div class="step-form-form">
11 12 <a-steps :current="current">
... ... @@ -28,9 +29,11 @@
28 29 <script lang="ts">
29 30 import { defineComponent, ref, computed, unref, reactive, toRefs } from 'vue';
30 31 import { BasicModal, useModalInner } from '/@/components/Modal';
  32 + import { createOrEditDevice } from '/@/api/device/deviceManager';
31 33 import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue';
32 34 import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue';
33 35 import { Steps } from 'ant-design-vue';
  36 + import { useMessage } from '/@/hooks/web/useMessage';
34 37 export default defineComponent({
35 38 name: 'DeviceModal',
36 39 components: {
... ... @@ -43,31 +46,42 @@
43 46 props: {
44 47 userData: { type: Object },
45 48 },
46   - setup(_) {
47   - // const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>();
  49 + setup(_, { emit }) {
48 50 const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>();
49 51 const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>();
  52 + const { createMessage } = useMessage();
50 53 const state = reactive({
51 54 initStep2: false,
52 55 });
53 56 const current = ref(0);
54 57 const isUpdate = ref(true);
55   - const modelRef = ref({});
56 58 const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备'));
57 59 // 所有参数
58   - let stepState = reactive({});
59   - const [register] = useModalInner((data) => {
  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 + }
60 71 isUpdate.value = !!data?.isUpdate;
61 72 });
62 73
  74 + // 上一步
63 75 function handleStepPrev() {
64 76 current.value--;
65 77 }
  78 + // 下一步
66 79 function handleStep1Next(step1Values: any) {
67 80 current.value++;
68 81 state.initStep2 = true;
69 82 stepState = { ...step1Values };
70 83 }
  84 + //
71 85 function handleStep2Next(step2Values: any) {
72 86 stepState = { ...stepState, ...step2Values };
73 87 }
... ... @@ -75,17 +89,34 @@
75 89 current.value = 0;
76 90 DeviceStep1Ref?.value?.resetFields();
77 91 DeviceStep2Ref?.value?.resetFields();
78   - console.log('关闭弹框');
79   - stepState = {};
80 92 }
81   - function handleOk() {
82   - // 所有参数
83   - console.log(stepState);
84   - console.log('确定了');
  93 + // 提交
  94 + async function handleOk() {
  95 + if (current.value === 0) {
  96 + // 验证
  97 + const valid = await DeviceStep1Ref.value?.parentValidate();
  98 + if (!valid) return;
  99 +
  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');
85 117 }
86 118 return {
87 119 register,
88   - model: modelRef,
89 120 getTitle,
90 121 current,
91 122 DeviceStep1Ref,
... ...
1   -import { BasicColumn } from '/@/components/Table';
2   -import { FormSchema } from '/@/components/Table';
3   -import { findDictItemByCode } from '/@/api/system/dict';
4   -import { MessageEnum } from '/@/enums/messageEnum';
5   -import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel';
6   -// 表格列数据
7   -export const columns: BasicColumn[] = [
8   - {
9   - title: '设备名称',
10   - dataIndex: 'name',
11   - width: 200,
12   - },
13   - {
14   - title: '设备类型',
15   - dataIndex: 'deviceType',
16   - width: 200,
17   - slots: { customRender: 'deviceType' },
18   - },
19   - {
20   - title: '设备配置',
21   - dataIndex: 'deviceProfile.name',
22   - width: 180,
23   - slots: { customRender: 'deviceProfile' },
24   - },
25   - {
26   - title: '标签',
27   - dataIndex: 'label',
28   - width: 180,
29   - },
30   - {
31   - title: '配置信息',
32   - dataIndex: 'deviceInfo',
33   - width: 180,
34   - slots: { customRender: 'config' },
35   - },
36   - {
37   - title: '状态',
38   - dataIndex: 'deviceState',
39   - width: 120,
40   - slots: { customRender: 'deviceState' },
41   - },
42   - {
43   - title: '最后连接时间',
44   - dataIndex: 'lastConnectTime',
45   - width: 180,
46   - },
47   - {
48   - title: '创建时间',
49   - dataIndex: 'createTime',
50   - width: 180,
51   - },
52   -];
53   -
54   -// 查询字段
55   -export const searchFormSchema: FormSchema[] = [
56   - {
57   - field: 'deviceType',
58   - label: '设备类型',
59   - component: 'Select',
60   - componentProps: {
61   - options: [
62   - { label: '网关设备', value: DeviceTypeEnum.GATEWAY },
63   - { label: '直连设备', value: DeviceTypeEnum.DIRECT_CONNECTION },
64   - { label: '网关子设备', value: DeviceTypeEnum.SENSOR },
65   - ],
66   - },
67   - colProps: { span: 4 },
68   - },
69   - {
70   - field: 'deviceState',
71   - label: '设备状态',
72   - component: 'Select',
73   - componentProps: {
74   - options: [
75   - { label: '待激活', value: DeviceState.INACTIVE },
76   - { label: '在线', value: DeviceState.ONLINE },
77   - { label: '离线', value: DeviceState.OFFLINE },
78   - ],
79   - },
80   - colProps: { span: 4 },
81   - },
82   - {
83   - field: 'name',
84   - label: '设备名称',
85   - component: 'Input',
86   - colProps: { span: 8 },
87   - },
88   -];
89   -
90   -// 弹框配置项
91   -export const formSchema: FormSchema[] = [
92   - {
93   - field: 'configName',
94   - label: '配置名称',
95   - required: true,
96   - component: 'Input',
97   - },
98   - {
99   - field: 'messageType',
100   - label: '消息类型',
101   - required: true,
102   - component: 'ApiSelect',
103   - componentProps: {
104   - api: findDictItemByCode,
105   - params: {
106   - dictCode: 'message_type',
107   - },
108   - labelField: 'itemText',
109   - valueField: 'itemValue',
110   - },
111   - },
112   - {
113   - field: 'platformType',
114   - label: '平台类型',
115   - required: true,
116   - component: 'ApiSelect',
117   - componentProps: {
118   - api: findDictItemByCode,
119   - params: {
120   - dictCode: 'platform_type',
121   - },
122   - labelField: 'itemText',
123   - valueField: 'itemValue',
124   - },
125   - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
126   - },
127   - {
128   - field: 'accessKeyId',
129   - label: 'accessKeyId',
130   - required: true,
131   - component: 'Input',
132   - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
133   - },
134   - {
135   - field: 'accessKeySecret',
136   - label: 'accessKeySecret',
137   - required: true,
138   - component: 'Input',
139   - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
140   - },
141   - {
142   - field: 'host',
143   - label: '服务器地址',
144   - defaultValue: 'smtp.163.com',
145   - required: true,
146   - component: 'Input',
147   - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
148   - },
149   - {
150   - field: 'port',
151   - label: '端口',
152   - defaultValue: 25,
153   - required: true,
154   - component: 'InputNumber',
155   - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
156   - },
157   - {
158   - field: 'username',
159   - label: '用户名',
160   - required: true,
161   - component: 'Input',
162   - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
163   - },
164   - {
165   - field: 'password',
166   - label: '密码',
167   - required: true,
168   - component: 'InputPassword',
169   - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
170   - },
171   - {
172   - field: 'config',
173   - label: '消息配置',
174   - component: 'Input',
175   - show: false,
176   - },
177   - {
178   - field: 'id',
179   - label: '主键',
180   - component: 'Input',
181   - show: false,
182   - },
183   - {
184   - field: 'status',
185   - label: '状态',
186   - component: 'RadioButtonGroup',
187   - defaultValue: 0,
188   - componentProps: {
189   - options: [
190   - { label: '启用', value: 1 },
191   - { label: '停用', value: 0 },
192   - ],
193   - },
194   - },
195   - {
196   - label: '备注',
197   - field: 'remark',
198   - component: 'InputTextArea',
199   - },
200   -];
201   -
202   -export const isMessage = (type: string) => {
203   - return type === MessageEnum.IS_SMS;
204   -};
205   -export const isEmail = (type: string) => {
206   - return type === MessageEnum.IS_EMAIL;
207   -};
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 });
... ...
... ... @@ -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 />
... ... @@ -59,7 +66,6 @@
59 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, resetFields }] = 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,14 +188,31 @@
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 {
175 217 resetFields,
176 218 positionState,
... ... @@ -182,8 +224,12 @@
182 224 visible,
183 225 scrollRef,
184 226 handleOk,
  227 + handleCancel,
185 228 wrapRef,
186 229 labelCol: { style: { width: '40px' } },
  230 + parentSetFieldsValue,
  231 + parentGetFieldsValue,
  232 + parentValidate,
187 233 };
188 234 },
189 235 });
... ...
... ... @@ -4,15 +4,16 @@
4 4 ><input type="checkbox" v-model="creaentialsPassword.isCreaentials" @click="checked" />
5 5 添加凭证
6 6 </div>
7   -
8 7 <a-form
9 8 ref="formRef"
  9 + :rules="rules"
10 10 :label-col="labelCol"
11 11 :wrapper-col="wrapperCol"
12   - v-if="creaentialsPassword.isCreaentials"
  12 + v-show="creaentialsPassword.isCreaentials"
13 13 :model="creaentialsPassword"
  14 + labelAlign="left"
14 15 >
15   - <a-form-item label="凭据类型" name="creantialsType">
  16 + <a-form-item label="凭据类型" name="creaentialsType">
16 17 <a-select
17 18 v-model:value="creaentialsPassword.creaentialsType"
18 19 style="width: 200px"
... ... @@ -23,13 +24,13 @@
23 24 </a-form-item>
24 25 <div v-if="creaentialsPassword.creaentialsType === 'Access token'">
25 26 <a-form-item label="访问令牌" name="token">
26   - <a-input type="input" style="width: 200px" v-model:value="creaentialsPassword.token" />
  27 + <a-input type="password" style="width: 200px" v-model:value="creaentialsPassword.token" />
27 28 </a-form-item>
28 29 </div>
29 30 <div v-else-if="creaentialsPassword.creaentialsType === 'X.509'">
30 31 <a-form-item label="RSA公钥" name="publicKey">
31 32 <a-input
32   - type="input"
  33 + type="password"
33 34 style="width: 200px"
34 35 v-model:value="creaentialsPassword.publicKey"
35 36 />
... ... @@ -51,7 +52,6 @@
51 52 </a-form-item>
52 53 </div>
53 54 </a-form>
54   -
55 55 <div class="flex justify-start">
56 56 <a-button class="mr-5" @click="prevStep">上一步</a-button>
57 57 </div>
... ... @@ -69,6 +69,7 @@
69 69 [Select.name]: Select,
70 70 [Button.name]: Button,
71 71 },
  72 +
72 73 emits: ['prev', 'next'],
73 74 setup(_, { emit }) {
74 75 const formRef = ref();
... ... @@ -81,6 +82,12 @@
81 82 username: '',
82 83 password: '',
83 84 });
  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 + };
84 91 const options = ref([
85 92 {
86 93 value: 'Access token',
... ... @@ -96,8 +103,11 @@
96 103 label: 'MQTT Basic',
97 104 },
98 105 ]);
  106 + // 切换是否添加凭证
99 107 const checked = () => {
100 108 creaentialsPassword.isCreaentials = !creaentialsPassword.isCreaentials;
  109 + formRef.value.resetFields();
  110 + creaentialsPassword.creaentialsType = 'Access token';
101 111 };
102 112 const prevStep = () => {
103 113 emit('prev');
... ... @@ -109,21 +119,40 @@
109 119 // 切换凭证类型时,重置字段
110 120 const handleChange = (value) => {
111 121 if (value === 'Access token') {
112   - creaentialsPassword.token = '';
  122 + resetCreantialsType();
113 123 } else if (value === 'X.509') {
114   - creaentialsPassword.publicKey = '';
  124 + resetCreantialsType();
115 125 } else {
116   - creaentialsPassword.clientId = '';
117   - creaentialsPassword.username = '';
118   - creaentialsPassword.password = '';
  126 + resetCreantialsType();
119 127 }
120 128 };
  129 + // 切换凭证类型时,重置字段
  130 + function resetCreantialsType() {
  131 + creaentialsPassword.token = '';
  132 + creaentialsPassword.publicKey = '';
  133 + creaentialsPassword.clientId = '';
  134 + creaentialsPassword.username = '';
  135 + creaentialsPassword.password = '';
  136 + }
121 137
122 138 // 重置所有字段
123 139 function resetFields() {
124   - console.log(formRef);
  140 + creaentialsPassword.isCreaentials = false;
  141 + creaentialsPassword.creaentialsType = 'Access token';
  142 + creaentialsPassword.token = '';
  143 + creaentialsPassword.publicKey = '';
  144 + creaentialsPassword.clientId = '';
  145 + creaentialsPassword.username = '';
  146 + creaentialsPassword.password = '';
125 147 formRef.value.resetFields();
126   - console.log('----');
  148 + }
  149 +
  150 + // 表单验证
  151 + function validate() {
  152 + if (creaentialsPassword.isCreaentials) {
  153 + return formRef.value.validate();
  154 + }
  155 + return true;
127 156 }
128 157 return {
129 158 options,
... ... @@ -135,13 +164,15 @@
135 164 labelCol: { style: { width: '150px' } },
136 165 wrapperCol: { span: 18 },
137 166 resetFields,
  167 + validate,
  168 + rules,
138 169 };
139 170 },
140 171 });
141 172 </script>
142 173 <style lang="less" scoped>
143 174 .step2 {
144   - width: 500px;
  175 + width: 700px;
145 176 margin: 0 auto;
146 177 }
147 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 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 ];
... ...