Commit c800aa8794189f1a3db98872b52b56347c60ef77

Authored by sqy
1 parent caabfc6a

'设备页面开发'

... ... @@ -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.129:8082/api"],["/upload","http://192.168.10.122:3300/upload"]]
  9 +VITE_PROXY = [["/api","http://192.168.10.120:8082/api"],["/upload","http://192.168.10.120:3300/upload"]]
10 10 # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
11 11
12 12 # Delete console
... ...
  1 +export function useChildrenIdsRemoveParentId(str, arr) {
  2 + const index = arr.indexOf(str);
  3 + arr.splice(index, 1);
  4 + return arr;
  5 +}
... ...
... ... @@ -3,11 +3,11 @@
3 3 <OrganizationIdTree class="w-1/4 xl:w-1/5" @select="handleSelect" />
4 4 <BasicTable @register="registerTable" :searchInfo="searchInfo" class="w-3/4 xl:w-4/5">
5 5 <template #toolbar>
6   - <a-button type="primary" @click="handleCreateOrEdit"> 新增联系人 </a-button>
  6 + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增联系人 </a-button>
7 7 <a-button
8 8 type="primary"
9 9 color="error"
10   - @click="handleDeleteOrBatchDelete"
  10 + @click="handleDeleteOrBatchDelete(null)"
11 11 :disabled="hasBatchDelete"
12 12 >
13 13 批量删除
... ... @@ -46,7 +46,6 @@
46 46 import { useDrawer } from '/@/components/Drawer';
47 47 import ContactDrawer from './ContactDrawer.vue';
48 48 import OrganizationIdTree from '../../common/OrganizationIdTree.vue';
49   - import { Modal } from 'ant-design-vue';
50 49 import { getAlarmContact, deleteAlarmContact } from '/@/api/alarm/contact/alarmContact';
51 50 import { searchFormSchema, columns } from './config.data';
52 51 export default defineComponent({
... ... @@ -121,15 +120,11 @@
121 120 }
122 121 } else {
123 122 try {
124   - await Modal.confirm({
125   - title: '警告',
126   - content: '是否删除勾选的信息?',
127   - });
128 123 await deleteAlarmContact(selectedRowIds.value);
129 124 createMessage.success('批量删除联系人成功');
130 125 handleSuccess();
131 126 } catch (e) {
132   - createMessage.info('取消删除');
  127 + createMessage.info('删除失败');
133 128 }
134 129 }
135 130 };
... ...
1   -<template>
2   - <BasicDrawer
3   - v-bind="$attrs"
4   - @register="registerDrawer"
5   - showFooter
6   - :title="getTitle"
7   - width="500px"
8   - @ok="handleSubmit"
9   - >
10   - <BasicForm @register="registerForm">
11   - <template #iconSelect>
12   - <Upload
13   - name="avatar"
14   - list-type="picture-card"
15   - class="avatar-uploader"
16   - :show-upload-list="false"
17   - :customRequest="customUpload"
18   - :before-upload="beforeUpload"
19   - >
20   - <img v-if="devicePic" :src="devicePic" alt="avatar" />
21   - <div v-else>
22   - <loading-outlined v-if="loading" />
23   - <plus-outlined v-else />
24   - <div class="ant-upload-text">图片上传</div>
25   - </div>
26   - </Upload>
27   - </template>
28   - </BasicForm>
29   - </BasicDrawer>
30   -</template>
31   -<script lang="ts">
32   - import { defineComponent, ref, computed, unref } from 'vue';
33   - import { BasicForm, useForm } from '/@/components/Form';
34   - import { formSchema } from './device.data';
35   - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
36   -
37   - import { saveOrEditMessageConfig } from '/@/api/message/config';
38   - import { useMessage } from '/@/hooks/web/useMessage';
39   - import { upload } from '/@/api/oss/ossFileUploader';
40   - import { message, Upload } from 'ant-design-vue';
41   - import { FileItem } from '/@/components/Upload/src/typing';
42   - import { LoadingOutlined, PlusOutlined } from '@ant-design/icons-vue';
43   -
44   - export default defineComponent({
45   - name: 'DeviceDrawer',
46   - components: { BasicDrawer, BasicForm, Upload, PlusOutlined, LoadingOutlined },
47   - emits: ['success', 'register'],
48   - setup(_, { emit }) {
49   - const isUpdate = ref(true);
50   -
51   - const devicePic = ref('');
52   - const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
53   - labelWidth: 80,
54   - schemas: formSchema,
55   - showActionButtonGroup: false,
56   - });
57   -
58   - const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
59   - await resetFields();
60   - setDrawerProps({ confirmLoading: false });
61   - isUpdate.value = !!data?.isUpdate;
62   - if (unref(isUpdate)) {
63   - const config = data.record.config;
64   - for (const key in config) {
65   - Reflect.set(data.record, key + '', config[key]);
66   - }
67   - await setFieldsValue({
68   - ...data.record,
69   - });
70   - }
71   - });
72   -
73   - const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备'));
74   -
75   - async function handleSubmit() {
76   - try {
77   - const values = await validate();
78   - const { createMessage } = useMessage();
79   - setDrawerProps({ confirmLoading: true });
80   - let config = {};
81   - if (values.messageType === 'PHONE_MESSAGE') {
82   - config = {
83   - accessKeyId: values.accessKeyId,
84   - accessKeySecret: values.accessKeySecret,
85   - };
86   - } else if (values.messageType === 'EMAIL_MESSAGE') {
87   - config = {
88   - host: values.host,
89   - port: values.port,
90   - username: values.username,
91   - password: values.password,
92   - };
93   - }
94   - Reflect.set(values, 'config', config);
95   - let saveMessage = '添加成功';
96   - let updateMessage = '修改成功';
97   - await saveOrEditMessageConfig(values, unref(isUpdate));
98   - closeDrawer();
99   - emit('success');
100   - createMessage.success(unref(isUpdate) ? updateMessage : saveMessage);
101   - } finally {
102   - setDrawerProps({ confirmLoading: false });
103   - }
104   - }
105   - async function customUpload({ file }) {
106   - if (beforeUpload(file)) {
107   - const formData = new FormData();
108   - formData.append('file', file);
109   - const response = await upload(formData);
110   - if (response.fileStaticUri) {
111   - devicePic.value = response.fileStaticUri;
112   - }
113   - }
114   - }
115   -
116   - const beforeUpload = (file: FileItem) => {
117   - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
118   - if (!isJpgOrPng) {
119   - message.error('只能上传图片文件!');
120   - }
121   - const isLt2M = (file.size as number) / 1024 / 1024 < 2;
122   - if (!isLt2M) {
123   - message.error('图片大小不能超过2MB!');
124   - }
125   - return isJpgOrPng && isLt2M;
126   - };
127   - return {
128   - registerDrawer,
129   - registerForm,
130   - getTitle,
131   - handleSubmit,
132   - beforeUpload,
133   - customUpload,
134   - devicePic,
135   - };
136   - },
137   - });
138   -</script>
139   -<style>
140   - .ant-upload-select-picture-card i {
141   - font-size: 32px;
142   - color: #999;
143   - }
144   -</style>
... ... @@ -3,14 +3,14 @@
3 3 v-bind="$attrs"
4 4 width="55rem"
5 5 @register="register"
6   - :title=getTitle
  6 + :title="getTitle"
7 7 @visible-change="handleVisibleChange"
  8 + @cancel="handleCancel"
8 9 >
9 10 <div class="step-form-form">
10 11 <a-steps :current="current">
11 12 <a-step title="填写设备信息" />
12   - <a-step title="确认转账信息" />
13   - <a-step title="完成" />
  13 + <a-step title="添加设备凭证" />
14 14 </a-steps>
15 15 </div>
16 16 <div class="mt-5">
... ... @@ -21,68 +21,35 @@
21 21 v-show="current === 1"
22 22 v-if="initStep2"
23 23 />
24   - <DeviceStep3 v-show="current === 2" @redo="handleRedo" v-if="initStep3" />
25 24 </div>
26 25 </BasicModal>
27 26 </template>
28 27 <script lang="ts">
29   -import {defineComponent, ref, nextTick, computed, unref, reactive, toRefs} from 'vue';
  28 + import { defineComponent, ref, nextTick, computed, unref, reactive, toRefs } from 'vue';
30 29 import { BasicModal, useModalInner } from '/@/components/Modal';
31   - import { BasicForm, FormSchema, useForm } from '/@/components/Form';
32   - import DeviceStep1 from "/@/views/device/step/DeviceStep1.vue";
33   - import DeviceStep2 from "/@/views/device/step/DeviceStep2.vue";
34   - import DeviceStep3 from "/@/views/device/step/DeviceStep3.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   - ];
  30 + import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue';
  31 + import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue';
  32 + import { Steps } from 'ant-design-vue';
55 33 export default defineComponent({
56   - name:'DeviceModal',
57   - components: { BasicModal, BasicForm, DeviceStep1, DeviceStep2, DeviceStep3,
  34 + name: 'DeviceModal',
  35 + components: {
  36 + BasicModal,
  37 + DeviceStep1,
  38 + DeviceStep2,
58 39 [Steps.name]: Steps,
59   - [Steps.Step.name]: Steps.Step, },
  40 + [Steps.Step.name]: Steps.Step,
  41 + },
60 42 props: {
61 43 userData: { type: Object },
62 44 },
63 45 setup(props) {
64 46 const state = reactive({
65 47 initStep2: false,
66   - initStep3: false,
67 48 });
68 49 const current = ref(0);
69 50 const isUpdate = ref(true);
70 51 const modelRef = ref({});
71 52 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 53
87 54 const [register] = useModalInner((data) => {
88 55 isUpdate.value = !!data?.isUpdate;
... ... @@ -99,15 +66,15 @@ import {defineComponent, ref, nextTick, computed, unref, reactive, toRefs} from
99 66 }
100 67 function handleStep2Next(step2Values: any) {
101 68 current.value++;
102   - state.initStep3 = true;
103 69 console.log(step2Values);
104 70 }
105 71 function handleRedo() {
106 72 current.value = 0;
107   - state.initSetp2 = false;
108   - state.initSetp3 = false;
  73 + state.initStep2 = false;
  74 + }
  75 + function handleCancel() {
  76 + console.log('关闭了弹框');
109 77 }
110   -
111 78
112 79 function onDataReceive(data) {
113 80 console.log('Data Received', data);
... ... @@ -129,8 +96,19 @@ import {defineComponent, ref, nextTick, computed, unref, reactive, toRefs} from
129 96 v && props.userData && nextTick(() => onDataReceive(props.userData));
130 97 }
131 98
132   - return { register, schemas, registerForm, model: modelRef, getTitle,handleVisibleChange,
133   - current, ...toRefs(state), handleStepPrev, handleStep1Next, handleStep2Next, handleRedo};
  99 + return {
  100 + register,
  101 + model: modelRef,
  102 + getTitle,
  103 + handleVisibleChange,
  104 + current,
  105 + ...toRefs(state),
  106 + handleStepPrev,
  107 + handleStep1Next,
  108 + handleStep2Next,
  109 + handleCancel,
  110 + handleRedo,
  111 + };
134 112 },
135 113 });
136 114 </script>
... ...
1 1 import { BasicColumn } from '/@/components/Table';
2 2 import { FormSchema } from '/@/components/Table';
3   -import {findDictItemByCode} from "/@/api/system/dict";
4   -import {DeviceTypeEnum,DeviceState} from "/@/api/device/model/deviceModel";
  3 +import { findDictItemByCode } from '/@/api/system/dict';
  4 +import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel';
5 5 export const columns: BasicColumn[] = [
6 6 {
7 7 title: '设备名称',
... ... @@ -12,7 +12,7 @@ export const columns: BasicColumn[] = [
12 12 title: '设备类型',
13 13 dataIndex: 'deviceType',
14 14 width: 100,
15   - slots:{customRender:'deviceType'},
  15 + slots: { customRender: 'deviceType' },
16 16 },
17 17 {
18 18 title: '设备配置',
... ... @@ -29,7 +29,7 @@ export const columns: BasicColumn[] = [
29 29 {
30 30 title: '标签',
31 31 dataIndex: 'label',
32   - width: 180
  32 + width: 180,
33 33 },
34 34 {
35 35 title: '状态',
... ... @@ -80,7 +80,6 @@ export const searchFormSchema: FormSchema[] = [
80 80 },
81 81 ];
82 82
83   -
84 83 export const formSchema: FormSchema[] = [
85 84 {
86 85 field: 'icon',
... ... @@ -92,10 +91,10 @@ export const formSchema: FormSchema[] = [
92 91 field: 'name',
93 92 label: '设备名称',
94 93 required: true,
95   - component:'Input',
96   - componentProps:{
97   - maxLength:30
98   - }
  94 + component: 'Input',
  95 + componentProps: {
  96 + maxLength: 30,
  97 + },
99 98 },
100 99 {
101 100 field: 'deviceType',
... ... @@ -103,25 +102,25 @@ export const formSchema: FormSchema[] = [
103 102 required: true,
104 103 component: 'ApiSelect',
105 104 componentProps: {
106   - api:findDictItemByCode,
107   - params:{
108   - dictCode:"device_type"
  105 + api: findDictItemByCode,
  106 + params: {
  107 + dictCode: 'device_type',
109 108 },
110   - labelField:'itemText',
111   - valueField:'itemValue',
  109 + labelField: 'itemText',
  110 + valueField: 'itemValue',
112 111 },
113 112 },
114 113 {
115 114 field: 'label',
116 115 label: '设备标签',
117   - component:'Input',
118   - componentProps:{
119   - maxLength:255
120   - }
  116 + component: 'Input',
  117 + componentProps: {
  118 + maxLength: 255,
  119 + },
121 120 },
122 121 {
123 122 label: '备注',
124 123 field: 'remark',
125 124 component: 'InputTextArea',
126   - }
  125 + },
127 126 ];
... ...
... ... @@ -16,9 +16,9 @@
16 16 <template #deviceType="{ record }">
17 17 <Tag color="success" class="ml-2">
18 18 {{
19   - record.deviceType == DeviceTypeEnum.GATEWAY
  19 + record.deviceType === DeviceTypeEnum.GATEWAY
20 20 ? '网关设备'
21   - : record.deviceType == DeviceTypeEnum.DIRECT_CONNECTION
  21 + : record.deviceType === DeviceTypeEnum.DIRECT_CONNECTION
22 22 ? '直连设备'
23 23 : '网关子设备'
24 24 }}
... ... @@ -65,7 +65,7 @@
65 65 />
66 66 </template>
67 67 </BasicTable>
68   - <ConfigDrawer @register="registerDrawer" @success="handleSuccess" />
  68 + <!-- <ConfigDrawer @register="registerDrawer" @success="handleSuccess" /> -->
69 69 <DeviceModal @register="registerModal" @success="handleSuccess" />
70 70 </PageWrapper>
71 71 </template>
... ... @@ -73,11 +73,10 @@
73 73 import { defineComponent, reactive } from 'vue';
74 74 import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel';
75 75 import { BasicTable, useTable, TableAction } from '/@/components/Table';
76   - import { useDrawer } from '/@/components/Drawer';
77   - import ConfigDrawer from './DeviceDrawer.vue';
  76 + // import { useDrawer } from '/@/components/Drawer';
  77 + // import ConfigDrawer from './DeviceDrawer.vue';
78 78 import { columns, searchFormSchema } from './device.data';
79 79 import { Tag } from 'ant-design-vue';
80   - import { CodeEditor } from '/@/components/CodeEditor';
81 80 import { useMessage } from '/@/hooks/web/useMessage';
82 81 import { deleteDevice, devicePage } from '/@/api/device/deviceManager';
83 82 import { PageEnum } from '/@/enums/pageEnum';
... ... @@ -91,16 +90,15 @@
91 90 name: 'DeviceManagement',
92 91 components: {
93 92 BasicTable,
94   - ConfigDrawer,
  93 + // ConfigDrawer,
95 94 PageWrapper,
96 95 TableAction,
97 96 OrganizationIdTree,
98   - CodeEditor,
99 97 Tag,
100 98 DeviceModal,
101 99 },
102 100 setup() {
103   - const [registerDrawer, { openDrawer }] = useDrawer();
  101 + // const [registerDrawer, { openDrawer }] = useDrawer();
104 102 const { createMessage } = useMessage();
105 103 const go = useGo();
106 104 const searchInfo = reactive<Recordable>({});
... ... @@ -128,18 +126,15 @@
128 126 });
129 127
130 128 function handleCreate() {
131   - // openDrawer(true, {
132   - // isUpdate: false,
133   - // });
134 129 openModal(true, {
135 130 isUpdate: false,
136 131 });
137 132 }
138 133
139 134 function handleEdit(record: Recordable) {
140   - openDrawer(true, {
141   - record,
  135 + openModal(true, {
142 136 isUpdate: true,
  137 + record,
143 138 });
144 139 }
145 140
... ... @@ -163,7 +158,7 @@
163 158 }
164 159 return {
165 160 registerTable,
166   - registerDrawer,
  161 + // registerDrawer,
167 162 handleCreate,
168 163 handleEdit,
169 164 handleDelete,
... ...
... ... @@ -20,7 +20,7 @@
20 20 </Upload>
21 21 </template>
22 22 <template #devicePosition>
23   - <Input>
  23 + <Input disabled v-model:value="positionState.address">
24 24 <template #addonAfter>
25 25 <EnvironmentTwoTone @click="selectPosition" />
26 26 </template>
... ... @@ -28,27 +28,34 @@
28 28 </template>
29 29 </BasicForm>
30 30 </div>
31   - <modal v-model:visible="visible" title="设备位置" @ok="handleOk">
  31 + <Modal v-model:visible="visible" title="设备位置" @ok="handleOk" width="800px">
32 32 <div>
33   - <a-input-group>
34   - <a-row :gutter="8" class="flex">
35   - <a-col :span="6" class="flex"> 经度<a-input /> </a-col>
36   - <a-col :span="6" class="flex"> 纬度<a-input /> </a-col>
  33 + <a-form :label-col="labelCol">
  34 + <a-row :gutter="20">
  35 + <a-col :span="8">
  36 + <a-form-item label="经度">
  37 + <Input type="input" v-model:value="positionState.lng" disabled />
  38 + </a-form-item>
  39 + </a-col>
  40 + <a-col :span="8">
  41 + <a-form-item label="纬度">
  42 + <Input type="input" v-model:value="positionState.lat" disabled />
  43 + </a-form-item>
  44 + </a-col>
37 45 </a-row>
38   - </a-input-group>
39   - <div ref="wrapRef" style="height: 300px; width: 90%" class=""> </div>
  46 + </a-form>
  47 + <div ref="wrapRef" style="height: 300px; width: 90%" class="ml-6"></div>
40 48 </div>
41   - </modal>
42   - >
  49 + </Modal>
43 50 </div>
44 51 </template>
45 52 <script lang="ts">
46   - import { defineComponent, ref, onMounted, nextTick, unref, getCurrentInstance } from 'vue';
  53 + import { defineComponent, ref, nextTick, unref, reactive } from 'vue';
47 54 import { BasicForm, useForm } from '/@/components/Form';
48 55 import { step1Schemas } from './data';
49 56 import { useScript } from '/@/hooks/web/useScript';
50 57 import { ScrollActionType } from '/@/components/Container/index';
51   - import { Input, Divider, Upload, message, Modal, Col, Row } from 'ant-design-vue';
  58 + import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue';
52 59 import { EnvironmentTwoTone, LoadingOutlined, PlusOutlined } from '@ant-design/icons-vue';
53 60 import { upload } from '/@/api/oss/ossFileUploader';
54 61 import { FileItem } from '/@/components/Upload/src/typing';
... ... @@ -64,24 +71,19 @@
64 71 // LoadingOutlined,
65 72 PlusOutlined,
66 73 Modal,
67   - [Col.name]: Col,
  74 + [Form.name]: Form,
  75 + [Form.Item.name]: Form.Item,
68 76 [Row.name]: Row,
69   - },
70   - props: {
71   - width: {
72   - type: String,
73   - default: '300px',
74   - },
75   - height: {
76   - type: String,
77   - default: '300px',
78   - },
  77 + [Col.name]: Col,
79 78 },
80 79 emits: ['next'],
81 80 setup(_, { emit }) {
82   - const { proxy } = getCurrentInstance();
83   - console.log(proxy);
84 81 const devicePic = ref('');
  82 + const positionState = reactive({
  83 + lng: '',
  84 + lat: '',
  85 + address: '',
  86 + });
85 87 const [register, { validate }] = useForm({
86 88 labelWidth: 100,
87 89 schemas: step1Schemas,
... ... @@ -97,10 +99,15 @@
97 99
98 100 async function customSubmitFunc() {
99 101 try {
100   - const values = await validate();
  102 + let values = await validate();
  103 + values = { devicePic: devicePic.value, ...positionState, ...values };
  104 + delete values.icon;
  105 + delete values.devicePosition;
101 106 emit('next', values);
  107 + // 获取输入的数据
102 108 } catch (error) {}
103 109 }
  110 + // 图片上传
104 111 async function customUpload({ file }) {
105 112 if (beforeUpload(file)) {
106 113 const formData = new FormData();
... ... @@ -111,7 +118,6 @@
111 118 }
112 119 }
113 120 }
114   -
115 121 const beforeUpload = (file: FileItem) => {
116 122 const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
117 123 if (!isJpgOrPng) {
... ... @@ -123,12 +129,15 @@
123 129 }
124 130 return isJpgOrPng && isLt2M;
125 131 };
  132 +
  133 + // 地图的弹框
126 134 const visible = ref(false);
127 135 const selectPosition = () => {
128 136 visible.value = true;
129 137 initMap();
130 138 };
131 139
  140 + // 地图
132 141 const BAI_DU_MAP_URL =
133 142 'https://api.map.baidu.com/getscript?v=3.0&ak=7uOPPyAHn2Y2ZryeQqHtcRqtIY374vKa';
134 143 const wrapRef = ref<HTMLDivElement | null>(null);
... ... @@ -139,16 +148,31 @@
139 148 await nextTick();
140 149 const wrapEl = unref(wrapRef);
141 150 const BMap = (window as any).BMap;
142   - console.log(wrapRef, '----------------------------');
143 151 if (!wrapEl) return;
144 152 const map = new BMap.Map(wrapEl);
145   - const point = new BMap.Point(116.14282, 35.19515);
  153 + map.addEventListener('click', () => {
  154 + const { lat, lng } = map.he;
  155 + positionState.lat = lat + '';
  156 + positionState.lng = lng + '';
  157 + let gc = new BMap.Geocoder();
  158 + let newPoint = new BMap.Point(lng, lat);
  159 + gc.getLocation(newPoint, (rs) => {
  160 + let addComp = rs.addressComponents;
  161 + //获取详细的地址,精确到街道的名称
  162 + let addrname = addComp.city + addComp.district + addComp.street + addComp.streetNumber;
  163 + positionState.address = addrname;
  164 + });
  165 + });
  166 + const point = new BMap.Point(104.04813399999999, 30.54348986021446);
146 167 map.centerAndZoom(point, 15);
147 168 map.enableScrollWheelZoom(true);
148 169 }
149   - const handleOk = () => {};
150   -
  170 + // 确定选择的位置
  171 + const handleOk = () => {
  172 + visible.value = false;
  173 + };
151 174 return {
  175 + positionState,
152 176 register,
153 177 beforeUpload,
154 178 customUpload,
... ... @@ -158,6 +182,7 @@
158 182 scrollRef,
159 183 handleOk,
160 184 wrapRef,
  185 + labelCol: { style: { width: '40px' } },
161 186 };
162 187 },
163 188 });
... ...
1 1 <template>
2 2 <div class="step2">
3   - <a-alert message="确认转账后,资金将直接打入对方账户,无法退回。" show-icon />
4   - <a-descriptions :column="1" class="mt-5">
5   - <a-descriptions-item label="付款账户"> ant-design@alipay.com </a-descriptions-item>
6   - <a-descriptions-item label="收款账户"> test@example.com </a-descriptions-item>
7   - <a-descriptions-item label="收款人姓名"> Vben </a-descriptions-item>
8   - <a-descriptions-item label="转账金额"> 500元 </a-descriptions-item>
9   - </a-descriptions>
10   - <a-divider />
11   - <BasicForm @register="register" />
  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="凭据类型">
  7 + <a-select
  8 + v-model:value="creaentialsType"
  9 + style="width: 200px"
  10 + @change="handleChange"
  11 + placeholder="请选择凭据类型"
  12 + :options="options"
  13 + />
  14 + </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" />
  18 + </a-form-item>
  19 + </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" />
  23 + </a-form-item>
  24 + </div>
  25 + <div v-else>
  26 + <a-form-item label="客户端ID">
  27 + <a-input type="input" style="width: 200px" v-model:value="clientId" />
  28 + </a-form-item>
  29 + <a-form-item label="用户名">
  30 + <a-input type="input" style="width: 200px" v-model:value="username" />
  31 + </a-form-item>
  32 + <a-form-item label="密码">
  33 + <a-input type="password" style="width: 200px" v-model:value="password" />
  34 + </a-form-item>
  35 + </div>
  36 + </a-form>
  37 +
  38 + <div class="flex justify-start">
  39 + <a-button class="mr-5" @click="prevStep">上一步</a-button>
  40 + </div>
12 41 </div>
13 42 </template>
14 43 <script lang="ts">
15   - import { defineComponent } from 'vue';
16   - import { BasicForm, useForm } from '/@/components/Form';
17   - import { step2Schemas } from './data';
18   - import { Alert, Divider, Descriptions } from 'ant-design-vue';
  44 + import { defineComponent, reactive, ref, toRefs } from 'vue';
19 45
  46 + import { Input, Form, Select, Button, SelectProps } from 'ant-design-vue';
20 47 export default defineComponent({
21 48 components: {
22   - BasicForm,
23   - [Alert.name]: Alert,
24   - [Divider.name]: Divider,
25   - [Descriptions.name]: Descriptions,
26   - [Descriptions.Item.name]: Descriptions.Item,
  49 + [Form.name]: Form,
  50 + [Form.Item.name]: Form.Item,
  51 + [Input.name]: Input,
  52 + [Select.name]: Select,
  53 + [Button.name]: Button,
27 54 },
28   - emits: ['next', 'prev'],
  55 + emits: ['prev'],
29 56 setup(_, { emit }) {
30   - const [register, { validate, setProps }] = useForm({
31   - labelWidth: 80,
32   - schemas: step2Schemas,
33   - actionColOptions: {
34   - span: 14,
  57 + const isCreaentials = ref(false);
  58 + const creaentialsType = ref('Access token');
  59 + const creaentialsPassword = reactive({
  60 + token: '',
  61 + publicKey: '',
  62 + clientId: '',
  63 + username: '',
  64 + password: '',
  65 + });
  66 + const options = ref<SelectProps['options']>([
  67 + {
  68 + value: 'Access token',
  69 + label: 'Access token',
35 70 },
36   - resetButtonOptions: {
37   - text: '上一步',
  71 +
  72 + {
  73 + value: 'X.509',
  74 + label: 'X.509',
38 75 },
39   - submitButtonOptions: {
40   - text: '提交',
  76 + {
  77 + value: 'MQTT Basic',
  78 + label: 'MQTT Basic',
41 79 },
42   - resetFunc: customResetFunc,
43   - submitFunc: customSubmitFunc,
44   - });
45   -
46   - async function customResetFunc() {
  80 + ]);
  81 + const checked = () => {
  82 + isCreaentials.value = !isCreaentials.value;
  83 + };
  84 + const prevStep = () => {
47 85 emit('prev');
48   - }
49   -
50   - async function customSubmitFunc() {
51   - try {
52   - const values = await validate();
53   - setProps({
54   - submitButtonOptions: {
55   - loading: true,
56   - },
57   - });
58   - setTimeout(() => {
59   - setProps({
60   - submitButtonOptions: {
61   - loading: false,
62   - },
63   - });
64   - emit('next', values);
65   - }, 1500);
66   - } catch (error) {}
67   - }
68   -
69   - return { register };
  86 + };
  87 + // 切换凭证类型时,重置字段
  88 + const handleChange = (value) => {
  89 + if (value === 'Access token') {
  90 + creaentialsPassword.token = '';
  91 + } else if (value === 'X.509') {
  92 + creaentialsPassword.publicKey = '';
  93 + } else {
  94 + creaentialsPassword.clientId = '';
  95 + creaentialsPassword.username = '';
  96 + creaentialsPassword.password = '';
  97 + }
  98 + };
  99 + return {
  100 + ...toRefs(creaentialsPassword),
  101 + creaentialsType,
  102 + isCreaentials,
  103 + options,
  104 + handleChange,
  105 + prevStep,
  106 + checked,
  107 + labelCol: { style: { width: '150px' } },
  108 + wrapperCol: { span: 18 },
  109 + };
70 110 },
71 111 });
72 112 </script>
73 113 <style lang="less" scoped>
74 114 .step2 {
75   - width: 450px;
  115 + width: 500px;
76 116 margin: 0 auto;
77 117 }
78 118 </style>
... ...
1   -<template>
2   - <div class="step3">
3   - <a-result status="success" title="操作成功" sub-title="预计两小时内到账">
4   - <template #extra>
5   - <a-button type="primary" @click="redo"> 再转一笔 </a-button>
6   - <a-button> 查看账单 </a-button>
7   - </template>
8   - </a-result>
9   - <div class="desc-wrap">
10   - <a-descriptions :column="1" class="mt-5">
11   - <a-descriptions-item label="付款账户"> ant-design@alipay.com </a-descriptions-item>
12   - <a-descriptions-item label="收款账户"> test@example.com </a-descriptions-item>
13   - <a-descriptions-item label="收款人姓名"> Vben </a-descriptions-item>
14   - <a-descriptions-item label="转账金额"> 500元 </a-descriptions-item>
15   - </a-descriptions>
16   - </div>
17   - </div>
18   -</template>
19   -<script lang="ts">
20   - import { defineComponent } from 'vue';
21   - import { Result, Descriptions } from 'ant-design-vue';
22   - export default defineComponent({
23   - components: {
24   - [Result.name]: Result,
25   - [Descriptions.name]: Descriptions,
26   - [Descriptions.Item.name]: Descriptions.Item,
27   - },
28   - emits: ['redo'],
29   - setup(_, { emit }) {
30   - return {
31   - redo: () => {
32   - emit('redo');
33   - },
34   - };
35   - },
36   - });
37   -</script>
38   -<style lang="less" scoped>
39   - .step3 {
40   - width: 600px;
41   - margin: 0 auto;
42   - }
43   -
44   - .desc-wrap {
45   - padding: 24px 40px;
46   - margin-top: 24px;
47   - background-color: @background-color-light;
48   - }
49   -</style>
src/views/device/step/StepIndexDemo.vue renamed from src/views/device/step/StepIndex.vue
... ... @@ -20,7 +20,6 @@
20 20 v-show="current === 1"
21 21 v-if="initSetp2"
22 22 />
23   - <Step3 v-show="current === 2" @redo="handleRedo" v-if="initSetp3" />
24 23 </div>
25 24 </PageWrapper>
26 25 </template>
... ... @@ -28,7 +27,6 @@
28 27 import { defineComponent, ref, reactive, toRefs } from 'vue';
29 28 import Step1 from './DeviceStep1.vue';
30 29 import Step2 from './DeviceStep2.vue';
31   - import Step3 from './DeviceStep3.vue';
32 30 import { PageWrapper } from '/@/components/Page';
33 31 import { Steps } from 'ant-design-vue';
34 32
... ... @@ -37,17 +35,16 @@
37 35 components: {
38 36 Step1,
39 37 Step2,
40   - Step3,
  38 +
41 39 PageWrapper,
42 40 [Steps.name]: Steps,
43 41 [Steps.Step.name]: Steps.Step,
44 42 },
45 43 setup() {
46   - const current = ref(0);
  44 + const current = ref(1);
47 45
48 46 const state = reactive({
49 47 initSetp2: false,
50   - initSetp3: false,
51 48 });
52 49
53 50 function handleStep1Next(step1Values: any) {
... ... @@ -62,14 +59,12 @@
62 59
63 60 function handleStep2Next(step2Values: any) {
64 61 current.value++;
65   - state.initSetp3 = true;
66 62 console.log(step2Values);
67 63 }
68 64
69 65 function handleRedo() {
70 66 current.value = 0;
71 67 state.initSetp2 = false;
72   - state.initSetp3 = false;
73 68 }
74 69
75 70 return {
... ...
... ... @@ -51,13 +51,3 @@ export const step1Schemas: FormSchema[] = [
51 51 component: 'InputTextArea',
52 52 },
53 53 ];
54   -
55   -export const step2Schemas: FormSchema[] = [
56   - {
57   - field: 'pwd',
58   - component: 'InputPassword',
59   - label: '支付密码',
60   - required: true,
61   - defaultValue: '123456',
62   - },
63   -];
... ...
... ... @@ -10,10 +10,11 @@
10 10 <BasicForm @register="registerForm">
11 11 <template #menu="{ model, field }">
12 12 <BasicTree
  13 + ref="tree"
13 14 v-model:value="model[field]"
14 15 :treeData="treeData"
15 16 :replaceFields="{ title: 'menuName' }"
16   - :checked-keys="roleMenus"
  17 + :checkedKeys="roleMenus"
17 18 checkable
18 19 toolbar
19 20 title="菜单分配"
... ... @@ -23,11 +24,16 @@
23 24 </BasicForm>
24 25 </BasicDrawer>
25 26 </template>
  27 +
26 28 <script lang="ts">
27   - import { defineComponent, ref, computed, unref } from 'vue';
  29 + import { defineComponent, ref, computed, unref, getCurrentInstance } from 'vue';
  30 +
28 31 import { BasicForm, useForm } from '/@/components/Form/index';
  32 +
29 33 import { formSchema } from './role.data';
  34 +
30 35 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  36 +
31 37 import { BasicTree, TreeItem } from '/@/components/Tree';
32 38
33 39 const { t } = useI18n(); //加载国际化
... ... @@ -35,68 +41,129 @@
35 41 // import { getMenuList } from '/@/api/demo/system';
36 42
37 43 // 加载菜单数据
  44 +
38 45 import { getMenuList, getMenusIdsByRoleId } from '/@/api/sys/menu';
  46 +
39 47 import { useI18n } from '/@/hooks/web/useI18n';
  48 +
40 49 import { RouteItem } from '/@/api/sys/model/menuModel';
  50 +
41 51 import { saveOrUpdateRoleInfoWithMenu } from '/@/api/system/system';
  52 + import { useChildrenIdsRemoveParentId } from '/@/hooks/web/useChildrenIdsRemoveParentId';
42 53 export default defineComponent({
43 54 name: 'RoleDrawer',
  55 +
44 56 components: { BasicDrawer, BasicForm, BasicTree },
  57 +
45 58 emits: ['success', 'register'],
  59 +
46 60 setup(_, { emit }) {
  61 + const { proxy } = getCurrentInstance();
  62 +
47 63 const isUpdate = ref<boolean>(true);
  64 +
48 65 const treeData = ref<TreeItem[]>([]);
  66 +
49 67 const roleMenus = ref<string[]>([]);
  68 +
50 69 const allCheckedKeys = ref<string[]>();
  70 +
51 71 const roleHalfCheckedKeys = ref<string[]>([]);
  72 +
52 73 const roleId = ref<string>('');
  74 +
53 75 const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
54 76 labelWidth: 90,
  77 +
55 78 schemas: formSchema,
  79 +
56 80 showActionButtonGroup: false,
57 81 });
58 82
59 83 function processChildren(items: RouteItem[]) {
60 84 items.map((item) => {
61 85 item.menuName = t(item.meta.title);
  86 +
62 87 item.icon = item.meta.icon;
  88 +
63 89 item.key = item.id;
  90 +
64 91 if (item.children) {
65 92 processChildren(item.children);
66 93 }
67 94 });
68 95 }
69 96
  97 + /**
  98 +
  99 + * 根据角色id获取所有的菜单ids----里面包含父级id---会造成回显数据时
  100 +
  101 + * 存在父级id则默认勾选所有子级id
  102 +
  103 + */
  104 +
70 105 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
71 106 resetFields();
  107 +
72 108 roleId.value = '';
  109 +
73 110 setDrawerProps({ confirmLoading: false });
  111 +
74 112 // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告
  113 +
75 114 if (unref(treeData).length === 0) {
76 115 // 获取全部的菜单
  116 +
77 117 const menuListModel = await getMenuList();
  118 +
78 119 processChildren(menuListModel);
  120 +
79 121 let treeValues: TreeItem[] = [];
  122 +
80 123 menuListModel.map((item) => {
81 124 const data = {
82 125 menuName: t(item.meta.title),
  126 +
83 127 icon: item.meta.icon,
  128 +
84 129 key: item.id,
  130 +
85 131 children: item.children as any as TreeItem[],
86 132 };
  133 +
87 134 treeValues.push(data);
88 135 });
  136 +
89 137 treeData.value = treeValues;
90 138 }
91   - if (data.record) {
92   - // 通过角色id去获取角色对应的菜单的ids
93   - roleMenus.value = await getMenusIdsByRoleId(data.record.id);
94   - console.log(roleMenus.value, 'roleMenus.value');
95   - // TODO: 角色回显问题:待解决
96   - roleId.value = data.record.id;
97   - }
98   - isUpdate.value = !!data?.isUpdate;
  139 +
99 140 if (unref(isUpdate)) {
  141 + if (data.record) {
  142 + // // 通过角色id去获取角色对应的菜单的ids
  143 +
  144 + roleMenus.value = await getMenusIdsByRoleId(data.record.id);
  145 +
  146 + console.log(roleMenus.value);
  147 +
  148 + console.log(treeData.value);
  149 +
  150 + treeData.value.map((m) => {
  151 + roleMenus.value.map((m1) => {
  152 + if (m.key === m1) {
  153 + useChildrenIdsRemoveParentId(m1, roleMenus.value);
  154 + }
  155 + });
  156 + });
  157 +
  158 + console.log(roleMenus.value);
  159 +
  160 + proxy.$refs.tree.setCheckedKeys(roleMenus.value);
  161 +
  162 + // console.log(roleMenus.value, 'roleMenus.value');
  163 +
  164 + roleId.value = data.record.id;
  165 + }
  166 +
100 167 setFieldsValue({
101 168 ...data.record,
102 169 });
... ... @@ -108,38 +175,59 @@
108 175 async function handleSubmit() {
109 176 try {
110 177 const values = await validate();
  178 +
111 179 setDrawerProps({ confirmLoading: true });
  180 +
112 181 const req = {
113 182 id: roleId.value,
  183 +
114 184 name: values.name,
  185 +
115 186 remark: values.remark,
  187 +
116 188 status: values.status,
  189 +
117 190 menu: allCheckedKeys.value as string[],
118 191 };
  192 +
119 193 saveOrUpdateRoleInfoWithMenu(req).then(() => {
120 194 closeDrawer();
  195 +
121 196 emit('success');
122 197 });
123 198 } finally {
124 199 setDrawerProps({ confirmLoading: false });
125 200 }
126 201 }
  202 +
127 203 // Tree check事件
  204 +
128 205 const handleCheckClick = (checkedKeys: string[], { halfCheckedKeys }) => {
129 206 allCheckedKeys.value = [...checkedKeys, ...halfCheckedKeys];
  207 +
130 208 // 父节点
  209 +
131 210 roleHalfCheckedKeys.value = halfCheckedKeys;
132 211 };
133 212
134 213 return {
135 214 allCheckedKeys,
  215 +
136 216 registerDrawer,
  217 +
137 218 registerForm,
  219 +
138 220 getTitle,
  221 +
139 222 handleSubmit,
  223 +
140 224 treeData,
  225 +
141 226 roleMenus,
  227 +
142 228 handleCheckClick,
  229 +
  230 + useChildrenIdsRemoveParentId,
143 231 };
144 232 },
145 233 });
... ...