Commit b042fdeb59f1bf37d90b970654831f9eae5460bf

Authored by sqy
1 parent 656b64d2

'修改主题色,调整页面菜单文件名称'

Showing 53 changed files with 11 additions and 9957 deletions
1 import { generate } from '@ant-design/colors'; 1 import { generate } from '@ant-design/colors';
2 2
3 -export const primaryColor = '#0960bd'; 3 +export const primaryColor = '#377DFF';
4 4
5 export const darkMode = 'light'; 5 export const darkMode = 'light';
6 6
@@ -10,21 +10,21 @@ export default { @@ -10,21 +10,21 @@ export default {
10 status: 'status', 10 status: 'status',
11 }, 11 },
12 notice: { 12 notice: {
13 - webSiteNotice: 'web site notice', 13 + webSiteNotice: 'platform notice',
14 noticeManagement: 'notice management', 14 noticeManagement: 'notice management',
15 myNotice: 'my notice', 15 myNotice: 'my notice',
16 }, 16 },
17 17
18 device: { 18 device: {
19 deviceManagement: 'device management', 19 deviceManagement: 'device management',
20 - device: 'device', 20 + device: 'device management',
21 deviceProfile: 'device profile', 21 deviceProfile: 'device profile',
22 }, 22 },
23 tenant: { 23 tenant: {
24 tenant: 'tenant', 24 tenant: 'tenant',
25 tenantManagement: 'tenant management', 25 tenantManagement: 'tenant management',
26 tenantSetting: 'tenant config', 26 tenantSetting: 'tenant config',
27 - tenantOEM: 'OEM customization', 27 + tenantOEM: 'platform customization',
28 tenantRule: 'tenant rule', 28 tenantRule: 'tenant rule',
29 }, 29 },
30 30
@@ -49,23 +49,9 @@ export default { @@ -49,23 +49,9 @@ export default {
49 alarmManagement: 'alarm management', 49 alarmManagement: 'alarm management',
50 geographicPosition: 'geographic position', 50 geographicPosition: 'geographic position',
51 alarmContact: 'alarm contact', 51 alarmContact: 'alarm contact',
52 - alarmCenter: 'alarm center', 52 + alarmCenter: 'alarm record',
53 }, 53 },
54 54
55 - dept: {  
56 - queryDeptName: 'dept name',  
57 - queryDeptStatus: 'status',  
58 - toolDeptList: 'dept list',  
59 - toolCreateDept: 'create dept',  
60 - toolEditDept: 'edit dept',  
61 - tableTitleDeptSort: 'sort',  
62 - tableTitleDeptCreateTime: 'create time',  
63 - tableTitleDeptOperation: 'operation',  
64 - drawerTitleDeptEnable: 'enable',  
65 - drawerTitleDeptDisable: 'disable',  
66 - drawerTitleDeptParentDept: 'parent dept',  
67 - tableTitleMemo: 'memo',  
68 - },  
69 system: { 55 system: {
70 system: 'system', 56 system: 'system',
71 accountManagement: 'account management', 57 accountManagement: 'account management',
@@ -10,13 +10,13 @@ export default { @@ -10,13 +10,13 @@ export default {
10 status: '状态', 10 status: '状态',
11 }, 11 },
12 notice: { 12 notice: {
13 - webSiteNotice: '站内通知', 13 + webSiteNotice: '平台通知',
14 noticeManagement: '通知管理', 14 noticeManagement: '通知管理',
15 myNotice: '我的通知', 15 myNotice: '我的通知',
16 }, 16 },
17 device: { 17 device: {
18 deviceManagement: '设备管理', 18 deviceManagement: '设备管理',
19 - device: '设备', 19 + device: '设备管理',
20 deviceProfile: '设备配置', 20 deviceProfile: '设备配置',
21 }, 21 },
22 22
@@ -24,7 +24,7 @@ export default { @@ -24,7 +24,7 @@ export default {
24 tenant: '租户', 24 tenant: '租户',
25 tenantManagement: '租户管理', 25 tenantManagement: '租户管理',
26 tenantSetting: '租户配置', 26 tenantSetting: '租户配置',
27 - tenantOEM: 'OEM定制', 27 + tenantOEM: '平台定制',
28 tenantRule: '租户角色', 28 tenantRule: '租户角色',
29 }, 29 },
30 organization: { 30 organization: {
@@ -34,20 +34,7 @@ export default { @@ -34,20 +34,7 @@ export default {
34 toolEditOrganization: '编辑组织', 34 toolEditOrganization: '编辑组织',
35 parentOrganization: '上级组织', 35 parentOrganization: '上级组织',
36 }, 36 },
37 - dept: {  
38 - queryDeptName: '部门名称',  
39 - queryDeptStatus: '状态',  
40 - toolDeptList: '部门列表',  
41 - toolCreateDept: '新增部门',  
42 - toolEditDept: '编辑部门',  
43 - tableTitleDeptSort: '排序',  
44 - tableTitleDeptCreateTime: '创建时间',  
45 - tableTitleDeptOperation: '操作',  
46 - drawerTitleDeptEnable: '启用',  
47 - drawerTitleDeptDisable: '停用',  
48 - drawerTitleDeptParentDept: '上级部门',  
49 - tableTitleMemo: '备注',  
50 - }, 37 +
51 RuleEngine: { 38 RuleEngine: {
52 ruleEngine: '规则引擎', 39 ruleEngine: '规则引擎',
53 sceneLinkage: '场景联动', 40 sceneLinkage: '场景联动',
@@ -62,7 +49,7 @@ export default { @@ -62,7 +49,7 @@ export default {
62 alarmManagement: '告警管理', 49 alarmManagement: '告警管理',
63 geographicPosition: '地理位置', 50 geographicPosition: '地理位置',
64 alarmContact: '告警联系人', 51 alarmContact: '告警联系人',
65 - alarmCenter: '告警中心', 52 + alarmCenter: '告警记录',
66 }, 53 },
67 system: { 54 system: {
68 system: '系统管理', 55 system: '系统管理',
@@ -78,7 +78,7 @@ const setting: ProjectConfig = { @@ -78,7 +78,7 @@ const setting: ProjectConfig = {
78 // Menu configuration 78 // Menu configuration
79 menuSetting: { 79 menuSetting: {
80 // sidebar menu bg color 80 // sidebar menu bg color
81 - bgColor: SIDE_BAR_BG_COLOR_LIST[0], 81 + bgColor: SIDE_BAR_BG_COLOR_LIST[3],
82 // Whether to fix the left menu 82 // Whether to fix the left menu
83 fixed: true, 83 fixed: true,
84 // Menu collapse 84 // Menu collapse
1 -import { alarmLevel, statusType } from '/@/views/device/manage/config/detail.config';  
2 -import { FormSchema } from '/@/components/Form';  
3 -import { BasicColumn } from '/@/components/Table';  
4 -import moment from 'moment';  
5 -export const alarmSearchSchemas: FormSchema[] = [  
6 - {  
7 - field: 'status',  
8 - label: '告警状态',  
9 - component: 'Select',  
10 - colProps: { span: 6 },  
11 - componentProps: {  
12 - options: [  
13 - {  
14 - label: '清除未确认',  
15 - value: 'CLEARED_UNACK',  
16 - },  
17 - {  
18 - label: '激活未确认',  
19 - value: 'ACTIVE_UNACK',  
20 - },  
21 - {  
22 - label: '清除已确认',  
23 - value: 'CLEARED_ACK',  
24 - },  
25 - {  
26 - label: '激活已确认',  
27 - value: 'ACTIVE_ACK',  
28 - },  
29 - ],  
30 - },  
31 - },  
32 - {  
33 - field: 'alarmType',  
34 - label: '告警类型',  
35 - component: 'Input',  
36 - colProps: { span: 6 },  
37 - componentProps: {  
38 - maxLength: 255,  
39 - placeholder: '请输入告警类型',  
40 - },  
41 - dynamicRules: () => {  
42 - return [  
43 - {  
44 - required: false,  
45 - validator: (_, value) => {  
46 - if (String(value).length > 255) {  
47 - return Promise.reject('字数不超过255个字');  
48 - }  
49 - return Promise.resolve();  
50 - },  
51 - },  
52 - ];  
53 - },  
54 - },  
55 - {  
56 - field: 'endTime',  
57 - label: '告警时间',  
58 - component: 'DatePicker',  
59 - componentProps: {  
60 - valueFormat: 'x',  
61 - showTime: { defaultValue: moment('23:59:59', 'HH:mm:ss') },  
62 - },  
63 - colProps: { span: 6 },  
64 - },  
65 -];  
66 -export const alarmColumns: BasicColumn[] = [  
67 - {  
68 - title: '告警时间',  
69 - dataIndex: 'createdTime',  
70 - width: 120,  
71 - },  
72 - {  
73 - title: '告警设备',  
74 - dataIndex: 'deviceName',  
75 - width: 100,  
76 - },  
77 - {  
78 - title: '类型',  
79 - dataIndex: 'type',  
80 - width: 160,  
81 - },  
82 - {  
83 - title: '告警级别',  
84 - dataIndex: 'severity',  
85 - width: 160,  
86 - format: (text) => alarmLevel(text),  
87 - },  
88 - {  
89 - title: '状态',  
90 - dataIndex: 'status',  
91 - format: (text) => statusType(text),  
92 - width: 160,  
93 - },  
94 -];  
95 -  
96 -export const alarmSchemasForm: FormSchema[] = [  
97 - {  
98 - field: 'deviceName',  
99 - label: '告警设备',  
100 - component: 'Input',  
101 - componentProps: {  
102 - disabled: true,  
103 - },  
104 - },  
105 -  
106 - {  
107 - field: 'startTs',  
108 - label: '开始时间',  
109 - component: 'Input',  
110 - componentProps: {  
111 - disabled: true,  
112 - },  
113 - },  
114 - {  
115 - field: 'endTs',  
116 - label: '结束时间',  
117 - component: 'Input',  
118 - componentProps: {  
119 - disabled: true,  
120 - },  
121 - },  
122 - {  
123 - field: 'ackTs',  
124 - label: '处理时间',  
125 - component: 'Input',  
126 - componentProps: {  
127 - disabled: true,  
128 - },  
129 - ifShow: ({ values }) => values.status === '激活已确认' || values.status === '清除已确认',  
130 - },  
131 - {  
132 - field: 'clearTs',  
133 - label: '清除时间',  
134 - component: 'Input',  
135 - componentProps: {  
136 - disabled: true,  
137 - },  
138 - ifShow: ({ values }) => values.status === '清除已确认' || values.status === '清除未确认',  
139 - },  
140 - {  
141 - field: 'type',  
142 - label: '告警类型',  
143 - component: 'Input',  
144 - componentProps: {  
145 - disabled: true,  
146 - },  
147 - },  
148 - {  
149 - field: 'severity',  
150 - label: '严重程度',  
151 - component: 'Input',  
152 - componentProps: {  
153 - disabled: true,  
154 - },  
155 - },  
156 - {  
157 - field: 'status',  
158 - label: '状态',  
159 - component: 'Input',  
160 - componentProps: {  
161 - disabled: true,  
162 - },  
163 - },  
164 - {  
165 - field: 'details',  
166 - label: '详情',  
167 - component: 'InputTextArea',  
168 - },  
169 -];  
1 -<template>  
2 - <BasicDrawer v-bind="$attrs" title="告警详情" @register="registerDrawer" width="30%">  
3 - <BasicForm @register="registerForm" />  
4 - <div class="flex justify-end">  
5 - <a-button  
6 - type="primary"  
7 - class="mr-4"  
8 - @click="handleAlarm"  
9 - v-if="alarmStatus !== 'ACTIVE_ACK' && alarmStatus !== 'CLEARED_ACK'"  
10 - >处理</a-button  
11 - >  
12 - <a-button  
13 - danger  
14 - type="primary"  
15 - @click="clearAlarm"  
16 - v-if="alarmStatus !== 'CLEARED_UNACK' && alarmStatus !== 'CLEARED_ACK'"  
17 - >清除</a-button  
18 - >  
19 - </div>  
20 - </BasicDrawer>  
21 -</template>  
22 -  
23 -<script lang="ts">  
24 - import { defineComponent, ref, unref } from 'vue';  
25 - import { BasicForm, useForm } from '/@/components/Form';  
26 - import { alarmSchemasForm } from '../config/detail.config';  
27 - import { clearOrAckAlarm } from '/@/api/device/deviceManager';  
28 - import { alarmLevel, statusType } from '/@/views/device/manage/config/detail.config';  
29 - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';  
30 - export default defineComponent({  
31 - name: 'AlarmDetailDrawer',  
32 - components: {  
33 - BasicForm,  
34 - BasicDrawer,  
35 - },  
36 - emits: ['success', 'register'],  
37 - setup(_, { emit }) {  
38 - const [registerForm, { setFieldsValue, resetFields }] = useForm({  
39 - showActionButtonGroup: false,  
40 - schemas: alarmSchemasForm,  
41 - labelCol: {  
42 - span: 5,  
43 - },  
44 - });  
45 - const alarmId = ref('');  
46 - const alarmStatus = ref('');  
47 - const [registerDrawer, { closeDrawer }] = useDrawerInner(async (data) => {  
48 - await resetFields();  
49 - await setFieldsValue({  
50 - ...data,  
51 - severity: alarmLevel(data.severity),  
52 - status: statusType(data.status),  
53 - });  
54 - alarmStatus.value = data.status;  
55 - alarmId.value = data.id;  
56 - });  
57 - // 处理报警  
58 - const handleAlarm = async () => {  
59 - await clearOrAckAlarm(unref(alarmId), false);  
60 - emit('success');  
61 - closeDrawer();  
62 - };  
63 - // 清除报警  
64 - const clearAlarm = async () => {  
65 - await clearOrAckAlarm(unref(alarmId), true);  
66 - emit('success');  
67 - closeDrawer();  
68 - };  
69 - return {  
70 - registerDrawer,  
71 - registerForm,  
72 - clearAlarm,  
73 - handleAlarm,  
74 - alarmStatus,  
75 - };  
76 - },  
77 - });  
78 -</script>  
79 -  
80 -<style lang="less" scoped></style>  
1 -<template>  
2 - <div>  
3 - <BasicTable @register="registerTable">  
4 - <template #action="{ record }">  
5 - <TableAction  
6 - :actions="[  
7 - {  
8 - label: '详情',  
9 - icon: 'ant-design:eye-outlined',  
10 - onClick: handleDetail.bind(null, record),  
11 - },  
12 - ]"  
13 - />  
14 - </template>  
15 - </BasicTable>  
16 - <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" />  
17 - </div>  
18 -</template>  
19 -<script lang="ts">  
20 - import { defineComponent } from 'vue';  
21 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
22 - import { alarmColumns, alarmSearchSchemas } from './config/detail.config';  
23 - import { getDeviceAlarm } from '/@/api/device/deviceManager';  
24 - import { useDrawer } from '/@/components/Drawer';  
25 - import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue';  
26 -  
27 - export default defineComponent({  
28 - name: 'AlarmCenter',  
29 - components: {  
30 - BasicTable,  
31 - TableAction,  
32 - AlarmDetailDrawer,  
33 - },  
34 -  
35 - setup() {  
36 - const [registerTable, { reload }] = useTable({  
37 - api: getDeviceAlarm,  
38 - columns: alarmColumns,  
39 - formConfig: {  
40 - labelWidth: 120,  
41 - schemas: alarmSearchSchemas,  
42 - },  
43 - useSearchForm: true,  
44 - bordered: true,  
45 - showIndexColumn: false,  
46 - showTableSetting: true,  
47 - actionColumn: {  
48 - width: 200,  
49 - title: '操作',  
50 - slots: { customRender: 'action' },  
51 - fixed: 'right',  
52 - },  
53 - beforeFetch: (data) => {  
54 - Reflect.set(data, 'startTime', null);  
55 - },  
56 - });  
57 - const [registerDetailDrawer, { openDrawer }] = useDrawer();  
58 - const handleDetail = (record: Recordable) => {  
59 - openDrawer(true, record);  
60 - };  
61 - const handleSuccess = () => {  
62 - reload();  
63 - };  
64 - return {  
65 - registerTable,  
66 - registerDetailDrawer,  
67 - handleDetail,  
68 - handleSuccess,  
69 - };  
70 - },  
71 - });  
72 -</script>  
1 -import type { BasicColumn } from '/@/components/Table';  
2 -import type { FormSchema } from '/@/components/Table';  
3 -import { getOrganizationList } from '/@/api/system/system';  
4 -import { copyTransFun } from '/@/utils/fnUtils';  
5 -import { getDeviceProfile } from '/@/api/alarm/position';  
6 -  
7 -export enum AggregateDataEnum {  
8 - MIN = 'MIN',  
9 - MAX = 'MAX',  
10 - AVG = 'AVG',  
11 - SUM = 'SUM',  
12 - COUNT = 'COUNT',  
13 - NONE = 'NONE',  
14 -}  
15 -export const formSchema: FormSchema[] = [  
16 - {  
17 - field: 'organizationId',  
18 - label: '',  
19 - component: 'ApiTreeSelect',  
20 - componentProps: {  
21 - placeholder: '请选择组织',  
22 - api: async () => {  
23 - const data = await getOrganizationList();  
24 - copyTransFun(data as any as any[]);  
25 - return data;  
26 - },  
27 - },  
28 - },  
29 - {  
30 - field: 'profileId',  
31 - label: '',  
32 - component: 'ApiSelect',  
33 - componentProps: {  
34 - api: getDeviceProfile,  
35 - placeholder: '请选择设备配置',  
36 - labelField: 'name',  
37 - valueField: 'id',  
38 - },  
39 - },  
40 - {  
41 - field: 'name',  
42 - label: '',  
43 - component: 'Input',  
44 - componentProps: {  
45 - maxLength: 255,  
46 - placeholder: '请输入设备名称',  
47 - },  
48 - },  
49 - {  
50 - field: 'deviceState',  
51 - label: '',  
52 - component: 'RadioGroup',  
53 - componentProps: {  
54 - size: 'small',  
55 - options: [  
56 - { label: '全部', value: '' },  
57 - { label: '待激活', value: 'INACTIVE' },  
58 - { label: '在线', value: 'ONLINE' },  
59 - { label: '离线', value: 'OFFLINE' },  
60 - ],  
61 - },  
62 - },  
63 - {  
64 - field: 'alarmStatus',  
65 - label: '是否告警',  
66 - component: 'RadioGroup',  
67 - labelWidth: '85px',  
68 - componentProps: {  
69 - size: 'small',  
70 - options: [  
71 - { label: '是', value: '1' },  
72 - { label: '否', value: '0' },  
73 - ],  
74 - },  
75 - },  
76 -];  
77 -  
78 -export const columns: BasicColumn[] = [  
79 - {  
80 - title: '名称',  
81 - dataIndex: 'name',  
82 - width: 100,  
83 - },  
84 - {  
85 - title: '位置',  
86 - dataIndex: 'deviceInfo.address',  
87 - width: 100,  
88 - },  
89 - {  
90 - title: '状态',  
91 - dataIndex: 'deviceState',  
92 - width: 100,  
93 - slots: { customRender: 'deviceState' },  
94 - },  
95 -];  
96 -  
97 -// 动态生成options  
98 -function generateOptions(value: number) {  
99 - if (value === 3600000) {  
100 - return [  
101 - {  
102 - label: '10秒',  
103 - value: 10000,  
104 - },  
105 - {  
106 - label: '15秒',  
107 - value: 15000,  
108 - },  
109 - {  
110 - label: '30秒',  
111 - value: 30000,  
112 - },  
113 - {  
114 - label: '1分钟',  
115 - value: 60000,  
116 - },  
117 - {  
118 - label: '2分钟',  
119 - value: 120000,  
120 - },  
121 - {  
122 - label: '5分钟',  
123 - value: 300000,  
124 - },  
125 - ];  
126 - } else if (value === 7200000) {  
127 - return [  
128 - {  
129 - label: '15秒',  
130 - value: 15000,  
131 - },  
132 - {  
133 - label: '30秒',  
134 - value: 30000,  
135 - },  
136 - {  
137 - label: '1分钟',  
138 - value: 60000,  
139 - },  
140 - {  
141 - label: '2分钟',  
142 - value: 120000,  
143 - },  
144 - {  
145 - label: '5分钟',  
146 - value: 300000,  
147 - },  
148 - {  
149 - label: '10分钟',  
150 - value: 600000,  
151 - },  
152 - {  
153 - label: '15分钟',  
154 - value: 900000,  
155 - },  
156 - ];  
157 - } else if (value === 18000000) {  
158 - return [  
159 - {  
160 - label: '1分钟',  
161 - value: 60000,  
162 - },  
163 - {  
164 - label: '2分钟',  
165 - value: 120000,  
166 - },  
167 - {  
168 - label: '5分钟',  
169 - value: 300000,  
170 - },  
171 - {  
172 - label: '10分钟',  
173 - value: 600000,  
174 - },  
175 - {  
176 - label: '15分钟',  
177 - value: 900000,  
178 - },  
179 - {  
180 - label: '30分钟',  
181 - value: 1800000,  
182 - },  
183 - ];  
184 - } else if (value === 36000000) {  
185 - return [  
186 - {  
187 - label: '2分钟',  
188 - value: 120000,  
189 - },  
190 - {  
191 - label: '5分钟',  
192 - value: 300000,  
193 - },  
194 - {  
195 - label: '10分钟',  
196 - value: 600000,  
197 - },  
198 - {  
199 - label: '15分钟',  
200 - value: 900000,  
201 - },  
202 - {  
203 - label: '30分钟',  
204 - value: 1800000,  
205 - },  
206 - {  
207 - label: '1小时',  
208 - value: 3600000,  
209 - },  
210 - ];  
211 - } else if (value === 43200000) {  
212 - return [  
213 - {  
214 - label: '2分钟',  
215 - value: 120000,  
216 - },  
217 - {  
218 - label: '5分钟',  
219 - value: 300000,  
220 - },  
221 - {  
222 - label: '10分钟',  
223 - value: 600000,  
224 - },  
225 - {  
226 - label: '15分钟',  
227 - value: 900000,  
228 - },  
229 - {  
230 - label: '30分钟',  
231 - value: 1800000,  
232 - },  
233 - {  
234 - label: '1小时',  
235 - value: 3600000,  
236 - },  
237 - ];  
238 - } else if (value === 86400000) {  
239 - return [  
240 - {  
241 - label: '5分钟',  
242 - value: 300000,  
243 - },  
244 - {  
245 - label: '10分钟',  
246 - value: 600000,  
247 - },  
248 - {  
249 - label: '15分钟',  
250 - value: 900000,  
251 - },  
252 - {  
253 - label: '30分钟',  
254 - value: 1800000,  
255 - },  
256 - {  
257 - label: '1小时',  
258 - value: 3600000,  
259 - },  
260 - {  
261 - label: '2小时',  
262 - value: 7200000,  
263 - },  
264 - ];  
265 - } else if (value === 604800000) {  
266 - return [  
267 - {  
268 - label: '30分钟',  
269 - value: 1800000,  
270 - },  
271 - {  
272 - label: '1小时',  
273 - value: 3600000,  
274 - },  
275 - {  
276 - label: '2小时',  
277 - value: 7200000,  
278 - },  
279 - {  
280 - label: '5小时',  
281 - value: 18000000,  
282 - },  
283 - {  
284 - label: '10小时',  
285 - value: 36000000,  
286 - },  
287 - {  
288 - label: '12小时',  
289 - value: 43200000,  
290 - },  
291 - {  
292 - label: '1天',  
293 - value: 86400000,  
294 - },  
295 - ];  
296 - } else {  
297 - return [  
298 - {  
299 - label: '2小时',  
300 - value: 7200000,  
301 - },  
302 - {  
303 - label: '5小时',  
304 - value: 18000000,  
305 - },  
306 - {  
307 - label: '10小时',  
308 - value: 36000000,  
309 - },  
310 - {  
311 - label: '12小时',  
312 - value: 43200000,  
313 - },  
314 - {  
315 - label: '1天',  
316 - value: 86400000,  
317 - },  
318 - ];  
319 - }  
320 -}  
321 -export const schemas: FormSchema[] = [  
322 - {  
323 - field: 'endTs',  
324 - label: '最后数据',  
325 - component: 'Select',  
326 - required: true,  
327 - componentProps({ formModel, formActionType }) {  
328 - return {  
329 - onChange(value) {  
330 - const { updateSchema } = formActionType;  
331 - console.log(value);  
332 - formModel.interval = '';  
333 - updateSchema({  
334 - field: 'interval',  
335 - componentProps: {  
336 - placeholder: '请选择分组间隔',  
337 - options: generateOptions(value),  
338 - },  
339 - });  
340 - },  
341 - getPopupContainer: () => document.body,  
342 - options: [  
343 - {  
344 - label: '最近1小时',  
345 - value: 3600000,  
346 - },  
347 - {  
348 - label: '最近2小时',  
349 - value: 7200000,  
350 - },  
351 - {  
352 - label: '最近5小时',  
353 - value: 18000000,  
354 - },  
355 - {  
356 - label: '最近10小时',  
357 - value: 36000000,  
358 - },  
359 - {  
360 - label: '最近12小时',  
361 - value: 43200000,  
362 - },  
363 - {  
364 - label: '最近1天',  
365 - value: 86400000,  
366 - },  
367 - {  
368 - label: '最近7天',  
369 - value: 604800000,  
370 - },  
371 - {  
372 - label: '最近30天',  
373 - value: 2592000000,  
374 - },  
375 - ],  
376 - };  
377 - },  
378 - colProps: {  
379 - span: 6,  
380 - },  
381 - },  
382 - {  
383 - field: 'interval',  
384 - label: '分组间隔',  
385 - component: 'Select',  
386 - colProps: {  
387 - span: 6,  
388 - },  
389 - componentProps: {  
390 - placeholder: '请选择分组间隔',  
391 - getPopupContainer: () => document.body,  
392 - options: [  
393 - {  
394 - label: '5分钟',  
395 - value: 300000,  
396 - },  
397 - {  
398 - label: '10分钟',  
399 - value: 600000,  
400 - },  
401 - {  
402 - label: '15分钟',  
403 - value: 900000,  
404 - },  
405 - {  
406 - label: '30分钟',  
407 - value: 1800000,  
408 - },  
409 - {  
410 - label: '1小时',  
411 - value: 3600000,  
412 - },  
413 - {  
414 - label: '2小时',  
415 - value: 7200000,  
416 - },  
417 - ],  
418 - },  
419 - },  
420 - {  
421 - field: 'agg',  
422 - label: '数据聚合功能',  
423 - component: 'Select',  
424 - componentProps: {  
425 - getPopupContainer: () => document.body,  
426 - options: [  
427 - {  
428 - label: '最小值',  
429 - value: AggregateDataEnum.MIN,  
430 - },  
431 - {  
432 - label: '最大值',  
433 - value: AggregateDataEnum.MAX,  
434 - },  
435 - {  
436 - label: '平均值',  
437 - value: AggregateDataEnum.AVG,  
438 - },  
439 - {  
440 - label: '求和',  
441 - value: AggregateDataEnum.SUM,  
442 - },  
443 - ],  
444 - },  
445 - colProps: {  
446 - span: 6,  
447 - },  
448 - },  
449 -];  
1 -<template>  
2 - <div class="wrapper">  
3 - <div ref="wrapRef" :style="{ height, width }"> </div>  
4 - <div class="right-wrap">  
5 - <BasicTable @register="registerTable" @rowClick="deviceRowClick">  
6 - <template #deviceState="{ record }">  
7 - <Tag  
8 - :color="  
9 - record.deviceState == DeviceState.INACTIVE  
10 - ? 'warning'  
11 - : record.deviceState == DeviceState.ONLINE  
12 - ? 'success'  
13 - : 'error'  
14 - "  
15 - class="ml-2"  
16 - >  
17 - {{  
18 - record.deviceState == DeviceState.INACTIVE  
19 - ? '待激活'  
20 - : record.deviceState == DeviceState.ONLINE  
21 - ? '在线'  
22 - : '离线'  
23 - }}  
24 - </Tag>  
25 - </template>  
26 - </BasicTable>  
27 - </div>  
28 - <BasicModal  
29 - @register="registerModal"  
30 - title="历史数据"  
31 - width="70%"  
32 - :minHeight="400"  
33 - :footer="null"  
34 - @cancel="cancelHistoryModal"  
35 - :canFullscreen="false"  
36 - >  
37 - <BasicForm @register="registerForm" />  
38 - <div v-show="isNull" ref="chartRef" :style="{ height: '600px', width }"></div>  
39 - <Empty v-show="!isNull" />  
40 - </BasicModal>  
41 - <DeviceDetailDrawer @register="registerDetailDrawer" />  
42 - </div>  
43 -</template>  
44 -<script lang="ts">  
45 - import { defineComponent, ref, nextTick, unref, onMounted, Ref } from 'vue';  
46 - import { useScript } from '/@/hooks/web/useScript';  
47 - import { formSchema, columns } from './config.data';  
48 - import { BasicTable, useTable } from '/@/components/Table';  
49 - import { devicePage } from '/@/api/alarm/contact/alarmContact';  
50 - import { Tag, Empty } from 'ant-design-vue';  
51 - import { DeviceState } from '/@/api/device/model/deviceModel';  
52 - import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';  
53 - import { useModal, BasicModal } from '/@/components/Modal';  
54 - import { BasicForm, useForm } from '/@/components/Form';  
55 - import { schemas } from './config.data';  
56 - import { useECharts } from '/@/hooks/web/useECharts';  
57 - import {  
58 - getDeviceHistoryInfo,  
59 - getDeviceDataKeys,  
60 - getDeviceActiveTime,  
61 - } from '/@/api/alarm/position';  
62 - import { useDrawer } from '/@/components/Drawer';  
63 - import DeviceDetailDrawer from '/@/views/device/manage/cpns/modal/DeviceDetailDrawer.vue';  
64 - import moment from 'moment';  
65 - // 导入一些静态图片,避免打包时不能正确解析  
66 - import djx from '/@/assets/images/djx.png';  
67 - import zx from '/@/assets/images/zx.png';  
68 - import lx from '/@/assets/images/lx.png';  
69 - import djh from '/@/assets/images/djh.png';  
70 - import online from '/@/assets/images/online1.png';  
71 - import lx1 from '/@/assets/images/lx1.png';  
72 - export default defineComponent({  
73 - name: 'BaiduMap',  
74 - components: {  
75 - BasicTable,  
76 - Tag,  
77 - Empty,  
78 - BasicModal,  
79 - BasicForm,  
80 - DeviceDetailDrawer,  
81 - },  
82 - props: {  
83 - width: {  
84 - type: String,  
85 - default: '100%',  
86 - },  
87 - height: {  
88 - type: String,  
89 - default: 'calc(100vh - 78px)',  
90 - },  
91 - },  
92 - setup() {  
93 - let entityId = '';  
94 - let keys = [];  
95 - let globalRecord: any = {};  
96 - const wrapRef = ref<HTMLDivElement | null>(null);  
97 - const chartRef = ref<HTMLDivElement | null>(null);  
98 - const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);  
99 - const isNull = ref(true);  
100 - const { toPromise } = useScript({ src: BAI_DU_MAP_URL });  
101 - const [registerDetailDrawer, { openDrawer }] = useDrawer();  
102 - const [registerModal, { openModal }] = useModal();  
103 - const [  
104 - registerForm,  
105 - { resetFields, getFieldsValue, setFieldsValue, validate, updateSchema },  
106 - ] = useForm({  
107 - labelWidth: 120,  
108 - schemas,  
109 - async submitFunc() {  
110 - // 表单验证  
111 - await validate();  
112 - let { endTs, interval, agg } = getFieldsValue();  
113 - if (!endTs || !keys.length) return;  
114 - // 数据收集  
115 - const dataArray: any[] = [];  
116 - const startTs = Date.now() - endTs;  
117 - endTs = Date.now();  
118 - // 发送请求  
119 - const res = await getDeviceHistoryInfo({  
120 - entityId,  
121 - keys: keys.join(),  
122 - startTs,  
123 - endTs,  
124 - interval,  
125 - agg,  
126 - });  
127 - // 判断数据对象是否为空  
128 - if (!Object.keys(res).length) {  
129 - isNull.value = false;  
130 - return;  
131 - } else {  
132 - isNull.value = true;  
133 - }  
134 - // 处理数据  
135 - for (const key in res) {  
136 - for (const item1 of res[key]) {  
137 - let { ts, value } = item1;  
138 - const time = moment(ts).format('YYYY-MM-DD HH:mm:ss');  
139 - value = Number(value).toFixed(2);  
140 - dataArray.push([time, value, key]);  
141 - }  
142 - }  
143 - const series: any = keys.map((item) => {  
144 - return {  
145 - name: item,  
146 - type: 'line',  
147 - stack: 'Total',  
148 - data: dataArray.filter((item1) => item1[2] === item),  
149 - };  
150 - });  
151 - // 设置数据  
152 - setOptions({  
153 - tooltip: {  
154 - trigger: 'axis',  
155 - },  
156 - legend: {  
157 - data: keys,  
158 - },  
159 - grid: {  
160 - left: '3%',  
161 - right: '4%',  
162 - bottom: '3%',  
163 - containLabel: true,  
164 - },  
165 - dataZoom: [  
166 - {  
167 - type: 'inside',  
168 - start: 0,  
169 - end: 50,  
170 - },  
171 - {  
172 - start: 20,  
173 - end: 40,  
174 - },  
175 - ],  
176 - xAxis: {  
177 - type: 'time',  
178 - boundaryGap: false,  
179 - },  
180 - yAxis: {  
181 - type: 'value',  
182 - boundaryGap: [0, '100%'],  
183 - },  
184 - series,  
185 - });  
186 - },  
187 - });  
188 - const [registerTable] = useTable({  
189 - api: devicePage,  
190 - columns,  
191 - formConfig: {  
192 - schemas: formSchema,  
193 - labelAlign: 'left',  
194 - },  
195 - showIndexColumn: false,  
196 - useSearchForm: true,  
197 - pagination: {  
198 - showSizeChanger: false,  
199 - },  
200 - });  
201 -  
202 - async function initMap() {  
203 - await toPromise();  
204 - await nextTick();  
205 - const wrapEl = unref(wrapRef);  
206 - const BMap = (window as any).BMap;  
207 - if (!wrapEl) return;  
208 - const map = new BMap.Map(wrapEl);  
209 - const point = new BMap.Point(104.04666605565338, 30.543516387560476);  
210 - map.centerAndZoom(point, 15);  
211 - map.enableScrollWheelZoom(true);  
212 - }  
213 - // 点击表格某一行触发  
214 - const deviceRowClick = async (record) => {  
215 - entityId = record.tbDeviceId;  
216 - globalRecord = record;  
217 - const BMap = (window as any).BMap;  
218 - const wrapEl = unref(wrapRef);  
219 - const map = new BMap.Map(wrapEl);  
220 - if (record.deviceInfo.address) {  
221 - keys = await getDeviceDataKeys(entityId);  
222 - const { name, organizationDTO, deviceState, deviceProfile } = record;  
223 - const { longitude, latitude, address } = record.deviceInfo;  
224 - const point = new BMap.Point(longitude, latitude);  
225 - let options = {  
226 - width: 300, // 信息窗口宽度  
227 - height: 230, // 信息窗口高度  
228 - };  
229 - map.centerAndZoom(point, 15);  
230 - map.enableScrollWheelZoom(true);  
231 - // 创建信息窗口对象  
232 - const res = await getDeviceActiveTime(entityId);  
233 -  
234 - let { value: activeStatus, lastUpdateTs } = res[0];  
235 - lastUpdateTs = moment(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss');  
236 - let infoWindow = new BMap.InfoWindow(  
237 - `  
238 - <div style="display:flex;justify-content:space-between; margin:20px 0px;">  
239 - <div style="font-size:16px;font-weight:bold">${name}</div>  
240 - ${  
241 - deviceState === 'INACTIVE'  
242 - ? `<div style="display:flex;align-items:center"><img style="width:15px;height:15px" src="${djh}">待激活</div>`  
243 - : deviceState === 'ONLINE'  
244 - ? `<div style="display:flex;align-items:center"><img style="width:15px;height:15px" src="${online}">在线</div>`  
245 - : `<div style="display:flex;align-items:center"><img style="width:15px;height:15px" src="${lx1}">离线</div>`  
246 - }  
247 - </div>  
248 - <div>所属组织:${organizationDTO.name}</div>  
249 - <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div>  
250 - <div style="margin-top:6px;">设备位置:${address}</div>  
251 - <div style="margin-top:6px;">${activeStatus ? '在' : '离'}线时间:${lastUpdateTs}</div>  
252 - <div style="display:flex;justify-content:end; margin-top:10px">  
253 - <button onclick="openDeviceInfoDrawer()" style="margin-right:10px;color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">设备信息</button>  
254 - <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button>  
255 - </div>  
256 - `,  
257 - options  
258 - );  
259 -  
260 - map.openInfoWindow(infoWindow, map.getCenter());  
261 - let preMarker = null;  
262 -  
263 - const rivet = deviceState === 'INACTIVE' ? djx : deviceState === 'ONLINE' ? zx : lx;  
264 - let myIcon = new BMap.Icon(rivet, new BMap.Size(20, 30));  
265 - let marker = new BMap.Marker(point, { icon: myIcon });  
266 - if (marker) {  
267 - map.removeOverlay(preMarker);  
268 - }  
269 - map.addOverlay(marker);  
270 - } else {  
271 - const point = new BMap.Point(106.63028229687498, 36.06735821600903);  
272 - let options = {  
273 - width: 100, // 信息窗口宽度  
274 - height: 100, // 信息窗口高度  
275 - title: '提示', // 信息窗口标题  
276 - };  
277 - map.centerAndZoom(point, 5);  
278 - map.enableScrollWheelZoom(true);  
279 - let infoWindow = new BMap.InfoWindow('该设备暂无地理位置', options); // 创建信息窗口对象  
280 - map.openInfoWindow(infoWindow, map.getCenter());  
281 - }  
282 - };  
283 -  
284 - // 设备信息  
285 - const openDeviceInfoDrawer = async () => {  
286 - const { id, tbDeviceId } = globalRecord;  
287 - openDrawer(true, {  
288 - id,  
289 - tbDeviceId,  
290 - });  
291 - };  
292 - const openHistoryModal = async () => {  
293 - openModal(true);  
294 - // 收集参数  
295 - const dataArray: any[] = [];  
296 - const startTs = Date.now() - 86400000; //最近一天  
297 - const endTs = Date.now();  
298 - // 发送请求  
299 - if (!keys.length) {  
300 - isNull.value = false;  
301 - return;  
302 - } else {  
303 - isNull.value = true;  
304 - }  
305 - const res = await getDeviceHistoryInfo({  
306 - entityId,  
307 - keys: keys.join(),  
308 - startTs,  
309 - endTs,  
310 - interval: 7200000, //间隔两小时  
311 - agg: 'AVG',  
312 - });  
313 - // 判断对象是否为空  
314 - if (!Object.keys(res).length) {  
315 - isNull.value = false;  
316 - return;  
317 - } else {  
318 - isNull.value = true;  
319 - }  
320 - // 处理数据  
321 - for (const key in res) {  
322 - for (const item1 of res[key]) {  
323 - let { ts, value } = item1;  
324 - const time = moment(ts).format('YYYY-MM-DD HH:mm:ss');  
325 - value = Number(value).toFixed(2);  
326 - dataArray.push([time, value, key]);  
327 - }  
328 - }  
329 - const series: any = keys.map((item) => {  
330 - return {  
331 - name: item,  
332 - type: 'line',  
333 - stack: 'Total',  
334 - data: dataArray.filter((item1) => item1[2] === item),  
335 - };  
336 - });  
337 - console.log(dataArray);  
338 - // 设置数据;  
339 - setOptions({  
340 - tooltip: {  
341 - trigger: 'axis',  
342 - },  
343 - legend: {  
344 - data: keys,  
345 - },  
346 - grid: {  
347 - left: '3%',  
348 - right: '4%',  
349 - bottom: '3%',  
350 - containLabel: true,  
351 - },  
352 - dataZoom: [  
353 - {  
354 - type: 'inside',  
355 - start: 0,  
356 - end: 50,  
357 - },  
358 - {  
359 - start: 0,  
360 - end: 20,  
361 - },  
362 - ],  
363 - xAxis: {  
364 - type: 'time',  
365 - boundaryGap: false,  
366 - },  
367 - yAxis: {  
368 - type: 'value',  
369 - boundaryGap: [0, '100%'],  
370 - },  
371 - series,  
372 - });  
373 - setFieldsValue({  
374 - endTs: 86400000,  
375 - interval: 7200000,  
376 - agg: 'AVG',  
377 - });  
378 - };  
379 - const cancelHistoryModal = () => {  
380 - resetFields();  
381 - updateSchema({  
382 - field: 'interval',  
383 - componentProps: {  
384 - placeholder: '请选择分组间隔',  
385 - options: [  
386 - {  
387 - label: '5分钟',  
388 - value: 300000,  
389 - },  
390 - {  
391 - label: '10分钟',  
392 - value: 600000,  
393 - },  
394 - {  
395 - label: '15分钟',  
396 - value: 900000,  
397 - },  
398 - {  
399 - label: '30分钟',  
400 - value: 1800000,  
401 - },  
402 - {  
403 - label: '1小时',  
404 - value: 3600000,  
405 - },  
406 - {  
407 - label: '2小时',  
408 - value: 7200000,  
409 - },  
410 - ],  
411 - },  
412 - });  
413 - setOptions({});  
414 - };  
415 - onMounted(() => {  
416 - initMap();  
417 - (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer;  
418 - (window as any).openHistoryModal = openHistoryModal;  
419 - });  
420 - return {  
421 - wrapRef,  
422 - registerTable,  
423 - deviceRowClick,  
424 - DeviceState,  
425 - registerModal,  
426 - registerForm,  
427 - chartRef,  
428 - isNull,  
429 - cancelHistoryModal,  
430 - registerDetailDrawer,  
431 - };  
432 - },  
433 - });  
434 -</script>  
435 -<style scoped>  
436 - .wrapper {  
437 - position: relative;  
438 - }  
439 - .right-wrap {  
440 - padding-top: 10px;  
441 - width: 22%;  
442 - height: 95%;  
443 - position: absolute;  
444 - right: 5%;  
445 - top: 3%;  
446 - background-color: #fff;  
447 - }  
448 -</style>  
1 -<template>  
2 - <BasicDrawer  
3 - v-bind="$attrs"  
4 - @register="registerDrawer"  
5 - showFooter  
6 - :title="getTitle"  
7 - width="30%"  
8 - @ok="handleSubmit"  
9 - >  
10 - <BasicForm @register="registerForm" />  
11 - </BasicDrawer>  
12 -</template>  
13 -<script lang="ts">  
14 - import { defineComponent, ref, computed, unref } from 'vue';  
15 - import { BasicForm, useForm } from '/@/components/Form';  
16 - import { formSchema } from './config.data';  
17 - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';  
18 - import { saveOrEditAlarmContact } from '/@/api/alarm/contact/alarmContact';  
19 - import { useMessage } from '/@/hooks/web/useMessage';  
20 -  
21 - export default defineComponent({  
22 - name: 'ContactDrawer',  
23 - components: { BasicDrawer, BasicForm },  
24 - emits: ['success', 'register'],  
25 - setup(_, { emit }) {  
26 - const isUpdate = ref(true);  
27 -  
28 - const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({  
29 - labelWidth: 120,  
30 - schemas: formSchema,  
31 - showActionButtonGroup: false,  
32 - });  
33 -  
34 - const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {  
35 - await resetFields();  
36 - setDrawerProps({ confirmLoading: false });  
37 - isUpdate.value = !!data?.isUpdate;  
38 - if (unref(isUpdate)) {  
39 - if (data.record.organizationDTO) {  
40 - await setFieldsValue(data.record);  
41 - } else {  
42 - Reflect.deleteProperty(data.record, 'organizationId');  
43 - await setFieldsValue(data.record);  
44 - }  
45 - }  
46 - });  
47 -  
48 - const getTitle = computed(() => (!unref(isUpdate) ? '新增联系人配置' : '编辑联系人配置'));  
49 -  
50 - async function handleSubmit() {  
51 - try {  
52 - const { createMessage } = useMessage();  
53 - const values = await validate();  
54 - setDrawerProps({ confirmLoading: true });  
55 - let saveMessage = '添加成功';  
56 - let updateMessage = '修改成功';  
57 - await saveOrEditAlarmContact(values, unref(isUpdate));  
58 - closeDrawer();  
59 - emit('success');  
60 - createMessage.success(unref(isUpdate) ? updateMessage : saveMessage);  
61 - } finally {  
62 - setDrawerProps({ confirmLoading: false });  
63 - }  
64 - }  
65 -  
66 - return {  
67 - getTitle,  
68 - registerDrawer,  
69 - registerForm,  
70 - handleSubmit,  
71 - };  
72 - },  
73 - });  
74 -</script>  
1 -import { BasicColumn, FormSchema } from '/@/components/Table';  
2 -import { getOrganizationList } from '/@/api/system/system';  
3 -import { copyTransFun } from '/@/utils/fnUtils';  
4 -import { emailRule, phoneRule } from '/@/utils/rules';  
5 -  
6 -// 表格列数据  
7 -export const columns: BasicColumn[] = [  
8 - {  
9 - title: '姓名',  
10 - dataIndex: 'username',  
11 - width: 120,  
12 - },  
13 - {  
14 - title: '所属组织',  
15 - dataIndex: 'organizationDTO.name',  
16 - width: 160,  
17 - },  
18 - {  
19 - title: '手机',  
20 - dataIndex: 'phone',  
21 - width: 160,  
22 - },  
23 - {  
24 - title: '邮箱',  
25 - dataIndex: 'email',  
26 - width: 160,  
27 - },  
28 - {  
29 - title: '微信',  
30 - dataIndex: 'wechat',  
31 - width: 180,  
32 - },  
33 - {  
34 - title: '备注',  
35 - dataIndex: 'remark',  
36 - width: 120,  
37 - },  
38 -  
39 - {  
40 - title: '添加时间',  
41 - dataIndex: 'createTime',  
42 - width: 180,  
43 - },  
44 - {  
45 - title: '更新时间',  
46 - dataIndex: 'updateTime',  
47 - width: 180,  
48 - },  
49 -];  
50 -  
51 -// 查询字段  
52 -export const searchFormSchema: FormSchema[] = [  
53 - {  
54 - field: 'username',  
55 - label: '联系人姓名',  
56 - component: 'Input',  
57 - colProps: { span: 8 },  
58 - componentProps: {  
59 - maxLength: 36,  
60 - placeholder: '请输入联系人姓名',  
61 - },  
62 - },  
63 -];  
64 -  
65 -// 弹框配置项  
66 -export const formSchema: FormSchema[] = [  
67 - {  
68 - field: 'username',  
69 - label: '联系人姓名',  
70 - required: true,  
71 - component: 'Input',  
72 - componentProps: {  
73 - placeholder: '请输入联系人姓名',  
74 - maxLength: 255,  
75 - },  
76 - },  
77 - {  
78 - field: 'organizationId',  
79 - label: '所属组织',  
80 - component: 'ApiTreeSelect',  
81 - componentProps: {  
82 - api: async () => {  
83 - const data = await getOrganizationList();  
84 - copyTransFun(data as any as any[]);  
85 - return data;  
86 - },  
87 - },  
88 - },  
89 - {  
90 - field: 'phone',  
91 - label: '手机号码',  
92 - component: 'Input',  
93 - componentProps: {  
94 - placeholder: '请输入手机号码',  
95 - },  
96 - rules: phoneRule,  
97 - },  
98 - {  
99 - field: 'email',  
100 - label: '电子邮箱',  
101 - component: 'Input',  
102 - componentProps: {  
103 - placeholder: '请输入电子邮箱',  
104 - },  
105 - rules: emailRule,  
106 - },  
107 - {  
108 - field: 'wechat',  
109 - label: '微信',  
110 - component: 'Input',  
111 - componentProps: {  
112 - placeholder: '请输入微信号',  
113 - maxLength: 255,  
114 - },  
115 - },  
116 - {  
117 - field: 'remark',  
118 - label: '备注',  
119 - component: 'InputTextArea',  
120 - componentProps: {  
121 - placeholder: '请输入备注',  
122 - maxLength: 255,  
123 - },  
124 - },  
125 - {  
126 - field: 'id',  
127 - label: '',  
128 - component: 'Input',  
129 - show: false,  
130 - componentProps: {  
131 - maxLength: 36,  
132 - placeholder: 'id',  
133 - },  
134 - },  
135 -];  
1 -<template>  
2 - <div>  
3 - <PageWrapper dense contentFullHeight contentClass="flex">  
4 - <OrganizationIdTree  
5 - class="w-1/4 xl:w-1/5"  
6 - @select="handleSelect"  
7 - ref="organizationIdTreeRef"  
8 - />  
9 - <BasicTable @register="registerTable" :searchInfo="searchInfo" class="w-3/4 xl:w-4/5">  
10 - <template #toolbar>  
11 - <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增告警联系人 </a-button>  
12 - <a-button  
13 - type="primary"  
14 - color="error"  
15 - @click="handleDeleteOrBatchDelete(null)"  
16 - :disabled="hasBatchDelete"  
17 - >  
18 - 批量删除  
19 - </a-button>  
20 - </template>  
21 - <template #action="{ record }">  
22 - <TableAction  
23 - :actions="[  
24 - {  
25 - label: '编辑',  
26 - icon: 'clarity:note-edit-line',  
27 - onClick: handleCreateOrEdit.bind(null, record),  
28 - },  
29 - {  
30 - label: '删除',  
31 - icon: 'ant-design:delete-outlined',  
32 - color: 'error',  
33 - popConfirm: {  
34 - title: '是否确认删除',  
35 - confirm: handleDeleteOrBatchDelete.bind(null, record),  
36 - },  
37 - },  
38 - ]"  
39 - />  
40 - </template>  
41 - </BasicTable>  
42 - </PageWrapper>  
43 - <ContactDrawer @register="registerDrawer" @success="handleSuccess" />  
44 - </div>  
45 -</template>  
46 -  
47 -<script lang="ts">  
48 - import { defineComponent, reactive, ref, computed } from 'vue';  
49 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
50 - import { PageWrapper } from '/@/components/Page';  
51 - import { useMessage } from '/@/hooks/web/useMessage';  
52 - import { useDrawer } from '/@/components/Drawer';  
53 - import ContactDrawer from './ContactDrawer.vue';  
54 - import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree';  
55 -  
56 - import { getAlarmContact, deleteAlarmContact } from '/@/api/alarm/contact/alarmContact';  
57 - import { searchFormSchema, columns } from './config.data';  
58 - export default defineComponent({  
59 - components: {  
60 - PageWrapper,  
61 - OrganizationIdTree,  
62 - BasicTable,  
63 - TableAction,  
64 - ContactDrawer,  
65 - },  
66 - setup() {  
67 - let selectedRowIds = ref<string[]>([]);  
68 - const hasBatchDelete = computed(() => selectedRowIds.value.length <= 0);  
69 - // 复选框事件  
70 - const onSelectRowChange = (selectedRowKeys: string[]) => {  
71 - selectedRowIds.value = selectedRowKeys;  
72 - };  
73 - const searchInfo = reactive<Recordable>({});  
74 - const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);  
75 - // 表格hooks  
76 - const [registerTable, { reload }] = useTable({  
77 - api: getAlarmContact,  
78 - columns,  
79 - clickToRowSelect: false,  
80 - formConfig: {  
81 - labelWidth: 120,  
82 - schemas: searchFormSchema,  
83 - resetFunc: resetFn,  
84 - },  
85 - useSearchForm: true,  
86 - showTableSetting: true,  
87 - bordered: true,  
88 - rowSelection: {  
89 - onChange: onSelectRowChange,  
90 - type: 'checkbox',  
91 - },  
92 - rowKey: 'id',  
93 - actionColumn: {  
94 - width: 200,  
95 - title: '操作',  
96 - dataIndex: 'action',  
97 - slots: { customRender: 'action' },  
98 - fixed: 'right',  
99 - },  
100 - });  
101 - // 弹框  
102 - const [registerDrawer, { openDrawer }] = useDrawer();  
103 - const { createMessage } = useMessage();  
104 -  
105 - // 刷新  
106 - const handleSuccess = () => {  
107 - reload();  
108 - };  
109 - // 新增或编辑  
110 - const handleCreateOrEdit = (record: Recordable | null) => {  
111 - if (record) {  
112 - openDrawer(true, {  
113 - isUpdate: true,  
114 - record,  
115 - });  
116 - } else {  
117 - openDrawer(true, {  
118 - isUpdate: false,  
119 - });  
120 - }  
121 - };  
122 - // 删除或批量删除  
123 - const handleDeleteOrBatchDelete = async (record: Recordable | null) => {  
124 - if (record) {  
125 - try {  
126 - await deleteAlarmContact([record.id]);  
127 - createMessage.success('删除联系人成功');  
128 - handleSuccess();  
129 - } catch (e) {  
130 - createMessage.error('删除失败');  
131 - }  
132 - } else {  
133 - try {  
134 - await deleteAlarmContact(selectedRowIds.value);  
135 - createMessage.success('批量删除联系人成功');  
136 - selectedRowIds.value = [];  
137 - handleSuccess();  
138 - } catch (e) {  
139 - createMessage.info('删除失败');  
140 - }  
141 - }  
142 - };  
143 -  
144 - // 树形选择器  
145 - const handleSelect = (organizationId: string) => {  
146 - searchInfo.organizationId = organizationId;  
147 - handleSuccess();  
148 - };  
149 - return {  
150 - searchInfo,  
151 - hasBatchDelete,  
152 - handleCreateOrEdit,  
153 - handleDeleteOrBatchDelete,  
154 - handleSelect,  
155 - handleSuccess,  
156 - registerTable,  
157 - registerDrawer,  
158 - organizationIdTreeRef,  
159 - };  
160 - },  
161 - });  
162 -</script>  
1 -<template>  
2 - <div>  
3 - <BasicModal  
4 - v-bind="$attrs"  
5 - @register="registerDrawer"  
6 - showFooter  
7 - :title="getTitle"  
8 - width="1000px"  
9 - @ok="handleSubmit"  
10 - @cancel="handleCancel"  
11 - >  
12 - <div class="step-form-form">  
13 - <a-steps :current="current">  
14 - <a-step title="选择转换方式" />  
15 - <a-step title="完善配置参数" />  
16 - </a-steps>  
17 - </div>  
18 - <div>  
19 - <div v-show="current === 0">  
20 - <TransferConfigMode ref="refTransferConfigMode" @next="handleNext"  
21 - /></div>  
22 - <div v-show="current === 1">  
23 - <TransferConfigParams  
24 - ref="refTransferConfigParams"  
25 - :getModeSelect="getModeSelectVal"  
26 - @prevSon="handlePrev"  
27 - /></div>  
28 - </div>  
29 - </BasicModal>  
30 - </div>  
31 -</template>  
32 -<script lang="ts">  
33 - import { defineComponent, reactive, ref, computed, unref, getCurrentInstance } from 'vue';  
34 - import { BasicModal, useModalInner } from '/@/components/Modal';  
35 - import { Steps } from 'ant-design-vue';  
36 - import TransferConfigMode from './cpns/transferConfigMode.vue';  
37 - import TransferConfigParams from './cpns/transferConfigParams.vue';  
38 - import { postAddConvertApi } from '/@/api/datamanager/dataManagerApi';  
39 - import { useMessage } from '/@/hooks/web/useMessage';  
40 -  
41 - export default defineComponent({  
42 - name: 'ConfigDrawer',  
43 - components: {  
44 - BasicModal,  
45 - [Steps.name]: Steps,  
46 - [Steps.Step.name]: Steps.Step,  
47 - TransferConfigMode,  
48 - TransferConfigParams,  
49 - },  
50 - emits: ['success', 'register'],  
51 - setup(_, { emit }) {  
52 - const { createMessage } = useMessage();  
53 - const { proxy } = getCurrentInstance();  
54 - const allPostForm = reactive({});  
55 - const getNameObj = reactive({  
56 - name: '',  
57 - });  
58 - const getTypeObj = reactive({  
59 - type: '',  
60 - remark: '',  
61 - });  
62 - const additionalInfoV = {  
63 - additionalInfo: {  
64 - description: '',  
65 - },  
66 - };  
67 - const getSonFormValue = ref({});  
68 - const getModeSonFormValue = ref({});  
69 - const refTransferConfigParams = ref(null);  
70 - const refTransferConfigMode = ref(null);  
71 - const getModeSelectVal = ref({});  
72 - const isUpdate = ref(true);  
73 - const getTitle = computed(() => (!unref(isUpdate) ? '新增转换配置' : '编辑数据转换'));  
74 - const current = ref(0);  
75 - const editPostId = ref('');  
76 - const editType = reactive({  
77 - type: '',  
78 - configuration: {},  
79 - name: '',  
80 - });  
81 - const editNextType = reactive({  
82 - type: '',  
83 - configuration: {},  
84 - name: '',  
85 - remark: '',  
86 - });  
87 - const editTypeFunc = (d) => {  
88 - editType.type = d.type;  
89 - editType.configuration = d.configuration;  
90 - editType.name = d.name;  
91 - };  
92 -  
93 - const [registerDrawer, { closeModal }] = useModalInner(async (data) => {  
94 - isUpdate.value = !!data?.isUpdate;  
95 - current.value = 0;  
96 - if (unref(isUpdate)) {  
97 - editPostId.value = data.record.id;  
98 - editNextType.type = data.record.type;  
99 - editNextType.configuration = data.record;  
100 - editNextType.name = data.record.name;  
101 - editNextType.remark = data.record.remark;  
102 - proxy.$refs.refTransferConfigMode.setStepOneFieldsValueFunc(editNextType);  
103 - }  
104 - });  
105 - const handleCancel = () => {  
106 - defineClearFunc();  
107 - };  
108 - const defineClearFunc = () => {  
109 - try {  
110 - proxy.$refs.refTransferConfigMode.customResetStepOneFunc();  
111 - proxy.$refs.refTransferConfigParams?.clearSonValueDataFunc();  
112 - } catch (e) {  
113 - return e;  
114 - }  
115 - };  
116 - const handleNext = (args) => {  
117 - current.value++;  
118 - getModeSelectVal.value = args;  
119 - if (unref(isUpdate)) {  
120 - try {  
121 - if (editNextType.type == 'org.thingsboard.rule.engine.kafka.TbKafkaNode') {  
122 - editTypeFunc(editNextType.configuration);  
123 - } else if (editNextType.type == 'org.thingsboard.rule.engine.mqtt.TbMqttNode') {  
124 - editTypeFunc(editNextType.configuration);  
125 - } else if (editNextType.type == 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode') {  
126 - editTypeFunc(editNextType.configuration);  
127 - } else if (editNextType.type == 'org.thingsboard.rule.engine.rest.TbRestApiCallNode') {  
128 - editTypeFunc(editNextType.configuration);  
129 - }  
130 - proxy.$refs.refTransferConfigParams.editSonValueDataFunc(editType);  
131 - } catch (e) {  
132 - return e;  
133 - }  
134 - }  
135 - };  
136 - const handlePrev = () => {  
137 - current.value--;  
138 - };  
139 -  
140 - const commonFunc = () => {  
141 - try {  
142 - additionalInfoV.additionalInfo.description =  
143 - getSonFormValue.value.configuration.description;  
144 - delete getSonFormValue.value.configuration.description;  
145 - delete getSonFormValue.value.configuration.type;  
146 - delete getSonFormValue.value?.configuration?.name;  
147 - } catch (e) {  
148 - return e;  
149 - }  
150 - };  
151 - const addOrEditFunc = async () => {  
152 - if (!unref(isUpdate)) {  
153 - proxy.$refs.refTransferConfigParams.clearSonValueValidateFunc();  
154 - }  
155 - getModeSonFormValue.value = await proxy.$refs.refTransferConfigMode.getSonValueFunc();  
156 - getSonFormValue.value = await proxy.$refs.refTransferConfigParams.getSonValueDataFunc();  
157 - if (getModeSonFormValue.value?.type == 'org.thingsboard.rule.engine.kafka.TbKafkaNode') {  
158 - getTypeObj.type = 'org.thingsboard.rule.engine.kafka.TbKafkaNode';  
159 - getTypeObj.remark = getModeSonFormValue.value.remark;  
160 - getNameObj.name = getSonFormValue.value?.configuration?.name;  
161 - commonFunc();  
162 - } else if (  
163 - getModeSonFormValue.value?.type == 'org.thingsboard.rule.engine.mqtt.TbMqttNode'  
164 - ) {  
165 - getTypeObj.type = 'org.thingsboard.rule.engine.mqtt.TbMqttNode';  
166 - getTypeObj.remark = getModeSonFormValue.value.remark;  
167 - getNameObj.name = getSonFormValue.value?.configuration?.name;  
168 - commonFunc();  
169 - } else if (  
170 - getModeSonFormValue.value?.type == 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode'  
171 - ) {  
172 - getTypeObj.type = 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode';  
173 - getTypeObj.remark = getModeSonFormValue.value.remark;  
174 - getNameObj.name = getSonFormValue.value?.configuration?.name;  
175 - commonFunc();  
176 - } else if (  
177 - getModeSonFormValue.value?.type == 'org.thingsboard.rule.engine.rest.TbRestApiCallNode'  
178 - ) {  
179 - getTypeObj.type = 'org.thingsboard.rule.engine.rest.TbRestApiCallNode';  
180 - getTypeObj.remark = getModeSonFormValue.value.remark;  
181 - getNameObj.name = getSonFormValue.value?.configuration?.name;  
182 - commonFunc();  
183 - }  
184 - const id: any = {  
185 - id: unref(isUpdate) ? editPostId.value : '',  
186 - };  
187 - Object.assign(  
188 - allPostForm,  
189 - getTypeObj,  
190 - getSonFormValue.value,  
191 - getNameObj,  
192 - id,  
193 - additionalInfoV  
194 - );  
195 - if (!unref(isUpdate)) {  
196 - delete allPostForm.id;  
197 - }  
198 - };  
199 - const handleSubmit = async () => {  
200 - if (!unref(isUpdate)) {  
201 - await addOrEditFunc();  
202 - await postAddConvertApi(allPostForm);  
203 - createMessage.success('数据转换新增成功');  
204 - emit('success');  
205 - defineClearFunc();  
206 - closeModal();  
207 - } else {  
208 - await addOrEditFunc();  
209 - await postAddConvertApi(allPostForm);  
210 - createMessage.success('数据转换编辑成功');  
211 - emit('success');  
212 - defineClearFunc();  
213 - closeModal();  
214 - }  
215 - };  
216 - return {  
217 - handleCancel,  
218 - registerDrawer,  
219 - handleSubmit,  
220 - getTitle,  
221 - current,  
222 - handleNext,  
223 - handlePrev,  
224 - getModeSelectVal,  
225 - refTransferConfigParams,  
226 - refTransferConfigMode,  
227 - };  
228 - },  
229 - });  
230 -</script>  
1 -import { BasicColumn, FormSchema } from '/@/components/Table';  
2 -import { h } from 'vue';  
3 -import { Tag } from 'ant-design-vue';  
4 -  
5 -export const columns: BasicColumn[] = [  
6 - {  
7 - title: '数据转换名称',  
8 - dataIndex: 'name',  
9 - width: 200,  
10 - },  
11 - {  
12 - title: '途径',  
13 - dataIndex: 'type',  
14 - width: 200,  
15 - customRender: ({ record }) => {  
16 - const status = record.type;  
17 - const enable =  
18 - status === 'org.thingsboard.rule.engine.kafka.TbKafkaNode'  
19 - ? 'KafKa'  
20 - : record.type === 'org.thingsboard.rule.engine.mqtt.TbMqttNode'  
21 - ? 'MQTT'  
22 - : record.type === 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode'  
23 - ? 'RabbitMQ'  
24 - : 'REST_API';  
25 - const color =  
26 - enable == 'KafKa'  
27 - ? '#0099FF'  
28 - : enable == 'MQTT'  
29 - ? '#7C7CC9'  
30 - : enable == 'RabbitMQ'  
31 - ? '#E8A15E'  
32 - : '#81B1AB';  
33 - const text =  
34 - enable == 'KafKa'  
35 - ? 'KafKa'  
36 - : enable == 'MQTT'  
37 - ? 'MQTT'  
38 - : enable == 'RabbitMQ'  
39 - ? 'RabbitMQ'  
40 - : 'REST_API';  
41 - return h(Tag, { color: color }, () => text);  
42 - },  
43 -  
44 - format: (_text: string, record: Recordable) => {  
45 - return record.type === 'org.thingsboard.rule.engine.kafka.TbKafkaNode'  
46 - ? 'KafKa'  
47 - : record.type === 'org.thingsboard.rule.engine.mqtt.TbMqttNode'  
48 - ? 'MQTT'  
49 - : record.type === 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode'  
50 - ? 'RabbitMQ'  
51 - : 'REST_API';  
52 - },  
53 - },  
54 - {  
55 - title: '状态',  
56 - dataIndex: 'status',  
57 - width: 120,  
58 - customRender: ({ record }) => {  
59 - const status = record.status;  
60 - const enable = ~~status === 1;  
61 - const color = enable ? '#2aae67' : '#eb846f';  
62 - const text = enable ? '启用' : '禁用';  
63 - return h(Tag, { color: color }, () => text);  
64 - },  
65 - },  
66 - {  
67 - title: '描述',  
68 - dataIndex: 'remark',  
69 - width: 200,  
70 - },  
71 - {  
72 - title: '创建时间',  
73 - dataIndex: 'createTime',  
74 - width: 180,  
75 - },  
76 -];  
77 -  
78 -export const searchFormSchema: FormSchema[] = [  
79 - {  
80 - field: 'name',  
81 - label: '名称',  
82 - component: 'Input',  
83 - colProps: { span: 6 },  
84 - componentProps: {  
85 - maxLength: 36,  
86 - placeholder: '请输入名称',  
87 - },  
88 - },  
89 - {  
90 - field: 'status',  
91 - label: '状态',  
92 - component: 'Select',  
93 - componentProps: {  
94 - placeholder: '请选择状态',  
95 - options: [  
96 - { label: '已启用', value: '1' },  
97 - { label: '未启用', value: '0' },  
98 - ],  
99 - },  
100 - colProps: { span: 6 },  
101 - },  
102 -];  
1 -import { FormSchema } from '/@/components/Form';  
2 -import { findDictItemByCode } from '/@/api/system/dict';  
3 -import { isExistDataManagerNameApi } from '/@/api/datamanager/dataManagerApi';  
4 -import { ref } from 'vue';  
5 -import { useMessage } from '/@/hooks/web/useMessage';  
6 -const { createMessage } = useMessage();  
7 -  
8 -const typeValue = ref('');  
9 -  
10 -export enum CredentialsEnum {  
11 - IS_ANONYMOUS = 'anonymous',  
12 - IS_BASIC = 'basic',  
13 - IS_PEM = 'pem',  
14 -}  
15 -  
16 -export const isBasic = (type: string) => {  
17 - return type === CredentialsEnum.IS_BASIC;  
18 -};  
19 -export const isPem = (type: string) => {  
20 - return type === CredentialsEnum.IS_PEM;  
21 -};  
22 -  
23 -export const modeForm: FormSchema[] = [  
24 - {  
25 - field: 'type',  
26 - label: '转换方式',  
27 - component: 'ApiSelect',  
28 - required: true,  
29 - colProps: {  
30 - span: 13,  
31 - },  
32 - componentProps({}) {  
33 - return {  
34 - api: findDictItemByCode,  
35 - params: {  
36 - dictCode: 'convert_data_to',  
37 - },  
38 - labelField: 'itemText',  
39 - valueField: 'itemValue',  
40 - onChange(value) {  
41 - typeValue.value = value;  
42 - },  
43 - };  
44 - },  
45 - },  
46 - {  
47 - field: 'remark',  
48 - label: '描述',  
49 - colProps: { span: 13 },  
50 - component: 'Input',  
51 - componentProps: {  
52 - maxLength: 255,  
53 - placeholder: '请输入描述',  
54 - },  
55 - },  
56 -];  
57 -  
58 -export const modeKafkaInseretKeyAndValueForm: FormSchema[] = [  
59 - {  
60 - field: 'key',  
61 - label: 'Key',  
62 - colProps: { span: 12 },  
63 - required: true,  
64 - component: 'Input',  
65 - componentProps: {  
66 - maxLength: 255,  
67 - placeholder: '请输入Key',  
68 - },  
69 - },  
70 - {  
71 - field: 'value',  
72 - label: 'Value',  
73 - colProps: { span: 12 },  
74 - required: true,  
75 - component: 'Input',  
76 - componentProps: {  
77 - maxLength: 255,  
78 - placeholder: '请输入Value',  
79 - },  
80 - },  
81 -];  
82 -  
83 -export const modeApiInseretKeyAndValueForm: FormSchema[] = [  
84 - {  
85 - field: 'key',  
86 - label: 'Header',  
87 - colProps: { span: 12 },  
88 - required: true,  
89 - component: 'Input',  
90 - componentProps: {  
91 - maxLength: 255,  
92 - placeholder: '请输入Header',  
93 - },  
94 - },  
95 - {  
96 - field: 'value',  
97 - label: 'Value',  
98 - colProps: { span: 12 },  
99 - required: true,  
100 - component: 'Input',  
101 - componentProps: {  
102 - maxLength: 255,  
103 - placeholder: '请输入Value',  
104 - },  
105 - },  
106 -];  
107 -  
108 -export const modeKafkaForm: FormSchema[] = [  
109 - {  
110 - field: 'name',  
111 - label: '名称',  
112 - colProps: { span: 12 },  
113 - required: true,  
114 - component: 'Input',  
115 - componentProps: {  
116 - maxLength: 255,  
117 - placeholder: '请输入名称',  
118 - },  
119 - dynamicRules: ({ values }) => {  
120 - return [  
121 - {  
122 - required: true,  
123 - validator(_, value) {  
124 - return new Promise((resolve, reject) => {  
125 - if (value == '') {  
126 - reject('请输入名称');  
127 - } else {  
128 - if (values.name != undefined) {  
129 - isExistDataManagerNameApi({  
130 - name: value,  
131 - type:  
132 - typeValue.value == ''  
133 - ? 'org.thingsboard.rule.engine.kafka.TbKafkaNode'  
134 - : typeValue.value,  
135 - }).then((data) => {  
136 - if (data == true) {  
137 - createMessage.error('名称已存在');  
138 - resolve();  
139 - } else {  
140 - resolve();  
141 - }  
142 - });  
143 - } else {  
144 - resolve();  
145 - }  
146 - }  
147 - });  
148 - },  
149 - },  
150 - ];  
151 - },  
152 - },  
153 - {  
154 - field: 'topicPattern',  
155 - label: 'Topic',  
156 - colProps: { span: 12 },  
157 - required: true,  
158 - component: 'Input',  
159 - defaultValue: 'my-topic',  
160 - componentProps: {  
161 - maxLength: 255,  
162 - placeholder: '请输入Topic pattern',  
163 - },  
164 - },  
165 - {  
166 - field: 'bootstrapServers',  
167 - label: 'Bootstrap',  
168 - colProps: { span: 12 },  
169 - component: 'Input',  
170 - defaultValue: 'localhost:9092',  
171 - required: true,  
172 - componentProps: {  
173 - maxLength: 255,  
174 - placeholder: 'localhost:9092',  
175 - },  
176 - },  
177 - {  
178 - field: 'retries',  
179 - label: 'Retries',  
180 - colProps: { span: 12 },  
181 - component: 'InputNumber',  
182 - defaultValue: 0,  
183 - componentProps: {  
184 - maxLength: 255,  
185 - placeholder: '请输入Automatically retry times if fails',  
186 - },  
187 - },  
188 - {  
189 - field: 'batchSize',  
190 - label: 'BatchSize',  
191 - colProps: { span: 12 },  
192 - component: 'InputNumber',  
193 - defaultValue: 16384,  
194 - componentProps: {  
195 - maxLength: 255,  
196 - placeholder: '请输入Produces batch size in bytes',  
197 - },  
198 - },  
199 - {  
200 - field: 'linger',  
201 - label: 'Linger',  
202 - colProps: { span: 12 },  
203 - component: 'InputNumber',  
204 - defaultValue: 0,  
205 - componentProps: {  
206 - maxLength: 255,  
207 - placeholder: '请输入Time to buffer locally(ms)',  
208 - },  
209 - },  
210 - {  
211 - field: 'bufferMemory',  
212 - label: 'BufferMemory',  
213 - colProps: { span: 12 },  
214 - component: 'InputNumber',  
215 - defaultValue: 33554432,  
216 - componentProps: {  
217 - maxLength: 255,  
218 - placeholder: '请输入Client buffer max size in bytes',  
219 - },  
220 - },  
221 - {  
222 - field: 'acks',  
223 - component: 'Select',  
224 - label: 'Acks',  
225 - colProps: { span: 12 },  
226 - defaultValue: '-1',  
227 - componentProps: {  
228 - placeholder: '请选择Number of acknowledgments',  
229 - options: [  
230 - { label: 'all', value: 'all' },  
231 - { label: '-1', value: '-1' },  
232 - { label: '0', value: '0' },  
233 - { label: '1', value: '1' },  
234 - ],  
235 - },  
236 - },  
237 - {  
238 - field: 'keySerializer',  
239 - label: 'Key',  
240 - colProps: { span: 12 },  
241 - required: true,  
242 - component: 'Input',  
243 - defaultValue: 'org.apache.kafka.common.serialization.StringSerializer',  
244 - componentProps: {  
245 - maxLength: 255,  
246 - placeholder: 'org.apache.kafka.common.serialization.StringSerializer',  
247 - },  
248 - },  
249 - {  
250 - field: 'valueSerializer',  
251 - label: 'Value',  
252 - colProps: { span: 12 },  
253 - required: true,  
254 - component: 'Input',  
255 - defaultValue: 'org.apache.kafka.common.serialization.StringSerializer',  
256 - componentProps: {  
257 - maxLength: 255,  
258 - placeholder: 'org.apache.kafka.common.serialization.StringSerializer',  
259 - },  
260 - },  
261 - {  
262 - field: '1',  
263 - label: '',  
264 - colProps: { span: 24 },  
265 - slot: 'addValue',  
266 - component: 'Input',  
267 - },  
268 - {  
269 - field: 'addMetadataKeyValuesAsKafkaHeaders',  
270 - label: '选择',  
271 - colProps: { span: 12 },  
272 - component: 'Checkbox',  
273 - renderComponentContent: 'Add Message metadata key-value pairs to Kafka record headers',  
274 - },  
275 - {  
276 - field: 'kafkaHeadersCharset',  
277 - component: 'Select',  
278 - label: 'Charset',  
279 - required: true,  
280 - colProps: { span: 12 },  
281 - defaultValue: 'UTF-8',  
282 - componentProps: {  
283 - placeholder: '请选择Charset encoding',  
284 - options: [  
285 - { label: 'US-ASCII', value: 'US' },  
286 - { label: 'ISO-8859-1', value: 'ISO-8859-1' },  
287 - { label: 'UTF-8', value: 'UTF-8' },  
288 - { label: 'UTF-16BE', value: 'UTF-16BE' },  
289 - { label: 'UTF-16LE', value: 'UTF-16LE' },  
290 - { label: 'UTF-16', value: 'UTF-16' },  
291 - ],  
292 - },  
293 - ifShow: ({ values }) => {  
294 - return !!values.addMetadataKeyValuesAsKafkaHeaders;  
295 - },  
296 - },  
297 -  
298 - {  
299 - field: 'description',  
300 - label: '说明',  
301 - colProps: { span: 12 },  
302 - component: 'Input',  
303 - componentProps: {  
304 - maxLength: 255,  
305 - placeholder: '请输入说明',  
306 - },  
307 - },  
308 -];  
309 -  
310 -export const modeMqttForm: FormSchema[] = [  
311 - {  
312 - field: 'name',  
313 - label: '名称',  
314 - colProps: { span: 12 },  
315 - required: true,  
316 - component: 'Input',  
317 - componentProps: {  
318 - maxLength: 255,  
319 - placeholder: '请输入名称',  
320 - },  
321 - dynamicRules: ({ values }) => {  
322 - return [  
323 - {  
324 - required: true,  
325 - validator(_, value) {  
326 - return new Promise((resolve, reject) => {  
327 - if (value == '') {  
328 - reject('请输入名称');  
329 - } else {  
330 - if (values.name != undefined) {  
331 - isExistDataManagerNameApi({  
332 - name: value,  
333 - type:  
334 - typeValue.value == ''  
335 - ? 'org.thingsboard.rule.engine.mqtt.TbMqttNode'  
336 - : typeValue.value,  
337 - }).then((data) => {  
338 - if (data == true) {  
339 - createMessage.error('名称已存在');  
340 - resolve();  
341 - } else {  
342 - resolve();  
343 - }  
344 - });  
345 - } else {  
346 - resolve();  
347 - }  
348 - }  
349 - });  
350 - },  
351 - },  
352 - ];  
353 - },  
354 - },  
355 - {  
356 - field: 'topicPattern',  
357 - label: 'Topic',  
358 - colProps: { span: 12 },  
359 - required: true,  
360 - component: 'Input',  
361 - componentProps: {  
362 - maxLength: 255,  
363 - placeholder: '请输入Topic pattern',  
364 - },  
365 - },  
366 - {  
367 - field: 'host',  
368 - label: 'Host',  
369 - colProps: { span: 12 },  
370 - component: 'Input',  
371 - required: true,  
372 - defaultValue: 'localhost',  
373 - componentProps: {  
374 - maxLength: 255,  
375 - placeholder: '请输入Host',  
376 - },  
377 - },  
378 - {  
379 - field: 'port',  
380 - label: 'Port',  
381 - colProps: { span: 12 },  
382 - component: 'InputNumber',  
383 - defaultValue: 1883,  
384 - required: true,  
385 - componentProps: {  
386 - maxLength: 255,  
387 - placeholder: '请输入Port',  
388 - },  
389 - },  
390 - {  
391 - field: 'connectTimeoutSec',  
392 - label: 'Connection',  
393 - colProps: { span: 12 },  
394 - component: 'InputNumber',  
395 - defaultValue: 10,  
396 - required: true,  
397 - componentProps: {  
398 - maxLength: 255,  
399 - placeholder: '请输入Connection timeout (sec)',  
400 - },  
401 - },  
402 - {  
403 - field: 'clientId',  
404 - label: 'Client ID',  
405 - colProps: { span: 12 },  
406 - component: 'Input',  
407 - componentProps: {  
408 - maxLength: 255,  
409 - placeholder: '请输入Client ID',  
410 - },  
411 - },  
412 - {  
413 - field: 'cleanSession',  
414 - label: 'Clean',  
415 - colProps: { span: 12 },  
416 - component: 'Checkbox',  
417 - renderComponentContent: 'Clean session',  
418 - },  
419 - {  
420 - field: 'ssl',  
421 - label: 'Enable',  
422 - colProps: { span: 12 },  
423 - component: 'Checkbox',  
424 - renderComponentContent: 'Enable SSL',  
425 - },  
426 - {  
427 - field: 'type',  
428 - component: 'Select',  
429 - label: 'type',  
430 - colProps: { span: 12 },  
431 - componentProps: {  
432 - placeholder: '请选择Credentials',  
433 - options: [  
434 - { label: 'Anonymous', value: 'anonymous' },  
435 - { label: 'Basic', value: 'basic' },  
436 - { label: 'PEM', value: 'pem' },  
437 - ],  
438 - },  
439 - },  
440 - {  
441 - field: 'username',  
442 - label: 'Username',  
443 - colProps: { span: 12 },  
444 - component: 'Input',  
445 - required: true,  
446 - componentProps: {  
447 - maxLength: 255,  
448 - placeholder: '请输入Username',  
449 - },  
450 - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),  
451 - },  
452 - {  
453 - field: 'password',  
454 - label: 'Password',  
455 - colProps: { span: 12 },  
456 - component: 'Input',  
457 - componentProps: {  
458 - maxLength: 255,  
459 - placeholder: '请输入Password',  
460 - },  
461 - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),  
462 - },  
463 - {  
464 - field: '4',  
465 - label: '',  
466 - colProps: { span: 24 },  
467 - component: 'Input',  
468 - slot: 'uploadAdd1',  
469 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
470 - },  
471 - {  
472 - field: '5',  
473 - label: '',  
474 - colProps: { span: 24 },  
475 - component: 'Input',  
476 - slot: 'uploadAdd2',  
477 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
478 - },  
479 - {  
480 - field: '6',  
481 - label: '',  
482 - colProps: { span: 24 },  
483 - component: 'Input',  
484 - slot: 'uploadAdd3',  
485 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
486 - },  
487 - {  
488 - field: 'password',  
489 - label: 'Password',  
490 - colProps: { span: 12 },  
491 - component: 'Input',  
492 - componentProps: {  
493 - maxLength: 255,  
494 - placeholder: '请输入Password',  
495 - },  
496 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
497 - },  
498 - {  
499 - field: 'description',  
500 - label: '说明',  
501 - colProps: { span: 12 },  
502 - component: 'Input',  
503 - componentProps: {  
504 - maxLength: 255,  
505 - placeholder: '请输入说明',  
506 - },  
507 - },  
508 -];  
509 -  
510 -export const modeRabbitMqForm: FormSchema[] = [  
511 - {  
512 - field: 'name',  
513 - label: '名称',  
514 - colProps: { span: 12 },  
515 - required: true,  
516 - component: 'Input',  
517 - componentProps: {  
518 - maxLength: 255,  
519 - placeholder: '请输入名称',  
520 - },  
521 - dynamicRules: ({ values }) => {  
522 - return [  
523 - {  
524 - required: true,  
525 - validator(_, value) {  
526 - return new Promise((resolve, reject) => {  
527 - if (value == '') {  
528 - reject('请输入名称');  
529 - } else {  
530 - if (values.name != undefined) {  
531 - isExistDataManagerNameApi({  
532 - name: value,  
533 - type:  
534 - typeValue.value == ''  
535 - ? 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode'  
536 - : typeValue.value,  
537 - }).then((data) => {  
538 - if (data == true) {  
539 - createMessage.error('名称已存在');  
540 - resolve();  
541 - } else {  
542 - resolve();  
543 - }  
544 - });  
545 - } else {  
546 - resolve();  
547 - }  
548 - }  
549 - });  
550 - },  
551 - },  
552 - ];  
553 - },  
554 - },  
555 - {  
556 - field: 'exchangeNamePattern',  
557 - label: 'Exchange',  
558 - colProps: { span: 12 },  
559 - component: 'Input',  
560 - componentProps: {  
561 - maxLength: 255,  
562 - placeholder: '请输入Exchange name pattern',  
563 - },  
564 - },  
565 - {  
566 - field: 'routingKeyPattern',  
567 - label: 'Routing',  
568 - colProps: { span: 12 },  
569 - component: 'Input',  
570 - componentProps: {  
571 - maxLength: 255,  
572 - placeholder: '请输入Routing key pattern',  
573 - },  
574 - },  
575 - {  
576 - field: 'messageProperties',  
577 - component: 'Select',  
578 - label: 'Message',  
579 - colProps: { span: 12 },  
580 - componentProps: {  
581 - placeholder: '请选择Message properties',  
582 - options: [  
583 - { label: 'BASIC', value: 'BASIC' },  
584 - { label: 'TEXT_PLAIN', value: 'TEXT_PLAIN' },  
585 - { label: 'MINIMAL_BASIC', value: 'MINIMAL_BASIC' },  
586 - { label: 'MINIMAL_PERSISTENT_BASIC', value: 'MINIMAL_PERSISTENT_BASIC' },  
587 - { label: 'PERSISTENT_BASIC', value: 'PERSISTENT_BASIC' },  
588 - { label: 'PERSISTENT_TEXT_PLAIN', value: 'PERSISTENT_TEXT_PLAIN' },  
589 - ],  
590 - },  
591 - },  
592 - {  
593 - field: 'host',  
594 - label: 'Host',  
595 - colProps: { span: 12 },  
596 - component: 'Input',  
597 - required: true,  
598 - defaultValue: 'localhost',  
599 - componentProps: {  
600 - maxLength: 255,  
601 - placeholder: 'localhost',  
602 - },  
603 - },  
604 - {  
605 - field: 'port',  
606 - label: 'Port',  
607 - colProps: { span: 12 },  
608 - component: 'InputNumber',  
609 - defaultValue: 5672,  
610 - required: true,  
611 - componentProps: {  
612 - maxLength: 255,  
613 - placeholder: '请输入Port',  
614 - },  
615 - },  
616 - {  
617 - field: 'virtualHost',  
618 - label: 'Virtual',  
619 - colProps: { span: 12 },  
620 - component: 'Input',  
621 - defaultValue: '/',  
622 - componentProps: {  
623 - maxLength: 255,  
624 - placeholder: '/',  
625 - },  
626 - },  
627 - {  
628 - field: 'username',  
629 - label: 'Username',  
630 - colProps: { span: 12 },  
631 - component: 'Input',  
632 - defaultValue: 'guest',  
633 - componentProps: {  
634 - maxLength: 255,  
635 - placeholder: '请输入Username',  
636 - },  
637 - },  
638 - {  
639 - field: 'password',  
640 - label: 'Password',  
641 - colProps: { span: 12 },  
642 - component: 'Input',  
643 - defaultValue: 'guest',  
644 - componentProps: {  
645 - maxLength: 255,  
646 - placeholder: '请输入Password',  
647 - },  
648 - },  
649 - {  
650 - field: 'automaticRecoveryEnabled',  
651 - label: ' Automatic',  
652 - colProps: { span: 12 },  
653 - component: 'Checkbox',  
654 - renderComponentContent: 'Automatic recovery',  
655 - },  
656 - {  
657 - field: 'connectionTimeout',  
658 - label: 'Connect',  
659 - colProps: { span: 12 },  
660 - component: 'InputNumber',  
661 - defaultValue: 60000,  
662 - componentProps: {  
663 - maxLength: 255,  
664 - placeholder: '请输入Connection timeout (ms)',  
665 - },  
666 - },  
667 - {  
668 - field: 'handshakeTimeout',  
669 - label: 'Handshake',  
670 - colProps: { span: 12 },  
671 - component: 'InputNumber',  
672 - defaultValue: 10000,  
673 - componentProps: {  
674 - maxLength: 255,  
675 - placeholder: '请输入Handshake timeout (ms)',  
676 - },  
677 - },  
678 - {  
679 - field: '1',  
680 - label: '',  
681 - colProps: { span: 24 },  
682 - component: 'Input',  
683 - slot: 'addKeyAndValue',  
684 - },  
685 -  
686 - {  
687 - field: 'description',  
688 - label: '说明',  
689 - colProps: { span: 12 },  
690 - component: 'Input',  
691 - componentProps: {  
692 - maxLength: 255,  
693 - placeholder: '请输入说明',  
694 - },  
695 - },  
696 -];  
697 -  
698 -export const modeApiForm: FormSchema[] = [  
699 - {  
700 - field: 'name',  
701 - label: '名称',  
702 - colProps: { span: 12 },  
703 - required: true,  
704 - component: 'Input',  
705 - componentProps: {  
706 - maxLength: 255,  
707 - placeholder: '请输入名称',  
708 - },  
709 - dynamicRules: ({ values }) => {  
710 - return [  
711 - {  
712 - required: true,  
713 - validator(_, value) {  
714 - return new Promise((resolve, reject) => {  
715 - if (value == '') {  
716 - reject('请输入名称');  
717 - } else {  
718 - if (values.name != undefined) {  
719 - isExistDataManagerNameApi({  
720 - name: value,  
721 - type:  
722 - typeValue.value == ''  
723 - ? 'org.thingsboard.rule.engine.rest.TbRestApiCallNode'  
724 - : typeValue.value,  
725 - }).then((data) => {  
726 - if (data == true) {  
727 - createMessage.error('名称已存在');  
728 - resolve();  
729 - } else {  
730 - resolve();  
731 - }  
732 - });  
733 - } else {  
734 - resolve();  
735 - }  
736 - }  
737 - });  
738 - },  
739 - },  
740 - ];  
741 - },  
742 - },  
743 - {  
744 - field: 'restEndpointUrlPattern',  
745 - label: 'Endpoint',  
746 - colProps: { span: 12 },  
747 - required: true,  
748 - defaultValue: 'http://localhost/api',  
749 - component: 'Input',  
750 - componentProps: {  
751 - maxLength: 255,  
752 - placeholder: '请输入Endpoint URL pattern',  
753 - },  
754 - },  
755 - {  
756 - field: 'requestMethod',  
757 - component: 'Select',  
758 - label: 'Request',  
759 - colProps: { span: 12 },  
760 - defaultValue: 'POST',  
761 - componentProps: {  
762 - placeholder: '请选择Request method',  
763 - options: [  
764 - { label: 'GET', value: 'GET' },  
765 - { label: 'POST', value: 'POST' },  
766 - { label: 'PUT', value: 'PUT' },  
767 - { label: 'DELETE', value: 'DELETE' },  
768 - ],  
769 - },  
770 - },  
771 - {  
772 - field: 'enableProxy',  
773 - label: '选择',  
774 - colProps: { span: 12 },  
775 - component: 'Checkbox',  
776 - renderComponentContent: 'Enable proxy',  
777 - },  
778 -  
779 - {  
780 - field: 'proxyHost',  
781 - label: 'Host',  
782 - colProps: { span: 12 },  
783 - required: true,  
784 - component: 'Input',  
785 - componentProps: {  
786 - maxLength: 255,  
787 - placeholder: 'http或者https开头',  
788 - },  
789 - ifShow: ({ values }) => {  
790 - return !!values.enableProxy;  
791 - },  
792 - },  
793 - {  
794 - field: 'proxyPort',  
795 - label: 'Port',  
796 - colProps: { span: 12 },  
797 - required: true,  
798 - component: 'InputNumber',  
799 - defaultValue: 0,  
800 - componentProps: {  
801 - maxLength: 255,  
802 - placeholder: 'http或者https开头',  
803 - },  
804 - ifShow: ({ values }) => {  
805 - return !!values.enableProxy;  
806 - },  
807 - },  
808 - {  
809 - field: 'proxyUser',  
810 - label: 'User',  
811 - colProps: { span: 12 },  
812 - required: true,  
813 - component: 'Input',  
814 - componentProps: {  
815 - maxLength: 255,  
816 - placeholder: '请输入Proxy user',  
817 - },  
818 - ifShow: ({ values }) => {  
819 - return !!values.enableProxy;  
820 - },  
821 - },  
822 - {  
823 - field: 'proxyPassword',  
824 - label: 'Password',  
825 - colProps: { span: 12 },  
826 - required: true,  
827 - component: 'Input',  
828 - componentProps: {  
829 - maxLength: 255,  
830 - placeholder: '请输入Proxy password',  
831 - },  
832 - ifShow: ({ values }) => {  
833 - return !!values.enableProxy;  
834 - },  
835 - },  
836 -  
837 - {  
838 - field: 'useSystemProxyProperties',  
839 - label: '选择',  
840 - colProps: { span: 12 },  
841 - component: 'Checkbox',  
842 - renderComponentContent: 'Use system proxy properties',  
843 - },  
844 - {  
845 - field: 'maxParallelRequestsCount',  
846 - label: 'Max',  
847 - colProps: { span: 12 },  
848 - required: true,  
849 - component: 'InputNumber',  
850 - defaultValue: 0,  
851 - componentProps: {  
852 - maxLength: 255,  
853 - placeholder: '请输入Max number of paraller requests',  
854 - },  
855 - ifShow: ({ values }) => {  
856 - return !!values.useSystemProxyProperties;  
857 - },  
858 - },  
859 - {  
860 - field: 'ignoreRequestBody',  
861 - label: '选择',  
862 - colProps: { span: 12 },  
863 - component: 'Checkbox',  
864 - renderComponentContent: 'Without request body',  
865 - },  
866 - {  
867 - field: 'readTimeoutMs',  
868 - label: 'Read',  
869 - colProps: { span: 12 },  
870 - required: true,  
871 - component: 'InputNumber',  
872 - defaultValue: 0,  
873 - componentProps: {  
874 - maxLength: 255,  
875 - placeholder: '请输入Read timeout in times',  
876 - },  
877 - ifShow: ({ values }) => {  
878 - return !values.useSystemProxyProperties;  
879 - },  
880 - },  
881 - {  
882 - field: 'maxParallelRequestsCount',  
883 - label: 'Max',  
884 - colProps: { span: 12 },  
885 - required: true,  
886 - component: 'InputNumber',  
887 - defaultValue: 0,  
888 - componentProps: {  
889 - maxLength: 255,  
890 - placeholder: '请输入Max number of paraller requests',  
891 - },  
892 - ifShow: ({ values }) => {  
893 - return !values.useSystemProxyProperties;  
894 - },  
895 - },  
896 - {  
897 - field: 'Header',  
898 - label: 'Header',  
899 - colProps: { span: 12 },  
900 - required: true,  
901 - component: 'Input',  
902 - defaultValue: 'Content-Type',  
903 - componentProps: {  
904 - maxLength: 255,  
905 - placeholder: 'Content-Type',  
906 - },  
907 - },  
908 - {  
909 - field: 'Value',  
910 - label: 'Value',  
911 - colProps: { span: 12 },  
912 - required: true,  
913 - component: 'Input',  
914 - defaultValue: 'application/json',  
915 - componentProps: {  
916 - maxLength: 255,  
917 - placeholder: 'application/json',  
918 - },  
919 - },  
920 - {  
921 - field: '1',  
922 - label: '',  
923 - colProps: { span: 24 },  
924 - component: 'Input',  
925 - slot: 'addKeyAndValue',  
926 - },  
927 -  
928 - {  
929 - field: 'useRedisQueueForMsgPersistence',  
930 - label: '选择',  
931 - colProps: { span: 12 },  
932 - component: 'Checkbox',  
933 - renderComponentContent: 'Use redis queue for message persistence',  
934 - },  
935 - {  
936 - field: 'trimQueue',  
937 - label: '选择',  
938 - colProps: { span: 12 },  
939 - component: 'Checkbox',  
940 - renderComponentContent: 'Trim redis queue',  
941 - ifShow: ({ values }) => {  
942 - return !!values.useRedisQueueForMsgPersistence;  
943 - },  
944 - },  
945 - {  
946 - field: 'maxQueueSize',  
947 - label: 'Redis',  
948 - colProps: { span: 12 },  
949 - required: true,  
950 - component: 'InputNumber',  
951 - defaultValue: 0,  
952 - componentProps: {  
953 - maxLength: 255,  
954 - placeholder: '请输入Redis queue max size',  
955 - },  
956 - ifShow: ({ values }) => {  
957 - return !!values.useRedisQueueForMsgPersistence;  
958 - },  
959 - },  
960 -  
961 - {  
962 - field: 'type',  
963 - component: 'Select',  
964 - label: 'type',  
965 - colProps: { span: 12 },  
966 - componentProps: {  
967 - placeholder: '请选择Number of acknowledgments',  
968 - options: [  
969 - { label: 'Anonymous', value: 'anonymous' },  
970 - { label: 'Basic', value: 'basic' },  
971 - { label: 'PEM', value: 'pem' },  
972 - ],  
973 - },  
974 - },  
975 - {  
976 - field: 'username',  
977 - label: 'Username',  
978 - colProps: { span: 12 },  
979 - component: 'Input',  
980 - required: true,  
981 - componentProps: {  
982 - maxLength: 255,  
983 - placeholder: '请输入Username',  
984 - },  
985 - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),  
986 - },  
987 - {  
988 - field: 'password',  
989 - label: 'Password',  
990 - colProps: { span: 12 },  
991 - component: 'Input',  
992 - required: true,  
993 - componentProps: {  
994 - maxLength: 255,  
995 - placeholder: '请输入Password',  
996 - },  
997 - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),  
998 - },  
999 - {  
1000 - field: '1',  
1001 - label: '',  
1002 - colProps: { span: 24 },  
1003 - component: 'Input',  
1004 - slot: 'uploadAdd1',  
1005 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
1006 - },  
1007 - {  
1008 - field: '1',  
1009 - label: '',  
1010 - colProps: { span: 24 },  
1011 - component: 'Input',  
1012 - slot: 'uploadAdd2',  
1013 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
1014 - },  
1015 - {  
1016 - field: '1',  
1017 - label: '',  
1018 - colProps: { span: 24 },  
1019 - component: 'Input',  
1020 - slot: 'uploadAdd3',  
1021 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
1022 - },  
1023 - {  
1024 - field: 'password',  
1025 - label: 'Password',  
1026 - colProps: { span: 12 },  
1027 - component: 'Input',  
1028 - componentProps: {  
1029 - maxLength: 255,  
1030 - placeholder: '请输入Password',  
1031 - },  
1032 - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),  
1033 - },  
1034 -  
1035 - {  
1036 - field: 'description',  
1037 - label: '说明',  
1038 - colProps: { span: 12 },  
1039 - component: 'Input',  
1040 - componentProps: {  
1041 - maxLength: 255,  
1042 - placeholder: '请输入说明',  
1043 - },  
1044 - },  
1045 -];  
1 -<template>  
2 - <div class="root">  
3 - <div class="root-form">  
4 - <BasicForm :showSubmitButton="false" @register="register">  
5 - <template #addKeyAndValue="{ field }">  
6 - <span style="display: none">{{ field }}</span>  
7 - <div>  
8 - <div>  
9 - <template v-for="(item, index) in keyAndValueArr" :key="index">  
10 - <span style="display: none">{{ item + index }}</span>  
11 - <BasicForm  
12 - :showResetButton="false"  
13 - :showSubmitButton="false"  
14 - @register="registerKeyAndValue"  
15 - />  
16 - </template>  
17 - <div  
18 - style="  
19 - width: 7vw;  
20 - height: 3.3vh;  
21 - display: flex;  
22 - flex-direction: row;  
23 - justify-content: center;  
24 - align-items: center;  
25 - margin-left: 1.8vw;  
26 - "  
27 - >  
28 - <div  
29 - style="  
30 - width: 2.9vw;  
31 - height: 3.3vh;  
32 - background-color: #0960bd;  
33 - border-radius: 2px;  
34 - cursor: pointer;  
35 - text-align: center;  
36 - line-height: 3.1vh;  
37 - "  
38 - >  
39 - <span @click="addKeyAndValueFunc" style="color: white">添加</span>  
40 - </div>  
41 - <div  
42 - style="  
43 - width: 2.9vw;  
44 - height: 3.3vh;  
45 - margin-left: 1vw;  
46 - background-color: #ed6f6f;  
47 - border-radius: 2px;  
48 - cursor: pointer;  
49 - text-align: center;  
50 - line-height: 3.1vh;  
51 - "  
52 - >  
53 - <span @click="removeKeyAndValueFunc" style="color: white">删除</span>  
54 - </div>  
55 - </div>  
56 - <div> </div>  
57 - </div>  
58 - </div>  
59 - </template>  
60 - <template #uploadAdd1="{ field }">  
61 - <span style="display: none">{{ field }}</span>  
62 - <a-upload-dragger  
63 - v-model:fileList="fileList"  
64 - name="file"  
65 - :multiple="true"  
66 - action="https://www.mocky.io/v2/5cc8019d300000980a055e76"  
67 - @change="handleChange"  
68 - >  
69 - <p class="ant-upload-drag-icon">  
70 - <InboxOutlined />  
71 - </p>  
72 - <p class="ant-upload-text">Click or drag file to this area to upload</p>  
73 - <p class="ant-upload-hint">  
74 - Support for a single or bulk upload. Strictly prohibit from uploading company data or  
75 - other band files  
76 - </p>  
77 - </a-upload-dragger>  
78 - </template>  
79 - <template #uploadAdd2="{ field }">  
80 - <span style="display: none">{{ field }}</span>  
81 - <a-upload-dragger  
82 - v-model:fileList="fileList"  
83 - name="file"  
84 - :multiple="true"  
85 - action="https://www.mocky.io/v2/5cc8019d300000980a055e76"  
86 - @change="handleChange"  
87 - >  
88 - <p class="ant-upload-drag-icon">  
89 - <InboxOutlined />  
90 - </p>  
91 - <p class="ant-upload-text">Click or drag file to this area to upload</p>  
92 - <p class="ant-upload-hint">  
93 - Support for a single or bulk upload. Strictly prohibit from uploading company data or  
94 - other band files  
95 - </p>  
96 - </a-upload-dragger>  
97 - </template>  
98 - <template #uploadAdd3="{ field }">  
99 - <span style="display: none">{{ field }}</span>  
100 - <a-upload-dragger  
101 - v-model:fileList="fileList"  
102 - name="file"  
103 - :multiple="true"  
104 - action="https://www.mocky.io/v2/5cc8019d300000980a055e76"  
105 - @change="handleChange"  
106 - >  
107 - <p class="ant-upload-drag-icon">  
108 - <InboxOutlined />  
109 - </p>  
110 - <p class="ant-upload-text">Click or drag file to this area to upload</p>  
111 - <p class="ant-upload-hint">  
112 - Support for a single or bulk upload. Strictly prohibit from uploading company data or  
113 - other band files  
114 - </p>  
115 - </a-upload-dragger>  
116 - </template>  
117 - </BasicForm>  
118 - </div>  
119 - </div>  
120 -</template>  
121 -<script lang="ts">  
122 - import { defineComponent, ref, reactive } from 'vue';  
123 - import { BasicForm, useForm } from '/@/components/Form';  
124 - import { modeApiForm, modeApiInseretKeyAndValueForm } from '../config';  
125 - import { InboxOutlined } from '@ant-design/icons-vue';  
126 - import { Alert, Divider, Descriptions, Upload } from 'ant-design-vue';  
127 - interface IKeyAndValue {  
128 - key: string;  
129 - value: string;  
130 - }  
131 - export default defineComponent({  
132 - components: {  
133 - BasicForm,  
134 - [Alert.name]: Alert,  
135 - [Divider.name]: Divider,  
136 - [Descriptions.name]: Descriptions,  
137 - [Descriptions.Item.name]: Descriptions.Item,  
138 - InboxOutlined,  
139 - [Upload.Dragger.name]: Upload.Dragger,  
140 - },  
141 - emits: ['next', 'prev', 'register'],  
142 - setup(_, { emit }) {  
143 - const fileList = ref<[]>([]);  
144 - const keyAndValueArr = ref<[]>([]);  
145 - const temp = ref({});  
146 - let tempObj = ref({});  
147 - const otherPropertiesValues = reactive({  
148 - headers: {},  
149 - });  
150 - const credentialsV = reactive({  
151 - credentials: {  
152 - type: '',  
153 - },  
154 - });  
155 - const keyAndValueArrTemp = ref<[]>([]);  
156 - const keyAndValueObj = reactive<IKeyAndValue>({  
157 - key: '',  
158 - value: '',  
159 - });  
160 - const sonValues = reactive({  
161 - configuration: {},  
162 - });  
163 - const [register, { validate, setFieldsValue, resetFields: defineClearFunc }] = useForm({  
164 - labelWidth: 80,  
165 - schemas: modeApiForm,  
166 - actionColOptions: {  
167 - span: 14,  
168 - },  
169 - resetButtonOptions: {  
170 - text: '上一步',  
171 - },  
172 -  
173 - resetFunc: customResetFunc,  
174 - submitFunc: customSubmitFunc,  
175 - });  
176 -  
177 - const [  
178 - registerKeyAndValue,  
179 - { validate: validateKeyAndValue, resetFields: defineClearKeyAndValueFunc },  
180 - ] = useForm({  
181 - labelWidth: 80,  
182 - schemas: modeApiInseretKeyAndValueForm,  
183 - actionColOptions: {  
184 - span: 14,  
185 - },  
186 - });  
187 - const setStepTwoFieldsValueFunc = (v, v1) => {  
188 - setFieldsValue(v);  
189 - setFieldsValue({  
190 - name: v1,  
191 - });  
192 - };  
193 - const customClearStepTwoValueFunc = async () => {  
194 - defineClearFunc();  
195 - defineClearKeyAndValueFunc();  
196 - };  
197 - async function customResetFunc() {  
198 - emit('prev');  
199 - }  
200 - async function customSubmitFunc() {  
201 - try {  
202 - const values = await validate();  
203 - emit('next', values);  
204 - } catch (error) {  
205 - } finally {  
206 - }  
207 - }  
208 - const tempGetKeyAndVal = async () => {  
209 - temp.value = await validateKeyAndValue();  
210 - };  
211 - // const defaultAddKeyAndValueFunc = () => {  
212 - // if (keyAndValueArr.value.length == 0) {  
213 - // keyAndValueArr.value.push(keyAndValueObj as never);  
214 - // }  
215 - // };  
216 - // defaultAddKeyAndValueFunc();  
217 -  
218 - const getDefaultValue = async () => {  
219 - await tempGetKeyAndVal();  
220 - keyAndValueArrTemp.value.push(temp.value as never);  
221 - };  
222 -  
223 - const addKeyAndValueFunc = async () => {  
224 - keyAndValueArr.value.push(keyAndValueObj as never);  
225 - await tempGetKeyAndVal();  
226 - tempObj.value = temp.value;  
227 - keyAndValueArrTemp.value.push(tempObj.value as never);  
228 - };  
229 - const removeKeyAndValueFunc = () => {  
230 - keyAndValueArr.value.splice(0, 1);  
231 - };  
232 - const handleChange = () => {};  
233 -  
234 - const getSonValueFunc = async () => {  
235 - sonValues.configuration = await validate();  
236 - if (keyAndValueArrTemp.value.length != 0) {  
237 - await getDefaultValue();  
238 - }  
239 - credentialsV.credentials.type = sonValues.configuration.type;  
240 - const kong = {};  
241 - let kongTemp = {};  
242 - keyAndValueArrTemp.value.map((item) => {  
243 - kong[item.key] = item.value;  
244 - });  
245 - kongTemp = JSON.parse(JSON.stringify(kong));  
246 - otherPropertiesValues.headers = kongTemp;  
247 - Object.assign(sonValues.configuration, otherPropertiesValues, credentialsV);  
248 - return sonValues;  
249 - };  
250 - return {  
251 - register,  
252 - setStepTwoFieldsValueFunc,  
253 - customClearStepTwoValueFunc,  
254 - addKeyAndValueFunc,  
255 - removeKeyAndValueFunc,  
256 - getSonValueFunc,  
257 - keyAndValueArr,  
258 - registerKeyAndValue,  
259 - fileList,  
260 - handleChange,  
261 - };  
262 - },  
263 - });  
264 -</script>  
265 -<style lang="less" scoped>  
266 - .root {  
267 - width: 47.55vw;  
268 - border: 1px solid #bfbfbf;  
269 - display: flex;  
270 - margin-top: 1vh;  
271 - margin-left: 1.5vw;  
272 - border-radius: 8px;  
273 -  
274 - .root-form {  
275 - width: 45vw;  
276 - margin: 1vh 1vw;  
277 - position: relative;  
278 - :deep .ant-input-number {  
279 - width: 18.35vw !important;  
280 - }  
281 - :deep .ant-btn {  
282 - position: absolute;  
283 - right: 1vw;  
284 - background-color: #0960bd;  
285 - border-radius: 2px;  
286 - span {  
287 - color: white;  
288 - }  
289 - }  
290 - }  
291 - }  
292 -</style>  
1 -<template>  
2 - <div class="root">  
3 - <div class="root-form">  
4 - <BasicForm :showResetButton="false" :showSubmitButton="false" @register="register">  
5 - <template #addValue="{ field }">  
6 - <span style="display: none">{{ field }}</span>  
7 - <div>  
8 - <div>  
9 - <div v-if="keyAndValueArr.length > 0">  
10 - <template v-for="(item, index) in keyAndValueArr" :key="index">  
11 - <span style="display: none">{{ item + index }}</span>  
12 - <BasicForm  
13 - :showResetButton="false"  
14 - :showSubmitButton="false"  
15 - @register="registerKeyAndValue"  
16 - />  
17 - </template>  
18 - </div>  
19 - <div  
20 - style="  
21 - width: 7vw;  
22 - height: 3.3vh;  
23 - display: flex;  
24 - flex-direction: row;  
25 - justify-content: center;  
26 - align-items: center;  
27 - margin-left: 1.8vw;  
28 - "  
29 - >  
30 - <div  
31 - style="  
32 - width: 2.9vw;  
33 - height: 3.3vh;  
34 - background-color: #0960bd;  
35 - border-radius: 2px;  
36 - cursor: pointer;  
37 - text-align: center;  
38 - line-height: 3.1vh;  
39 - "  
40 - >  
41 - <span @click="addKeyAndValueFunc" style="color: white">添加</span>  
42 - </div>  
43 - <div  
44 - style="  
45 - width: 2.9vw;  
46 - height: 3.3vh;  
47 - margin-left: 1vw;  
48 - background-color: #ed6f6f;  
49 - border-radius: 2px;  
50 - cursor: pointer;  
51 - text-align: center;  
52 - line-height: 3.1vh;  
53 - "  
54 - >  
55 - <span @click="removeKeyAndValueFunc" style="color: white">删除</span>  
56 - </div>  
57 - </div>  
58 - <div> </div>  
59 - </div>  
60 - </div>  
61 - </template>  
62 - </BasicForm>  
63 - <div  
64 - style="  
65 - width: 3.3vw;  
66 - height: 3.3vh;  
67 - margin-left: 22vw;  
68 - margin-top: 2vh;  
69 - background-color: #0960bd;  
70 - border-radius: 2px;  
71 - cursor: pointer;  
72 - text-align: center;  
73 - line-height: 3.1vh;  
74 - "  
75 - >  
76 - <span @click="customResetFunc" style="color: white">上一步</span>  
77 - </div>  
78 - </div>  
79 - </div>  
80 -</template>  
81 -<script lang="ts">  
82 - import { defineComponent, ref, reactive } from 'vue';  
83 - import { BasicForm, useForm } from '/@/components/Form';  
84 - import { modeKafkaForm, modeKafkaInseretKeyAndValueForm } from '../config';  
85 - import { Alert, Divider, Descriptions } from 'ant-design-vue';  
86 -  
87 - interface IKeyAndValue {  
88 - key: string;  
89 - value: string;  
90 - }  
91 -  
92 - export default defineComponent({  
93 - components: {  
94 - BasicForm,  
95 - [Alert.name]: Alert,  
96 - [Divider.name]: Divider,  
97 - [Descriptions.name]: Descriptions,  
98 - [Descriptions.Item.name]: Descriptions.Item,  
99 - },  
100 - emits: ['next', 'prev', 'register'],  
101 - setup(_, { emit }) {  
102 - const temp = ref({});  
103 - let tempObj = ref({});  
104 - const keyAndValueArr = ref<[]>([]);  
105 - const keyAndValueArrTemp = ref<[]>([]);  
106 - const vType = ref('');  
107 - const keyAndValueObj = reactive<IKeyAndValue>({  
108 - key: '',  
109 - value: '',  
110 - });  
111 - const sonValues = reactive({  
112 - configuration: {},  
113 - });  
114 - const otherPropertiesValues = reactive({  
115 - otherProperties: {},  
116 - });  
117 -  
118 - const [register, { validate, setFieldsValue, resetFields: defineClearFunc, clearValidate }] =  
119 - useForm({  
120 - labelWidth: 80,  
121 - schemas: modeKafkaForm,  
122 - actionColOptions: {  
123 - span: 14,  
124 - },  
125 - resetButtonOptions: {  
126 - text: '上一步',  
127 - },  
128 - resetFunc: customResetFunc,  
129 - });  
130 -  
131 - const [  
132 - registerKeyAndValue,  
133 - { validate: validateKeyAndValue, resetFields: defineClearKeyAndValueFunc },  
134 - ] = useForm({  
135 - labelWidth: 80,  
136 - schemas: modeKafkaInseretKeyAndValueForm,  
137 - actionColOptions: {  
138 - span: 14,  
139 - },  
140 - });  
141 -  
142 - const clearValidateFunc = async () => {  
143 - await clearValidate(['name']);  
144 - };  
145 -  
146 - const setStepTwoFieldsValueFunc = async (v, v1) => {  
147 - setFieldsValue(v);  
148 - vType.value = v1;  
149 - setFieldsValue({  
150 - name: v1,  
151 - });  
152 - };  
153 -  
154 - const customClearStepTwoValueFunc = async () => {  
155 - defineClearFunc();  
156 - defineClearKeyAndValueFunc();  
157 - };  
158 - async function customResetFunc() {  
159 - emit('prev');  
160 - }  
161 -  
162 - const tempGetKeyAndVal = async () => {  
163 - temp.value = await validateKeyAndValue();  
164 - };  
165 - // const defaultAddKeyAndValueFunc = () => {  
166 - // if (keyAndValueArr.value.length == 0) {  
167 - // keyAndValueArr.value.push(keyAndValueObj as never);  
168 - // }  
169 - // };  
170 - // defaultAddKeyAndValueFunc();  
171 -  
172 - const getDefaultValue = async () => {  
173 - await tempGetKeyAndVal();  
174 - keyAndValueArrTemp.value.push(temp.value as never);  
175 - };  
176 -  
177 - const addKeyAndValueFunc = async () => {  
178 - keyAndValueArr.value.push(keyAndValueObj as never);  
179 - await tempGetKeyAndVal();  
180 - tempObj.value = temp.value;  
181 - keyAndValueArrTemp.value.push(tempObj.value as never);  
182 - };  
183 - const removeKeyAndValueFunc = () => {  
184 - keyAndValueArr.value.splice(0, 1);  
185 - };  
186 -  
187 - const getSonValueFunc = async () => {  
188 - try {  
189 - sonValues.configuration = await validate();  
190 - if (keyAndValueArrTemp.value.length != 0) {  
191 - await getDefaultValue();  
192 - }  
193 - const kong = {};  
194 - let kongTemp = {};  
195 - keyAndValueArrTemp.value.map((item) => {  
196 - kong[item.key] = item.value;  
197 - });  
198 - kongTemp = JSON.parse(JSON.stringify(kong));  
199 - otherPropertiesValues.otherProperties = kongTemp;  
200 - Object.assign(sonValues.configuration, otherPropertiesValues);  
201 - return sonValues;  
202 - } catch (e) {  
203 - return e;  
204 - }  
205 - };  
206 - return {  
207 - clearValidateFunc,  
208 - getSonValueFunc,  
209 - keyAndValueArr,  
210 - register,  
211 - setStepTwoFieldsValueFunc,  
212 - customClearStepTwoValueFunc,  
213 - addKeyAndValueFunc,  
214 - registerKeyAndValue,  
215 - removeKeyAndValueFunc,  
216 - customResetFunc,  
217 - };  
218 - },  
219 - });  
220 -</script>  
221 -<style lang="less" scoped>  
222 - .root {  
223 - width: 47.55vw;  
224 - border: 1px solid #d9d9d9;  
225 - display: flex;  
226 - margin-top: 1vh;  
227 - margin-left: 1.5vw;  
228 - border-radius: 8px;  
229 - .root-form {  
230 - width: 45vw;  
231 - margin: 1vh 1vw;  
232 - position: relative;  
233 - :deep .ant-input-number {  
234 - width: 18.35vw !important;  
235 - }  
236 - }  
237 - }  
238 -</style>  
1 -<template>  
2 - <div class="root">  
3 - <div class="root-form">  
4 - <BasicForm :showSubmitButton="false" @register="register">  
5 - <template #uploadAdd1="{ field }">  
6 - <span style="display: none">{{ field }}</span>  
7 - <a-upload-dragger  
8 - v-model:fileList="fileList"  
9 - name="file"  
10 - :multiple="true"  
11 - action="https://www.mocky.io/v2/5cc8019d300000980a055e76"  
12 - @change="handleChange"  
13 - >  
14 - <p class="ant-upload-drag-icon">  
15 - <InboxOutlined />  
16 - </p>  
17 - <p class="ant-upload-text">Click or drag file to this area to upload</p>  
18 - <p class="ant-upload-hint">  
19 - Support for a single or bulk upload. Strictly prohibit from uploading company data or  
20 - other band files  
21 - </p>  
22 - </a-upload-dragger>  
23 - </template>  
24 - <template #uploadAdd2="{ field }">  
25 - <span style="display: none">{{ field }}</span>  
26 - <a-upload-dragger  
27 - v-model:fileList="fileList"  
28 - name="file"  
29 - :multiple="true"  
30 - action="https://www.mocky.io/v2/5cc8019d300000980a055e76"  
31 - @change="handleChange"  
32 - >  
33 - <p class="ant-upload-drag-icon">  
34 - <InboxOutlined />  
35 - </p>  
36 - <p class="ant-upload-text">Click or drag file to this area to upload</p>  
37 - <p class="ant-upload-hint">  
38 - Support for a single or bulk upload. Strictly prohibit from uploading company data or  
39 - other band files  
40 - </p>  
41 - </a-upload-dragger>  
42 - </template>  
43 - <template #uploadAdd3="{ field }">  
44 - <span style="display: none">{{ field }}</span>  
45 - <a-upload-dragger  
46 - v-model:fileList="fileList"  
47 - name="file"  
48 - :multiple="true"  
49 - action="https://www.mocky.io/v2/5cc8019d300000980a055e76"  
50 - @change="handleChange"  
51 - >  
52 - <p class="ant-upload-drag-icon">  
53 - <InboxOutlined />  
54 - </p>  
55 - <p class="ant-upload-text">Click or drag file to this area to upload</p>  
56 - <p class="ant-upload-hint">  
57 - Support for a single or bulk upload. Strictly prohibit from uploading company data or  
58 - other band files  
59 - </p>  
60 - </a-upload-dragger>  
61 - </template>  
62 - </BasicForm>  
63 - </div>  
64 - </div>  
65 -</template>  
66 -<script lang="ts">  
67 - import { defineComponent, ref, reactive } from 'vue';  
68 - import { BasicForm, useForm } from '/@/components/Form';  
69 - import { modeMqttForm } from '../config';  
70 - import { InboxOutlined } from '@ant-design/icons-vue';  
71 - import { Alert, Divider, Descriptions, Upload } from 'ant-design-vue';  
72 -  
73 - export default defineComponent({  
74 - components: {  
75 - BasicForm,  
76 - [Alert.name]: Alert,  
77 - [Divider.name]: Divider,  
78 - [Descriptions.name]: Descriptions,  
79 - [Descriptions.Item.name]: Descriptions.Item,  
80 - InboxOutlined,  
81 - [Upload.Dragger.name]: Upload.Dragger,  
82 - },  
83 - emits: ['next', 'prev', 'register'],  
84 - setup(_, { emit }) {  
85 - const fileList = ref<[]>([]);  
86 - const credentialsV = reactive({  
87 - credentials: {  
88 - type: '',  
89 - },  
90 - });  
91 - const sonValues = reactive({  
92 - configuration: {},  
93 - });  
94 - const [register, { validate, setFieldsValue, resetFields: defineClearFunc }] = useForm({  
95 - labelWidth: 80,  
96 - schemas: modeMqttForm,  
97 - actionColOptions: {  
98 - span: 14,  
99 - },  
100 - resetButtonOptions: {  
101 - text: '上一步',  
102 - },  
103 -  
104 - resetFunc: customResetFunc,  
105 - submitFunc: customSubmitFunc,  
106 - });  
107 - const setStepTwoFieldsValueFunc = (v, v1) => {  
108 - setFieldsValue(v);  
109 - setFieldsValue({  
110 - name: v1,  
111 - });  
112 - };  
113 - const customClearStepTwoValueFunc = async () => {  
114 - defineClearFunc();  
115 - };  
116 - async function customResetFunc() {  
117 - emit('prev');  
118 - }  
119 - async function customSubmitFunc() {  
120 - try {  
121 - const values = await validate();  
122 - emit('next', values);  
123 - } catch (error) {  
124 - } finally {  
125 - }  
126 - }  
127 - const handleChange = () => {};  
128 - const getSonValueFunc = async () => {  
129 - sonValues.configuration = await validate();  
130 - credentialsV.credentials.type = sonValues.configuration.type;  
131 - Object.assign(sonValues.configuration, credentialsV);  
132 - return sonValues;  
133 - };  
134 - return {  
135 - getSonValueFunc,  
136 - register,  
137 - setStepTwoFieldsValueFunc,  
138 - customClearStepTwoValueFunc,  
139 - fileList,  
140 - handleChange,  
141 - };  
142 - },  
143 - });  
144 -</script>  
145 -<style lang="less" scoped>  
146 - .root {  
147 - width: 47.55vw;  
148 - min-height: 50vh;  
149 - border: 1px solid #bfbfbf;  
150 - display: flex;  
151 - margin-top: 1vh;  
152 - margin-left: 1.5vw;  
153 - border-radius: 8px;  
154 - .root-form {  
155 - width: 45vw;  
156 - margin: 1vh 1vw;  
157 - position: relative;  
158 - :deep .ant-input-number {  
159 - width: 18.35vw !important;  
160 - }  
161 - :deep .ant-btn {  
162 - position: absolute;  
163 - right: 1vw;  
164 - background-color: #0960bd;  
165 - border-radius: 2px;  
166 - span {  
167 - color: white;  
168 - }  
169 - }  
170 - }  
171 - }  
172 -</style>  
1 -<template>  
2 - <div class="root">  
3 - <div class="root-form">  
4 - <BasicForm :showSubmitButton="false" @register="register">  
5 - <template #addKeyAndValue="{ field }">  
6 - <span style="display: none">{{ field }}</span>  
7 - <div>  
8 - <div>  
9 - <template v-for="(item, index) in keyAndValueArr" :key="index">  
10 - <span style="display: none">{{ item + index }}</span>  
11 - <BasicForm  
12 - :showResetButton="false"  
13 - :showSubmitButton="false"  
14 - @register="registerKeyAndValue"  
15 - />  
16 - </template>  
17 - <div  
18 - style="  
19 - width: 7vw;  
20 - height: 3.3vh;  
21 - display: flex;  
22 - flex-direction: row;  
23 - justify-content: center;  
24 - align-items: center;  
25 - margin-left: 1.8vw;  
26 - "  
27 - >  
28 - <div  
29 - style="  
30 - width: 2.9vw;  
31 - height: 3.3vh;  
32 - background-color: #0960bd;  
33 - border-radius: 1px;  
34 - cursor: pointer;  
35 - text-align: center;  
36 - line-height: 3.1vh;  
37 - "  
38 - >  
39 - <span @click="addKeyAndValueFunc" style="color: white">添加</span>  
40 - </div>  
41 - <div  
42 - style="  
43 - width: 2.9vw;  
44 - height: 3.3vh;  
45 - margin-left: 1vw;  
46 - background-color: #ed6f6f;  
47 - border-radius: 1px;  
48 - cursor: pointer;  
49 - text-align: center;  
50 - line-height: 3.1vh;  
51 - "  
52 - >  
53 - <span @click="removeKeyAndValueFunc" style="color: white">删除</span>  
54 - </div>  
55 - </div>  
56 - <div> </div>  
57 - </div>  
58 - </div>  
59 - </template>  
60 - </BasicForm>  
61 - </div>  
62 - </div>  
63 -</template>  
64 -<script lang="ts">  
65 - import { defineComponent, ref, reactive } from 'vue';  
66 - import { BasicForm, useForm } from '/@/components/Form';  
67 - import { modeRabbitMqForm, modeKafkaInseretKeyAndValueForm } from '../config';  
68 - import { Alert, Divider, Descriptions } from 'ant-design-vue';  
69 -  
70 - interface IKeyAndValue {  
71 - key: string;  
72 - value: string;  
73 - }  
74 - export default defineComponent({  
75 - components: {  
76 - BasicForm,  
77 - [Alert.name]: Alert,  
78 - [Divider.name]: Divider,  
79 - [Descriptions.name]: Descriptions,  
80 - [Descriptions.Item.name]: Descriptions.Item,  
81 - },  
82 - emits: ['next', 'prev', 'register'],  
83 - setup(_, { emit }) {  
84 - const temp = ref({});  
85 - let tempObj = ref({});  
86 - const otherPropertiesValues = reactive({  
87 - clientProperties: {},  
88 - });  
89 -  
90 - const keyAndValueArrTemp = ref<[]>([]);  
91 - const keyAndValueObj = reactive<IKeyAndValue>({  
92 - key: '',  
93 - value: '',  
94 - });  
95 - const keyAndValueArr = ref<[]>([]);  
96 - const sonValues = reactive({  
97 - configuration: {},  
98 - });  
99 -  
100 - const [register, { validate, setFieldsValue, resetFields: defineClearFunc }] = useForm({  
101 - labelWidth: 80,  
102 - schemas: modeRabbitMqForm,  
103 - actionColOptions: {  
104 - span: 14,  
105 - },  
106 - resetButtonOptions: {  
107 - text: '上一步',  
108 - },  
109 -  
110 - resetFunc: customResetFunc,  
111 - submitFunc: customSubmitFunc,  
112 - });  
113 -  
114 - const [registerKeyAndValue, { validate: validateKeyAndValue }] = useForm({  
115 - labelWidth: 80,  
116 - schemas: modeKafkaInseretKeyAndValueForm,  
117 - actionColOptions: {  
118 - span: 14,  
119 - },  
120 - });  
121 -  
122 - const setStepTwoFieldsValueFunc = (v, v1) => {  
123 - setFieldsValue(v);  
124 - setFieldsValue({  
125 - name: v1,  
126 - });  
127 - };  
128 - const customClearStepTwoValueFunc = async () => {  
129 - defineClearFunc();  
130 - };  
131 - async function customResetFunc() {  
132 - emit('prev');  
133 - }  
134 - async function customSubmitFunc() {  
135 - try {  
136 - const values = await validate();  
137 - emit('next', values);  
138 - } catch (error) {  
139 - } finally {  
140 - }  
141 - }  
142 - const tempGetKeyAndVal = async () => {  
143 - temp.value = await validateKeyAndValue();  
144 - };  
145 - // const defaultAddKeyAndValueFunc = () => {  
146 - // if (keyAndValueArr.value.length == 0) {  
147 - // keyAndValueArr.value.push(keyAndValueObj as never);  
148 - // }  
149 - // };  
150 - // defaultAddKeyAndValueFunc();  
151 -  
152 - const getDefaultValue = async () => {  
153 - await tempGetKeyAndVal();  
154 - keyAndValueArrTemp.value.push(temp.value as never);  
155 - };  
156 -  
157 - const addKeyAndValueFunc = async () => {  
158 - keyAndValueArr.value.push(keyAndValueObj as never);  
159 - await tempGetKeyAndVal();  
160 - tempObj.value = temp.value;  
161 - keyAndValueArrTemp.value.push(tempObj.value as never);  
162 - };  
163 - const removeKeyAndValueFunc = () => {  
164 - keyAndValueArr.value.splice(0, 1);  
165 - };  
166 - const getSonValueFunc = async () => {  
167 - sonValues.configuration = await validate();  
168 - if (keyAndValueArrTemp.value.length != 0) {  
169 - await getDefaultValue();  
170 - }  
171 - const kong = {};  
172 - let kongTemp = {};  
173 - keyAndValueArrTemp.value.map((item) => {  
174 - kong[item.key] = item.value;  
175 - });  
176 - kongTemp = JSON.parse(JSON.stringify(kong));  
177 - otherPropertiesValues.clientProperties = kongTemp;  
178 - Object.assign(sonValues.configuration, otherPropertiesValues);  
179 - return sonValues;  
180 - };  
181 -  
182 - return {  
183 - getSonValueFunc,  
184 - register,  
185 - setStepTwoFieldsValueFunc,  
186 - customClearStepTwoValueFunc,  
187 - keyAndValueArr,  
188 - registerKeyAndValue,  
189 - addKeyAndValueFunc,  
190 - removeKeyAndValueFunc,  
191 - };  
192 - },  
193 - });  
194 -</script>  
195 -<style lang="less" scoped>  
196 - .root {  
197 - width: 47.55vw;  
198 - border: 1px solid #d9d9d9;  
199 - display: flex;  
200 - margin-top: 1vh;  
201 - margin-left: 1.5vw;  
202 - border-radius: 8px;  
203 -  
204 - .root-form {  
205 - width: 44vw;  
206 - margin: 1vh 1vw;  
207 - position: relative;  
208 - :deep .ant-input-number {  
209 - width: 17.85vw !important;  
210 - }  
211 - :deep .ant-btn {  
212 - position: absolute;  
213 - right: 1vw;  
214 - background-color: #0960bd;  
215 - border-radius: 2px;  
216 - span {  
217 - color: white;  
218 - }  
219 - }  
220 - }  
221 - }  
222 -</style>  
1 -<template>  
2 - <div class="root">  
3 - <div class="root-form">  
4 - <div>  
5 - <BasicForm @register="register" />  
6 - </div>  
7 - </div>  
8 - </div>  
9 -</template>  
10 -<script lang="ts">  
11 - import { defineComponent, ref } from 'vue';  
12 - import { BasicForm, useForm } from '/@/components/Form';  
13 - import { modeForm } from './config';  
14 - import { Select, Input, Divider } from 'ant-design-vue';  
15 -  
16 - export default defineComponent({  
17 - components: {  
18 - BasicForm,  
19 - [Select.name]: Select,  
20 - [Input.name]: Input,  
21 - [Input.Group.name]: Input.Group,  
22 - [Divider.name]: Divider,  
23 - },  
24 - emits: ['next', 'resetFunc', 'register'],  
25 - setup(_, { emit }) {  
26 - const sonValues = ref({});  
27 - const [register, { validateFields, setFieldsValue, resetFields }] = useForm({  
28 - labelWidth: 100,  
29 - schemas: modeForm,  
30 - actionColOptions: {  
31 - span: 14,  
32 - },  
33 - showResetButton: false,  
34 - submitButtonOptions: {  
35 - text: '下一步',  
36 - },  
37 - submitFunc: customSubmitFunc,  
38 - });  
39 - //提交数据  
40 - async function customSubmitFunc() {  
41 - try {  
42 - const values = await validateFields();  
43 - emit('next', values);  
44 - } catch (error) {}  
45 - }  
46 - //回显数据  
47 - const setStepOneFieldsValueFunc = (v) => {  
48 - setFieldsValue(v);  
49 - };  
50 -  
51 - //清空数据  
52 - const customResetStepOneFunc = () => {  
53 - resetFields();  
54 - };  
55 - const getSonValueFunc = async () => {  
56 - sonValues.value = await validateFields();  
57 - return sonValues.value;  
58 - };  
59 - return {  
60 - getSonValueFunc,  
61 - register,  
62 - setStepOneFieldsValueFunc,  
63 - customResetStepOneFunc,  
64 - };  
65 - },  
66 - });  
67 -</script>  
68 -<style lang="less" scoped>  
69 - .root {  
70 - width: 100vw;  
71 - height: 30vh;  
72 - .root-form {  
73 - width: 40vw;  
74 - position: relative;  
75 - left: 14vw;  
76 - top: 8vh;  
77 - :deep .ant-btn {  
78 - position: absolute;  
79 - right: 8.6vw;  
80 - top: 6vh;  
81 - background-color: #0960bd;  
82 - border-radius: 2px;  
83 - span {  
84 - color: white;  
85 - }  
86 - }  
87 - }  
88 - }  
89 -</style>  
1 -<template>  
2 - <div class="step2">  
3 - <div>  
4 - <div v-show="isWhereComp == 'org.thingsboard.rule.engine.kafka.TbKafkaNode'">  
5 - <TransferConfigKafka ref="refTransferConfigKafka" @prev="getSonPrev" />  
6 - </div>  
7 - <div v-show="isWhereComp == 'org.thingsboard.rule.engine.mqtt.TbMqttNode'">  
8 - <TransferConfigMqtt ref="refTransferConfigMqtt" @prev="getSonPrev" />  
9 - </div>  
10 - <div v-show="isWhereComp == 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode'">  
11 - <TransferConfigRabbitMq ref="refTransferConfigRabbitMq" @prev="getSonPrev" />  
12 - </div>  
13 - <div v-show="isWhereComp == 'org.thingsboard.rule.engine.rest.TbRestApiCallNode'">  
14 - <TransferConfigApi ref="refTransferConfigApi" @prev="getSonPrev" />  
15 - </div>  
16 - </div>  
17 - </div>  
18 -</template>  
19 -<script lang="ts">  
20 - import { defineComponent, watch, ref, getCurrentInstance } from 'vue';  
21 - import TransferConfigKafka from '../cpns/cpns/transferConfigKafka.vue';  
22 - import TransferConfigMqtt from '../cpns/cpns/transferConfigMqtt.vue';  
23 - import TransferConfigRabbitMq from '../cpns/cpns/transferConfigRabbitMq.vue';  
24 - import TransferConfigApi from '../cpns/cpns/transferConfigApi.vue';  
25 - import { Alert, Divider, Descriptions } from 'ant-design-vue';  
26 -  
27 - export default defineComponent({  
28 - components: {  
29 - [Alert.name]: Alert,  
30 - [Divider.name]: Divider,  
31 - [Descriptions.name]: Descriptions,  
32 - [Descriptions.Item.name]: Descriptions.Item,  
33 - TransferConfigKafka,  
34 - TransferConfigMqtt,  
35 - TransferConfigRabbitMq,  
36 - TransferConfigApi,  
37 - },  
38 - // eslint-disable-next-line vue/require-prop-types  
39 - props: ['getModeSelect', 'defineClearFuncProp'],  
40 - emits: ['prevSon'],  
41 - setup(props, { emit }) {  
42 - const { proxy } = getCurrentInstance();  
43 - const getTransferConfigKafkaValue = ref({});  
44 - const refTransferConfigKafka = ref(null);  
45 - const refTransferConfigMqtt = ref(null);  
46 - const refTransferConfigRabbitMq = ref(null);  
47 - const refTransferConfigApi = ref(null);  
48 - const isWhereComp = ref('');  
49 -  
50 - const getSonPrev = () => {  
51 - emit('prevSon');  
52 - };  
53 - watch(  
54 - () => props.getModeSelect,  
55 - (val) => {  
56 - isWhereComp.value = val.type;  
57 - }  
58 - );  
59 - const clearSonValueDataFunc = () => {  
60 - try {  
61 - proxy.$refs.refTransferConfigKafka?.customClearStepTwoValueFunc();  
62 - proxy.$refs.refTransferConfigMqtt?.customClearStepTwoValueFunc();  
63 - proxy.$refs.refTransferConfigRabbitMq?.customClearStepTwoValueFunc();  
64 - proxy.$refs.refTransferConfigApi?.customClearStepTwoValueFunc();  
65 - } catch (e) {  
66 - return e;  
67 - }  
68 - };  
69 - const clearSonValueValidateFunc = () => {  
70 - try {  
71 - proxy.$refs.refTransferConfigKafka?.clearValidateFunc();  
72 - // proxy.$refs.refTransferConfigMqtt?.customClearStepTwoValueFunc();  
73 - // proxy.$refs.refTransferConfigRabbitMq?.customClearStepTwoValueFunc();  
74 - // proxy.$refs.refTransferConfigApi?.customClearStepTwoValueFunc();  
75 - } catch (e) {  
76 - return e;  
77 - }  
78 - };  
79 - const getSonValueDataFunc = () => {  
80 - if (isWhereComp.value == 'org.thingsboard.rule.engine.kafka.TbKafkaNode') {  
81 - getTransferConfigKafkaValue.value = proxy.$refs.refTransferConfigKafka.getSonValueFunc();  
82 - } else if (isWhereComp.value == 'org.thingsboard.rule.engine.mqtt.TbMqttNode') {  
83 - getTransferConfigKafkaValue.value = proxy.$refs.refTransferConfigMqtt.getSonValueFunc();  
84 - } else if (isWhereComp.value == 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode') {  
85 - getTransferConfigKafkaValue.value =  
86 - proxy.$refs.refTransferConfigRabbitMq.getSonValueFunc();  
87 - } else if (isWhereComp.value == 'org.thingsboard.rule.engine.rest.TbRestApiCallNode') {  
88 - getTransferConfigKafkaValue.value = proxy.$refs.refTransferConfigApi.getSonValueFunc();  
89 - }  
90 - return getTransferConfigKafkaValue.value;  
91 - };  
92 - const editSonValueDataFunc = (v) => {  
93 - try {  
94 - if (v.type == 'org.thingsboard.rule.engine.kafka.TbKafkaNode') {  
95 - isWhereComp.value = v.type;  
96 - proxy.$refs.refTransferConfigKafka.setStepTwoFieldsValueFunc(v.configuration, v.name);  
97 - } else if (v.type == 'org.thingsboard.rule.engine.mqtt.TbMqttNode') {  
98 - isWhereComp.value = v.type;  
99 - proxy.$refs.refTransferConfigMqtt.setStepTwoFieldsValueFunc(v.configuration, v.name);  
100 - } else if (v.type == 'org.thingsboard.rule.engine.rabbitmq.TbRabbitMqNode') {  
101 - isWhereComp.value = v.type;  
102 - proxy.$refs.refTransferConfigRabbitMq.setStepTwoFieldsValueFunc(  
103 - v.configuration,  
104 - v.name  
105 - );  
106 - } else if (v.type == 'org.thingsboard.rule.engine.rest.TbRestApiCallNode') {  
107 - isWhereComp.value = v.type;  
108 - proxy.$refs.refTransferConfigApi.setStepTwoFieldsValueFunc(v.configuration, v.name);  
109 - }  
110 - } catch (e) {  
111 - return e;  
112 - }  
113 - };  
114 - return {  
115 - clearSonValueValidateFunc,  
116 - clearSonValueDataFunc,  
117 - editSonValueDataFunc,  
118 - refTransferConfigKafka,  
119 - getSonValueDataFunc,  
120 - getSonPrev,  
121 - isWhereComp,  
122 - refTransferConfigMqtt,  
123 - refTransferConfigRabbitMq,  
124 - refTransferConfigApi,  
125 - };  
126 - },  
127 - });  
128 -</script>  
129 -<style lang="less" scoped></style>  
1 -<template>  
2 - <div>  
3 - <BasicTable  
4 - @selection-change="useSelectionChange"  
5 - @register="registerTable"  
6 - :loading="loading"  
7 - :rowSelection="{ type: 'checkbox' }"  
8 - >  
9 - <template #toolbar>  
10 - <a-button type="primary" @click="handleAdd"> 添加转换 </a-button>  
11 - <a-button  
12 - :disabled="disabledStatus1"  
13 - @click="handleDelete"  
14 - :type="disabledStatus1 ? 'default' : 'primary'"  
15 - >  
16 - <span :style="{ color: disabledStatus1 ? 'grey' : 'white' }">批量删除</span>  
17 - </a-button>  
18 - <a-button  
19 - :disabled="disabledStatus2"  
20 - @click="handleMutiuteDisable"  
21 - :type="disabledStatus2 ? 'default' : 'primary'"  
22 - >  
23 - <span :style="{ color: disabledStatus2 ? 'grey' : 'white' }">批量禁用</span>  
24 - </a-button>  
25 - <a-button  
26 - :disabled="disabledStatus3"  
27 - @click="handleMutiuteEnable"  
28 - :type="disabledStatus3 ? 'default' : 'primary'"  
29 - >  
30 - <span :style="{ color: disabledStatus3 ? 'grey' : 'white' }">批量启用</span>  
31 - </a-button>  
32 - </template>  
33 - <template #action="{ record }">  
34 - <TableAction  
35 - :actions="[  
36 - {  
37 - label: '编辑',  
38 - icon: 'clarity:note-edit-line',  
39 - onClick: handleEdit.bind(null, record),  
40 - ifShow: (_action) => {  
41 - return record.status == 0;  
42 - },  
43 - },  
44 -  
45 - {  
46 - label: '删除',  
47 - icon: 'ant-design:delete-outlined',  
48 - color: 'error',  
49 - popConfirm: {  
50 - title: '是否确认删除',  
51 - confirm: handleSingleDelete.bind(null, record),  
52 - },  
53 - ifShow: (_action) => {  
54 - return record.status == 0;  
55 - },  
56 - },  
57 - {  
58 - label: '启用',  
59 - icon: 'ant-design:check-circle-outlined',  
60 - color: 'success',  
61 - popConfirm: {  
62 - title: '是否启用?',  
63 - confirm: handleEnableOrDisable.bind(null, record),  
64 - },  
65 - ifShow: (_action) => {  
66 - return record.status == 0;  
67 - },  
68 - },  
69 - {  
70 - label: '禁用',  
71 - icon: 'ant-design:close-circle-outlined',  
72 - popConfirm: {  
73 - title: '是否禁用?',  
74 - confirm: handleDisable.bind(null, record),  
75 - },  
76 - ifShow: (_action) => {  
77 - return record.status == 1;  
78 - },  
79 - },  
80 - ]"  
81 - />  
82 - </template>  
83 - </BasicTable>  
84 - <div>  
85 - <DataTransferDrawer @register="registerModal" @success="handleSuccess" />  
86 - </div>  
87 - </div>  
88 -</template>  
89 -<script lang="ts">  
90 - import { defineComponent, reactive, ref } from 'vue';  
91 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
92 - import { columns, searchFormSchema } from './config';  
93 - import { useModal } from '/@/components/Modal';  
94 - import DataTransferDrawer from './addDataTransferDrawer.vue';  
95 - import {  
96 - getConvertApi,  
97 - isEnableOrDisableApi,  
98 - deleteConvertApi,  
99 - } from '/@/api/datamanager/dataManagerApi';  
100 - import { useMessage } from '/@/hooks/web/useMessage';  
101 -  
102 - export default defineComponent({  
103 - name: 'Index',  
104 - components: { BasicTable, TableAction, DataTransferDrawer },  
105 - setup() {  
106 - const enableObj = reactive({  
107 - convertIds: [],  
108 - status: 0,  
109 - });  
110 - const disabledStatus1 = ref(true);  
111 - const disabledStatus2 = ref(true);  
112 - const disabledStatus3 = ref(true);  
113 - const loading = ref(true);  
114 - const { createMessage } = useMessage();  
115 - let selectedRowKeys: any = ref([]);  
116 - let getSelectRowsArr: any = ref([]);  
117 - let isJudgeSelectRowsArr: any = ref([]);  
118 - const [registerModal, { openModal }] = useModal();  
119 - const [  
120 - registerTable,  
121 - { reload, getSelectRowKeys, getSelectRows, setLoading, clearSelectedRowKeys },  
122 - ] = useTable({  
123 - title: '数据转换列表',  
124 - clickToRowSelect: false,  
125 - columns,  
126 - api: getConvertApi,  
127 - formConfig: {  
128 - labelWidth: 120,  
129 - schemas: searchFormSchema,  
130 - },  
131 - rowKey: 'id',  
132 - useSearchForm: true,  
133 - showTableSetting: true,  
134 - bordered: true,  
135 - showIndexColumn: false,  
136 - actionColumn: {  
137 - width: 180,  
138 - title: '操作',  
139 - dataIndex: 'action',  
140 - slots: { customRender: 'action' },  
141 - fixed: 'right',  
142 - },  
143 - });  
144 -  
145 - //新增  
146 - const handleAdd = () => {  
147 - setTimeout(() => {  
148 - openModal(true, {  
149 - isUpdate: false,  
150 - });  
151 - }, 10);  
152 - };  
153 -  
154 - const handleSuccess = () => {  
155 - reload();  
156 - };  
157 - const handleEdit = (record: Recordable) => {  
158 - setTimeout(() => {  
159 - openModal(true, {  
160 - record,  
161 - isUpdate: true,  
162 - });  
163 - }, 10);  
164 - };  
165 -  
166 - const handleEnableOrDisable = async (record: Recordable) => {  
167 - setLoading(true);  
168 - enableObj.convertIds.length = 0;  
169 - try {  
170 - enableObj.status = record.status;  
171 - enableObj.convertIds.push(record.id as never);  
172 - if (enableObj.status == 0) {  
173 - enableObj.status = 1;  
174 - }  
175 - const res = await isEnableOrDisableApi(enableObj as never);  
176 - if (res !== '') {  
177 - createMessage.success('转换配置启用成功');  
178 - setLoading(false);  
179 - reload();  
180 - } else {  
181 - createMessage.error('转换配置启用失败');  
182 - }  
183 - } catch (e) {  
184 - return e;  
185 - } finally {  
186 - setLoading(false);  
187 - }  
188 - };  
189 - const handleDisable = async (record: Recordable) => {  
190 - setLoading(true);  
191 - enableObj.convertIds.length = 0;  
192 - try {  
193 - enableObj.status = record.status;  
194 - enableObj.convertIds.push(record.id as never);  
195 - if (enableObj.status == 1) {  
196 - enableObj.status = 0;  
197 - }  
198 - const res = await isEnableOrDisableApi(enableObj as never);  
199 - if (res !== '') {  
200 - createMessage.success('转换配置禁用成功');  
201 - setLoading(false);  
202 - reload();  
203 - } else {  
204 - createMessage.error('转换配置禁用失败');  
205 - }  
206 - } catch (e) {  
207 - } finally {  
208 - setLoading(false);  
209 - }  
210 - };  
211 - const handleSingleDelete = async (record: Recordable) => {  
212 - try {  
213 - let ids = [record.id];  
214 - await deleteConvertApi(ids);  
215 - createMessage.success('删除成功');  
216 - reload();  
217 - } catch (e) {  
218 - return e;  
219 - }  
220 - };  
221 - const useSelectionChange = () => {  
222 - selectedRowKeys.value = getSelectRowKeys();  
223 - isJudgeSelectRowsArr.value = getSelectRows();  
224 - const hasDisableStatus = isJudgeSelectRowsArr.value.map((m) => {  
225 - return m.status;  
226 - });  
227 - if (hasDisableStatus.length == 0) {  
228 - disabledStatus1.value = true;  
229 - disabledStatus2.value = true;  
230 - disabledStatus3.value = true;  
231 - }  
232 - hasDisableStatus.every((e) => {  
233 - if (e == 1) {  
234 - disabledStatus3.value = true;  
235 - disabledStatus2.value = false;  
236 - } else if (e == 0) {  
237 - disabledStatus2.value = true;  
238 - disabledStatus3.value = false;  
239 - }  
240 - });  
241 - let i1 = hasDisableStatus.indexOf(0);  
242 - let i2 = hasDisableStatus.indexOf(1);  
243 - if (i1 !== -1 && i2 !== -1) {  
244 - disabledStatus2.value = true;  
245 - disabledStatus3.value = true;  
246 - }  
247 - if (isJudgeSelectRowsArr.value.length == 0) {  
248 - disabledStatus1.value = true;  
249 - } else {  
250 - disabledStatus1.value = false;  
251 - }  
252 - };  
253 -  
254 - const handleDelete = async () => {  
255 - try {  
256 - setLoading(true);  
257 - const data = await deleteConvertApi(selectedRowKeys.value);  
258 - if (data == true) {  
259 - createMessage.success('删除成功');  
260 - setLoading(false);  
261 - reload();  
262 - } else {  
263 - createMessage.error('删除失败');  
264 - }  
265 - } catch (e) {  
266 - return e;  
267 - } finally {  
268 - setLoading(false);  
269 - clearSelectedRowKeys();  
270 - }  
271 - };  
272 - const handleMutiuteDisable = async () => {  
273 - enableObj.convertIds.length = 0;  
274 - try {  
275 - setLoading(true);  
276 - getSelectRowsArr.value = getSelectRows();  
277 - getSelectRowsArr.value.forEach((f) => {  
278 - if (f.id) {  
279 - enableObj.status = 0;  
280 - enableObj.convertIds.push(f.id as never);  
281 - }  
282 - });  
283 - const res = await isEnableOrDisableApi(enableObj as never);  
284 - if (res !== '') {  
285 - createMessage.success('转换配置多项禁用成功');  
286 - setLoading(false);  
287 - reload();  
288 - } else {  
289 - createMessage.error('转换配置多项禁用失败');  
290 - }  
291 - } catch (e) {  
292 - return e;  
293 - } finally {  
294 - setLoading(false);  
295 - clearSelectedRowKeys();  
296 - }  
297 - };  
298 -  
299 - const handleMutiuteEnable = async () => {  
300 - enableObj.convertIds.length = 0;  
301 - try {  
302 - setLoading(true);  
303 - getSelectRowsArr.value = getSelectRows();  
304 - getSelectRowsArr.value.forEach((f) => {  
305 - if (f.id) {  
306 - enableObj.status = 1;  
307 - enableObj.convertIds.push(f.id as never);  
308 - }  
309 - });  
310 - const res = await isEnableOrDisableApi(enableObj as never);  
311 - if (res !== '') {  
312 - createMessage.success('转换配置多项启用成功');  
313 - setLoading(false);  
314 - reload();  
315 - } else {  
316 - createMessage.error('转换配置多项启用失败');  
317 - }  
318 - } catch (e) {  
319 - return e;  
320 - } finally {  
321 - setLoading(false);  
322 - clearSelectedRowKeys();  
323 - }  
324 - };  
325 -  
326 - return {  
327 - disabledStatus1,  
328 - disabledStatus2,  
329 - disabledStatus3,  
330 - handleMutiuteEnable,  
331 - loading,  
332 - registerTable,  
333 - handleAdd,  
334 - handleDelete,  
335 - registerModal,  
336 - handleSuccess,  
337 - handleEdit,  
338 - handleEnableOrDisable,  
339 - handleSingleDelete,  
340 - useSelectionChange,  
341 - handleMutiuteDisable,  
342 - handleDisable,  
343 - };  
344 - },  
345 - });  
346 -</script>  
347 -  
348 -<style lang="less" scoped></style>  
1 -import { BasicColumn, FormSchema } from '/@/components/Table';  
2 -import { h } from 'vue';  
3 -import { Tag, Switch } from 'ant-design-vue';  
4 -import { useMessage } from '/@/hooks/web/useMessage';  
5 -import { updateTransformScriptStatusApi } from '/@/api/device/TransformScriptApi';  
6 -export const columns: BasicColumn[] = [  
7 - {  
8 - title: '名称',  
9 - dataIndex: 'name',  
10 - width: 100,  
11 - },  
12 - {  
13 - title: '用途',  
14 - dataIndex: 'type',  
15 - width: 200,  
16 - customRender: () => h(Tag, { color: 'blue' }, () => '消息格式化'),  
17 - },  
18 - {  
19 - title: '状态',  
20 - dataIndex: 'status',  
21 - width: 120,  
22 - customRender: ({ record }) => {  
23 - if (!Reflect.has(record, 'pendingStatus')) {  
24 - record.pendingStatus = false;  
25 - }  
26 - return h(Switch, {  
27 - checked: record.status === 1,  
28 - checkedChildren: '已启用',  
29 - unCheckedChildren: '已禁用',  
30 - loading: record.pendingStatus,  
31 - onChange(checked: boolean) {  
32 - record.pendingStatus = true;  
33 - const newStatus = checked ? 1 : 0;  
34 - const { createMessage } = useMessage();  
35 - updateTransformScriptStatusApi(newStatus, record.id)  
36 - .then(() => {  
37 - record.status = newStatus;  
38 - createMessage.success(`${record.status ? '启用' : '禁用'}成功`);  
39 - })  
40 - .finally(() => {  
41 - record.pendingStatus = false;  
42 - });  
43 - },  
44 - });  
45 - },  
46 - },  
47 - {  
48 - title: '创建时间',  
49 - dataIndex: 'createTime',  
50 - width: 180,  
51 - },  
52 -];  
53 -  
54 -export const searchFormSchema: FormSchema[] = [  
55 - {  
56 - field: 'name',  
57 - label: '名称',  
58 - component: 'Input',  
59 - colProps: { span: 6 },  
60 - componentProps: {  
61 - maxLength: 36,  
62 - placeholder: '请输入名称',  
63 - },  
64 - },  
65 - {  
66 - field: 'status',  
67 - label: '状态',  
68 - component: 'Select',  
69 - componentProps: {  
70 - placeholder: '请选择状态',  
71 - options: [  
72 - { label: '已启用', value: '1' },  
73 - { label: '未启用', value: '0' },  
74 - ],  
75 - },  
76 - colProps: { span: 6 },  
77 - },  
78 -];  
79 -  
80 -export const formSchema: FormSchema[] = [  
81 - {  
82 - field: 'name',  
83 - label: '名称',  
84 - required: true,  
85 - component: 'Input',  
86 - componentProps: {  
87 - maxLength: 36,  
88 - placeholder: '请输入名称',  
89 - },  
90 - },  
91 - {  
92 - field: 'remark',  
93 - label: '说明',  
94 - component: 'InputTextArea',  
95 - componentProps: {  
96 - maxLength: 255,  
97 - autoSize: { minRows: 5, maxRows: 8 },  
98 - placeholder: '请输入说明',  
99 - },  
100 - },  
101 - {  
102 - field: 'function',  
103 - label: '',  
104 - component: 'Input',  
105 - slot: 'function',  
106 - },  
107 - {  
108 - field: 'id',  
109 - label: 'id',  
110 - component: 'Input',  
111 - ifShow: false,  
112 - },  
113 -];  
1 -<template>  
2 - <div>  
3 - <BasicDrawer  
4 - v-bind="$attrs"  
5 - :title="getTitle"  
6 - @register="register"  
7 - width="500px"  
8 - showFooter  
9 - @ok="handleSubmit"  
10 - >  
11 - <BasicForm @register="registerForm">  
12 - <template #function>  
13 - <Card title="转换函数" :bodyStyle="{ padding: 0, height: '280px' }">  
14 - <template #extra>  
15 - <Tag color="blue">Transform Function</Tag>  
16 - <a-button @click="handleFormat" size="small">格式化</a-button>  
17 - </template>  
18 - <div class="ml-8">function Transform(msg, metadata) {</div>  
19 - <div ref="aceRef" class="overflow-hidden"></div>  
20 - <div class="ml-7">}</div>  
21 - </Card>  
22 - <a-button type="primary" class="mt-4" @click="testTransformFunc">测试转换功能</a-button>  
23 - </template>  
24 - </BasicForm>  
25 - </BasicDrawer>  
26 - </div>  
27 -</template>  
28 -  
29 -<script lang="ts" setup>  
30 - import { ref, computed } from 'vue';  
31 - import { useDrawerInner, BasicDrawer } from '/@/components/Drawer/index';  
32 - import { useForm, BasicForm } from '/@/components/Form/index';  
33 - import { formSchema } from '../config/config.data.ts';  
34 - import { Card, Tag } from 'ant-design-vue';  
35 - import { createOrEditTransformScriptApi } from '/@/api/device/TransformScriptApi';  
36 - import { useMessage } from '/@/hooks/web/useMessage';  
37 - import ace from 'ace-builds';  
38 - import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题  
39 - import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式  
40 - import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js';  
41 -  
42 - const emit = defineEmits(['register', 'isStatus', 'success']);  
43 - const isUpdate = ref(false);  
44 - const aceEditor = ref();  
45 - const aceRef = ref();  
46 - const getTitle = computed(() => (isUpdate.value ? '编辑转换脚本' : '新增转换脚本'));  
47 - const [register, { closeDrawer }] = useDrawerInner((data) => {  
48 - resetFields();  
49 - isUpdate.value = data.isUpdate;  
50 - initEditor(data.record?.configuration.jsScript);  
51 - if (isUpdate.value) {  
52 - setFieldsValue(data.record);  
53 - }  
54 - });  
55 - const [registerForm, { getFieldsValue, setFieldsValue, resetFields }] = useForm({  
56 - showActionButtonGroup: false,  
57 - colProps: { span: 24 },  
58 - schemas: formSchema,  
59 - });  
60 -  
61 - // 初始化编辑器  
62 - const initEditor = (jsScript?: string) => {  
63 - aceEditor.value = ace.edit(aceRef.value, {  
64 - maxLines: 12, // 最大行数,超过会自动出现滚动条  
65 - minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小  
66 - fontSize: 14, // 编辑器内字体大小  
67 - theme: 'ace/theme/chrome', // 默认设置的主题  
68 - mode: 'ace/mode/javascript', // 默认设置的语言模式  
69 - tabSize: 2, // 制表符设置为 4 个空格大小  
70 - });  
71 -  
72 - aceEditor.value.setOptions({  
73 - enableBasicAutocompletion: true,  
74 - enableLiveAutocompletion: true,  
75 - });  
76 - aceEditor.value.setValue(jsScript ?? 'return {msg: msg, metadata: metadata};');  
77 - beautify(aceEditor.value.session);  
78 - };  
79 -  
80 - const testTransformFunc = () => {  
81 - closeDrawer();  
82 - const jsCode = aceEditor.value.getValue();  
83 - emit('isStatus', { status: 1, jsCode });  
84 - };  
85 - const handleSubmit = async () => {  
86 - const fieldsValue = getFieldsValue();  
87 - try {  
88 - await createOrEditTransformScriptApi({  
89 - configuration: {  
90 - jsScript: aceEditor.value.getValue(),  
91 - },  
92 - type: 'org.thingsboard.rule.engine.transform.TbTransformMsgNode',  
93 - ...fieldsValue,  
94 - });  
95 - closeDrawer();  
96 - emit('success');  
97 - const { createMessage } = useMessage();  
98 - createMessage.success('保存成功');  
99 - } catch (e) {  
100 - const { createMessage } = useMessage();  
101 - createMessage.success('保存失败');  
102 - }  
103 - };  
104 - const handleFormat = () => {  
105 - beautify(aceEditor.value.session);  
106 - };  
107 - defineExpose({ aceEditor });  
108 -</script>  
1 -<template>  
2 - <div>  
3 - <PageWrapper title="测试脚本功能" class="pl-4 pr-4 pt-4" :contentStyle="{ display: 'none' }" />  
4 - <div class="h-full flex p-4">  
5 - <div class="flex flex-col w-1/2">  
6 - <div class="flex-1 mr-4 mb-4">  
7 - <Card title="消息" :bodyStyle="cardStyle">  
8 - <template #extra>  
9 - <Tag color="blue">Message</Tag>  
10 - <a-button @click="handleFormatJson" size="small">格式化</a-button>  
11 - <a-button @click="handleMiniJson" size="small" class="ml-2">收起</a-button>  
12 - </template>  
13 - <div ref="jsoneditorRef" style="height: 100%"></div>  
14 - </Card>  
15 - </div>  
16 - <div class="flex-1 mr-4">  
17 - <Card title="转换函数" :bodyStyle="cardStyle">  
18 - <template #extra>  
19 - <Tag color="blue">Transform Function</Tag>  
20 - <a-button @click="handleFormatJScript" size="small">格式化</a-button>  
21 -  
22 - <Tooltip title="帮助文档" @click="openModal">  
23 - <QuestionCircleOutlined class="ml-2" style="font-size: 1rem" />  
24 - </Tooltip>  
25 - </template>  
26 - <div class="ml-8">function Transform(msg, metadata) {</div>  
27 - <div ref="aceRef" style="height: calc(100% - 44px)"></div>  
28 - <div class="ml-7">}</div>  
29 - </Card>  
30 - </div>  
31 - </div>  
32 - <div class="flex flex-col w-1/2">  
33 - <div class="flex-1 mb-4">  
34 - <Card title="元数据" :bodyStyle="cardStyle">  
35 - <template #extra>  
36 - <Tag color="blue">Meta Data</Tag>  
37 - </template>  
38 - <Description @register="registerDesc" />  
39 - </Card>  
40 - </div>  
41 - <div class="flex-1">  
42 - <Card title="输出" :bodyStyle="cardStyle">  
43 - <template #extra>  
44 - <Tag color="blue">Output</Tag>  
45 - <a-button @click="handleFormatOutPutJson" size="small">格式化</a-button>  
46 - <a-button @click="handleCompactJson" size="small" class="ml-2">收起</a-button>  
47 - </template>  
48 - <div class="ml-8 opacity-0">site</div>  
49 - <div ref="outputRef" style="height: calc(100% - 44px)"></div>  
50 - <div class="ml-7 opacity-0">site</div>  
51 - </Card>  
52 - </div>  
53 - </div>  
54 - </div>  
55 - <div class="flex justify-between pl-4 pr-4">  
56 - <div>  
57 - <a-button class="" type="primary" @click="handleTestFunc"> 测试</a-button>  
58 - </div>  
59 - <div>  
60 - <a-button class="ml-4" @click="handleCancel"> 取消</a-button>  
61 - <a-button class="ml-4" type="primary" @click="handleOk"> 保存</a-button>  
62 - </div>  
63 - </div>  
64 - <BasicModal  
65 - @register="registerModal"  
66 - title="转换消息功能"  
67 - :footer="null"  
68 - width="800px"  
69 - centered  
70 - v-bind="$attrs"  
71 - >  
72 - <h2> function Transform(msg,metadata): {msg: object, metadata: object} </h2>  
73 - <li> 将输入消息、元数据转换为输出消息的 JavaScript 函数 </li>  
74 - <h2>参数:</h2>  
75 - <ul>  
76 - <li>msg: {[key: string]: any} - 是消息有效负载键/值对象。</li>  
77 - <li>metadata: {[key: string]: string} - 是消息元数据键/值映射,其中键和值都是字符串。</li>  
78 - </ul>  
79 - <h2>返回值:</h2>  
80 - <ul>  
81 - <li> { msg?: {[key: string]: any}, metadata?: {[key: string]: string} } </li>  
82 - <li> 结果对象中的所有字段都是可选的,如果未指定,将从原始消息中获取。 </li>  
83 - </ul>  
84 - </BasicModal>  
85 - </div>  
86 -</template>  
87 -<script lang="ts" setup>  
88 - import { ref, onMounted, defineComponent } from 'vue';  
89 - import { Card, Tag, Tooltip } from 'ant-design-vue';  
90 - import { PageWrapper } from '/@/components/Page';  
91 - import { Description, DescItem, useDescription } from '/@/components/Description/index';  
92 - import { useMessage } from '/@/hooks/web/useMessage';  
93 - import { QuestionCircleOutlined } from '@ant-design/icons-vue';  
94 - import { BasicModal, useModal } from '/@/components/Modal/index';  
95 -  
96 - import jsoneditor from 'jsoneditor';  
97 - import 'jsoneditor/dist/jsoneditor.min.css';  
98 - import ace from 'ace-builds';  
99 - import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题  
100 - import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式  
101 - import 'ace-builds/src-noconflict/ext-language_tools.js'; //语言提示  
102 - import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; //格式化  
103 - // !!!important 重要,配置ace编辑器的错误提示,基础路径。否则会加载不到相关web Worker,就没有syntax validation提示  
104 - ace.config.set('basePath', 'https://cdn.jsdelivr.net/npm/ace-builds@1.4.14/src-noconflict/');  
105 - defineComponent({  
106 - Tooltip,  
107 - });  
108 -  
109 - const jsonValue = ref({  
110 - temperature: 22.4,  
111 - humidity: 78,  
112 - });  
113 - const cardStyle = { padding: 0, height: '280px' };  
114 -  
115 - // json 以及初始化JSON  
116 - const jsoneditorRef = ref();  
117 - const JsonEditor = ref();  
118 - const outputRef = ref();  
119 - const outputEditor = ref();  
120 - const aceEditor = ref();  
121 - const aceRef = ref();  
122 - const emit = defineEmits(['isStatus']);  
123 - function initEditor() {  
124 - let options = {  
125 - mode: 'code',  
126 - mainMenuBar: false,  
127 - statusBar: false,  
128 - onError: function (err) {  
129 - alert('EF1 ->' + err.toString());  
130 - },  
131 - };  
132 - let editor = new jsoneditor(jsoneditorRef.value, options);  
133 - editor.set(jsonValue.value);  
134 - JsonEditor.value = editor;  
135 - let outEditor = new jsoneditor(outputRef.value, options);  
136 - outEditor.set(true);  
137 - outputEditor.value = outEditor;  
138 -  
139 - aceEditor.value = ace.edit(aceRef.value, {  
140 - maxLines: 12, // 最大行数,超过会自动出现滚动条  
141 - minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小  
142 - fontSize: 14, // 编辑器内字体大小  
143 - theme: 'ace/theme/chrome', // 默认设置的主题  
144 - mode: 'ace/mode/javascript', // 默认设置的语言模式  
145 - tabSize: 2, // 制表符设置为 2 个空格大小  
146 - enableBasicAutocompletion: true, //补全  
147 - enableLiveAutocompletion: true, //  
148 - });  
149 - }  
150 - const mataData: any = {  
151 - deviceName: 'Test Device',  
152 - deviceType: 'default',  
153 - ts: Date.now(),  
154 - };  
155 - const schema: DescItem[] = [  
156 - {  
157 - field: 'deviceName',  
158 - label: 'deviceName',  
159 - },  
160 - {  
161 - field: 'deviceType',  
162 - label: 'deviceType',  
163 - },  
164 - {  
165 - field: 'ts',  
166 - label: 'ts',  
167 - },  
168 - ];  
169 - const [registerDesc] = useDescription({  
170 - column: 1,  
171 - data: mataData,  
172 - schema,  
173 - });  
174 - // 格式化json  
175 - const handleFormatJson = () => {  
176 - JsonEditor.value.repair();  
177 - JsonEditor.value.format();  
178 - };  
179 - // 迷你json  
180 - const handleMiniJson = () => {  
181 - JsonEditor.value.repair();  
182 - JsonEditor.value.compact();  
183 - };  
184 - // format json  
185 - const handleFormatOutPutJson = () => {  
186 - outputEditor.value.repair();  
187 - outputEditor.value.format();  
188 - };  
189 - // 迷你json  
190 - const handleCompactJson = () => {  
191 - outputEditor.value.repair();  
192 - outputEditor.value.compact();  
193 - };  
194 -  
195 - // 测试  
196 - const handleTestFunc = async () => {  
197 - // 收集3方数据  
198 - try {  
199 - const msg = JsonEditor.value.get();  
200 - const metadata = mataData;  
201 - const jsCode = aceEditor.value.getValue();  
202 - // 执行动态Javascript脚本  
203 - let result = Function('msg', 'metadata', jsCode)(msg, metadata);  
204 - // 设置输出值  
205 - outputEditor.value.set(result);  
206 - } catch (e) {  
207 - console.log(e);  
208 - const { createMessage } = useMessage();  
209 - createMessage.error(e.toString());  
210 - }  
211 - };  
212 - const [registerModal, { openModal }] = useModal();  
213 - const handleCancel = () => {  
214 - emit('isStatus', { status: 0, emitType: 'cancel' });  
215 - };  
216 - const handleOk = () => {  
217 - emit('isStatus', { status: 0, emitType: 'ok' });  
218 - };  
219 - const handleFormatJScript = () => {  
220 - beautify(aceEditor.value.session);  
221 - };  
222 - onMounted(() => {  
223 - initEditor();  
224 - });  
225 - defineExpose({ aceEditor });  
226 -</script>  
227 -  
228 -<style scope>  
229 - .jsoneditor {  
230 - border: none;  
231 - }  
232 -</style>  
1 -<template>  
2 - <div>  
3 - <BasicTable @register="registerTable" v-show="isStatus === 0">  
4 - <template #toolbar>  
5 - <a-button type="primary" @click="handleCreate"> 新增转换脚本 </a-button>  
6 - <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">  
7 - 批量删除  
8 - </a-button>  
9 - </template>  
10 - <template #action="{ record }">  
11 - <TableAction  
12 - :actions="[  
13 - {  
14 - label: '编辑',  
15 - icon: 'clarity:note-edit-line',  
16 -  
17 - onClick: handleEdit.bind(null, record),  
18 - },  
19 - {  
20 - label: '删除',  
21 - icon: 'ant-design:delete-outlined',  
22 - ifShow: record.status == 0,  
23 - color: 'error',  
24 - popConfirm: {  
25 - title: '是否确认删除',  
26 - confirm: handleDeleteOrBatchDelete.bind(null, record),  
27 - },  
28 - },  
29 - ]"  
30 - />  
31 - </template>  
32 - </BasicTable>  
33 - <ScriptDrawer  
34 - @register="registerDrawer"  
35 - @isStatus="handleIsStatus"  
36 - ref="scriptDrawerRef"  
37 - @success="handleSuccess"  
38 - />  
39 - <TestScript v-show="isStatus === 1" @isStatus="handleCancelStatus" ref="testScriptRef" />  
40 - </div>  
41 -</template>  
42 -  
43 -<script lang="ts" setup>  
44 - import { ref } from 'vue';  
45 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
46 - import { columns, searchFormSchema } from './config/config.data.ts';  
47 - import { getConvertApi, deleteTransformApi } from '/@/api/device/TransformScriptApi';  
48 - import { useBatchDelete } from '/@/hooks/web/useBatchDelete';  
49 - import { useDrawer } from '/@/components/Drawer/index';  
50 - import ScriptDrawer from './cpns/ScriptDrawer.vue';  
51 - import TestScript from './cpns/TestScript.vue';  
52 - const handleSuccess = () => {  
53 - reload();  
54 - };  
55 - const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(  
56 - deleteTransformApi,  
57 - handleSuccess  
58 - );  
59 - const [registerTable, { reload }] = useTable({  
60 - api: getConvertApi,  
61 - title: '转换脚本列表',  
62 - columns,  
63 - useSearchForm: true,  
64 - showTableSetting: true,  
65 - bordered: true,  
66 - showIndexColumn: false,  
67 - formConfig: {  
68 - labelWidth: 100,  
69 - schemas: searchFormSchema,  
70 - },  
71 - actionColumn: {  
72 - width: 180,  
73 - title: '操作',  
74 - dataIndex: 'action',  
75 - slots: { customRender: 'action' },  
76 - fixed: 'right',  
77 - },  
78 - ...selectionOptions,  
79 - });  
80 - const [registerDrawer, { openDrawer }] = useDrawer({});  
81 -  
82 - const isStatus = ref(0);  
83 - const testScriptRef = ref();  
84 - const scriptDrawerRef = ref();  
85 - const handleIsStatus = ({ status, jsCode }) => {  
86 - isStatus.value = status;  
87 - testScriptRef.value.aceEditor.setValue(jsCode);  
88 - };  
89 - const handleCancelStatus = ({ status, emitType }) => {  
90 - openDrawer(true);  
91 - isStatus.value = status;  
92 - if (emitType === 'ok') {  
93 - const jsCode = testScriptRef.value.aceEditor.getValue();  
94 - scriptDrawerRef.value.aceEditor.setValue(jsCode);  
95 - }  
96 - };  
97 - const handleCreate = () => {  
98 - openDrawer(true, {  
99 - isUpdate: false,  
100 - });  
101 - };  
102 - const handleEdit = (record: Recordable) => {  
103 - openDrawer(true, { isUpdate: true, record });  
104 - };  
105 -</script>  
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 - </BasicDrawer>  
12 -</template>  
13 -<script lang="ts">  
14 - import { defineComponent, ref, computed, unref } from 'vue';  
15 - import { BasicForm, useForm } from '/@/components/Form';  
16 - import { formSchema } from './config.data';  
17 - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';  
18 - import { saveOrEditMessageConfig } from '/@/api/message/config';  
19 - import { useMessage } from '/@/hooks/web/useMessage';  
20 -  
21 - export default defineComponent({  
22 - name: 'ConfigDrawer',  
23 - components: { BasicDrawer, BasicForm },  
24 - emits: ['success', 'register'],  
25 - setup(_, { emit }) {  
26 - const isUpdate = ref(true);  
27 -  
28 - const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({  
29 - labelWidth: 120,  
30 - schemas: formSchema,  
31 - showActionButtonGroup: false,  
32 - });  
33 -  
34 - const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {  
35 - await resetFields();  
36 - setDrawerProps({ confirmLoading: false });  
37 - isUpdate.value = !!data?.isUpdate;  
38 - if (unref(isUpdate)) {  
39 - const config = data.record.config;  
40 - for (const key in config) {  
41 - Reflect.set(data.record, key + '', config[key]);  
42 - }  
43 - await setFieldsValue({  
44 - ...data.record,  
45 - });  
46 - }  
47 - });  
48 -  
49 - const getTitle = computed(() => (!unref(isUpdate) ? '新增消息配置' : '编辑消息配置'));  
50 -  
51 - async function handleSubmit() {  
52 - try {  
53 - const values = await validate();  
54 - const { createMessage } = useMessage();  
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 - };  
69 - }  
70 - Reflect.set(values, 'config', config);  
71 - let saveMessage = '添加成功';  
72 - let updateMessage = '修改成功';  
73 - await saveOrEditMessageConfig(values, unref(isUpdate));  
74 - closeDrawer();  
75 - emit('success');  
76 - createMessage.success(unref(isUpdate) ? updateMessage : saveMessage);  
77 - } finally {  
78 - setDrawerProps({ confirmLoading: false });  
79 - }  
80 - }  
81 -  
82 - return {  
83 - registerDrawer,  
84 - registerForm,  
85 - getTitle,  
86 - handleSubmit,  
87 - };  
88 - },  
89 - });  
90 -</script>  
1 -import { BasicColumn } from '/@/components/Table';  
2 -import { FormSchema } from '/@/components/Table';  
3 -import { findDictItemByCode } from '/@/api/system/dict';  
4 -  
5 -export const columns: BasicColumn[] = [  
6 - {  
7 - title: '场景联动名称',  
8 - dataIndex: 'name',  
9 - },  
10 - {  
11 - title: '触发方式',  
12 - // dataIndex: 'name',  
13 - width: 200,  
14 - },  
15 - {  
16 - title: '状态',  
17 - dataIndex: 'status',  
18 - width: 200,  
19 - },  
20 - {  
21 - title: '描述',  
22 - dataIndex: 'description',  
23 - width: 180,  
24 - },  
25 -];  
26 -  
27 -export const formSchema: FormSchema[] = [  
28 - {  
29 - field: 'configName',  
30 - label: '场景联动名称',  
31 - required: true,  
32 - component: 'Input',  
33 - },  
34 - {  
35 - field: 'messageType',  
36 - label: '所属组织',  
37 - required: true,  
38 - component: 'ApiSelect',  
39 - componentProps: {  
40 - api: findDictItemByCode,  
41 - params: {  
42 - dictCode: 'message_type',  
43 - },  
44 - labelField: 'itemText',  
45 - valueField: 'itemValue',  
46 - },  
47 - },  
48 - {  
49 - field: 'no1',  
50 - label: '触发器',  
51 - required: true,  
52 - component: 'Input',  
53 - },  
54 - {  
55 - field: 'no2',  
56 - label: '执行条件',  
57 - required: true,  
58 - component: 'Input',  
59 - },  
60 - {  
61 - field: 'no3',  
62 - label: '执行动作',  
63 - required: true,  
64 - component: 'Input',  
65 - },  
66 -];  
1 -<template>  
2 - <div class="p-4">  
3 - <BasicTable @register="registerTable">  
4 - <template #toolbar>  
5 - <a-button type="primary" @click="handleCreate"> 新增设备 </a-button>  
6 - </template>  
7 - <template #config="{ record }">  
8 - <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button>  
9 - </template>  
10 - <template #deviceProfile="{ record }">  
11 - <a-button type="link" class="ml-2" @click="goDeviceProfile">  
12 - {{ record.deviceProfile.name }}  
13 - </a-button>  
14 - </template>  
15 - <template #deviceType="{ record }">  
16 - <Tag color="success" class="ml-2">  
17 - {{  
18 - record.deviceType == DeviceTypeEnum.GATEWAY  
19 - ? '网关设备'  
20 - : record.deviceType == DeviceTypeEnum.DIRECT_CONNECTION  
21 - ? '直连设备'  
22 - : '网关子设备'  
23 - }}  
24 - </Tag>  
25 - </template>  
26 - <template #deviceState="{ record }">  
27 - <Tag  
28 - :color="  
29 - record.deviceState == DeviceState.INACTIVE  
30 - ? 'warning'  
31 - : record.deviceState == DeviceState.ONLINE  
32 - ? 'success'  
33 - : 'error'  
34 - "  
35 - class="ml-2"  
36 - >  
37 - {{  
38 - record.deviceState == DeviceState.INACTIVE  
39 - ? '待激活'  
40 - : record.deviceState == DeviceState.ONLINE  
41 - ? '在线'  
42 - : '离线'  
43 - }}  
44 - </Tag>  
45 - </template>  
46 - <template #action="{ record }">  
47 - <TableAction  
48 - :actions="[  
49 - {  
50 - label: '编辑',  
51 - icon: 'clarity:note-edit-line',  
52 - onClick: handleEdit.bind(null, record),  
53 - },  
54 - {  
55 - label: '删除',  
56 - icon: 'ant-design:delete-outlined',  
57 - color: 'error',  
58 - popConfirm: {  
59 - title: '是否确认删除',  
60 - confirm: handleDelete.bind(null, record),  
61 - },  
62 - },  
63 - ]"  
64 - />  
65 - </template>  
66 - </BasicTable>  
67 - <RuleEngineDrawer @register="registerDrawer" @success="handleSuccess" />  
68 - </div>  
69 -</template>  
70 -<script lang="ts">  
71 - import { defineComponent, h } from 'vue';  
72 - import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel';  
73 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
74 - import { useDrawer } from '/@/components/Drawer';  
75 - import RuleEngineDrawer from './RuleEngineDrawer.vue';  
76 - import { columns } from './config.data';  
77 - import { Modal, Tag } from 'ant-design-vue';  
78 - import { useMessage } from '/@/hooks/web/useMessage';  
79 - import { deleteDevice, devicePage } from '/@/api/device/deviceManager';  
80 - import { PageEnum } from '/@/enums/pageEnum';  
81 - import { useGo } from '/@/hooks/web/usePage';  
82 -  
83 - export default defineComponent({  
84 - name: 'DeviceManagement',  
85 - components: { BasicTable, RuleEngineDrawer, TableAction, Tag },  
86 - setup() {  
87 - const [registerDrawer, { openDrawer }] = useDrawer();  
88 - const { createMessage } = useMessage();  
89 - const go = useGo();  
90 - const [registerTable, { reload }] = useTable({  
91 - title: '设备列表',  
92 - api: devicePage,  
93 - columns,  
94 - useSearchForm: false,  
95 - showTableSetting: true,  
96 - bordered: true,  
97 - showIndexColumn: false,  
98 - actionColumn: {  
99 - width: 200,  
100 - title: '操作',  
101 - dataIndex: 'action',  
102 - slots: { customRender: 'action' },  
103 - fixed: 'right',  
104 - },  
105 - });  
106 -  
107 - function handleCreate() {  
108 - openDrawer(true, {  
109 - isUpdate: false,  
110 - });  
111 - }  
112 -  
113 - function handleEdit(record: Recordable) {  
114 - openDrawer(true, {  
115 - record,  
116 - isUpdate: true,  
117 - });  
118 - }  
119 -  
120 - function handleDelete(record: Recordable) {  
121 - let ids = [record.id];  
122 - deleteDevice(ids).then(() => {  
123 - createMessage.success('删除设备成功');  
124 - handleSuccess();  
125 - });  
126 - }  
127 -  
128 - function handleSuccess() {  
129 - reload();  
130 - }  
131 - function showData(record: Recordable) {  
132 - Modal.info({  
133 - title: '当前配置',  
134 - width: 480,  
135 - content: h(JsonPreview, { data: JSON.parse(JSON.stringify(record.deviceInfo)) }),  
136 - });  
137 - }  
138 - function goDeviceProfile() {  
139 - go(PageEnum.DEVICE_PROFILE);  
140 - }  
141 - return {  
142 - registerTable,  
143 - registerDrawer,  
144 - showData,  
145 - handleCreate,  
146 - handleEdit,  
147 - handleDelete,  
148 - handleSuccess,  
149 - goDeviceProfile,  
150 - DeviceTypeEnum,  
151 - DeviceState,  
152 - };  
153 - },  
154 - });  
155 -</script>  
1 -<template>  
2 - <CollapseContainer style="background-color: #eeeeee">  
3 - <div style="position: relative">  
4 - <BasicForm  
5 - :labelWidth="100"  
6 - :emptySpan="10"  
7 - :showResetButton="false"  
8 - :showSubmitButton="false"  
9 - @register="registerCondition"  
10 - />  
11 - </div>  
12 - </CollapseContainer>  
13 -</template>  
14 -<script lang="ts">  
15 - import { defineComponent, ref } from 'vue';  
16 - import { CollapseContainer } from '/@/components/Container/index';  
17 - import { BasicForm, useForm } from '/@/components/Form/index';  
18 - import { Input } from 'ant-design-vue';  
19 - import { useConditionDrawerSchema } from '../config';  
20 - // import { screenLinkPageByDeptIdGetDevice } from '/@/api/ruleengine/ruleengineApi';  
21 -  
22 - export default defineComponent({  
23 - components: { CollapseContainer, BasicForm, [Input.name]: Input },  
24 - props: ['deviceInfo1', 'editConditionFather', 'newConditionMapFather'],  
25 -  
26 - setup(props) {  
27 - const fieldValue: any = ref({});  
28 - const [registerCondition, { setFieldsValue, getFieldsValue, updateSchema, resetFields }] =  
29 - useForm({  
30 - labelWidth: 100,  
31 - schemas: useConditionDrawerSchema,  
32 - actionColOptions: { span: 24 },  
33 - });  
34 - const getFieldsValueFunc = () => {  
35 - fieldValue.value = getFieldsValue();  
36 - return fieldValue.value;  
37 - };  
38 - const resetFieldsValueFunc = () => {  
39 - resetFields();  
40 - };  
41 - const updateFieldDeviceId = (v) => {  
42 - setTimeout(() => {  
43 - updateSchema({  
44 - field: 'entityId',  
45 - componentProps: {  
46 - options: v,  
47 - },  
48 - });  
49 - }, 10);  
50 - };  
51 -  
52 - //回显数据  
53 - const setFieldsFormValueFun = () => {  
54 - if (props.editConditionFather !== 1) {  
55 - setTimeout(() => {  
56 - setFieldsValue(props.editConditionFather);  
57 - setFieldsValue({  
58 - type:  
59 - props.editConditionFather?.triggerCondition?.condition[0]?.valueType == 'NUMERIC'  
60 - ? 'NUMERIC1'  
61 - : 'NUMERIC2',  
62 - operation1:  
63 - props.editConditionFather?.triggerCondition?.condition[0]?.predicate?.operation,  
64 - operation2:  
65 - props.editConditionFather?.triggerCondition?.condition[0]?.predicate?.operation,  
66 - value1:  
67 - props.editConditionFather?.triggerCondition?.condition[0]?.predicate?.value  
68 - ?.defaultValue,  
69 - value2:  
70 - props.editConditionFather?.triggerCondition?.condition[0]?.predicate?.value  
71 - ?.defaultValue,  
72 - });  
73 - }, 100);  
74 - }  
75 - };  
76 - setFieldsFormValueFun();  
77 - const editSelectDevice = () => {  
78 - if (props.newConditionMapFather !== 1) {  
79 - setTimeout(() => {  
80 - updateSchema({  
81 - field: 'entityId',  
82 - componentProps: {  
83 - options: props.newConditionMapFather,  
84 - },  
85 - });  
86 - }, 100);  
87 - }  
88 - };  
89 - editSelectDevice();  
90 - //新增清空设备选择  
91 - const clearSelectDevice = () => {  
92 - updateSchema({  
93 - field: 'entityId',  
94 - componentProps: {  
95 - options: [],  
96 - },  
97 - });  
98 - };  
99 - // const editSelectDevice = (v) => {  
100 - // updateSchema({  
101 - // field: 'entityId',  
102 - // componentProps: {  
103 - // options: v,  
104 - // },  
105 - // });  
106 - // };  
107 - return {  
108 - updateFieldDeviceId,  
109 - resetFieldsValueFunc,  
110 - clearSelectDevice,  
111 - editSelectDevice,  
112 - getFieldsValueFunc,  
113 - registerCondition,  
114 - };  
115 - },  
116 - });  
117 -</script>  
1 -<template>  
2 - <CollapseContainer class="prefixRedDot" style="background-color: #eeeeee">  
3 - <div style="position: relative">  
4 - <BasicForm  
5 - :labelWidth="100"  
6 - :showResetButton="false"  
7 - :showSubmitButton="false"  
8 - :emptySpan="10"  
9 - @register="registerAction"  
10 - />  
11 - </div>  
12 - </CollapseContainer>  
13 -</template>  
14 -<script lang="ts">  
15 - import { defineComponent, ref } from 'vue';  
16 - import { CollapseContainer } from '/@/components/Container/index';  
17 - import { BasicForm, useForm } from '/@/components/Form/index';  
18 - import { Input } from 'ant-design-vue';  
19 - import { useActionDrawerSchema } from '../config';  
20 -  
21 - export default defineComponent({  
22 - components: { CollapseContainer, BasicForm, [Input.name]: Input },  
23 - props: ['deviceInfo2', 'editActionFather', 'newActionMapFather'],  
24 -  
25 - setup(props) {  
26 - const fieldValue: any = ref({});  
27 - const [registerAction, { setFieldsValue, getFieldsValue, resetFields, updateSchema }] =  
28 - useForm({  
29 - labelWidth: 100,  
30 - schemas: useActionDrawerSchema,  
31 - actionColOptions: { span: 24 },  
32 - });  
33 - const getFieldsValueFunc = () => {  
34 - fieldValue.value = getFieldsValue();  
35 - return fieldValue.value;  
36 - };  
37 - const resetFieldsValueFunc = () => {  
38 - resetFields();  
39 - };  
40 - const updateFieldDeviceId = (v) => {  
41 - setTimeout(() => {  
42 - updateSchema({  
43 - field: 'deviceId',  
44 - componentProps: {  
45 - options: v,  
46 - },  
47 - });  
48 - }, 10);  
49 - };  
50 -  
51 - //回显数据  
52 - const setFieldsFormValueFun = () => {  
53 - if (props.editActionFather !== 1) {  
54 - setTimeout(() => {  
55 - setFieldsValue(props.editActionFather);  
56 - }, 100);  
57 - }  
58 - };  
59 - setFieldsFormValueFun();  
60 - const editSelectDevice = () => {  
61 - if (props.newActionMapFather !== 1) {  
62 - setTimeout(() => {  
63 - updateSchema({  
64 - field: 'deviceId',  
65 - componentProps: {  
66 - options: props.newActionMapFather,  
67 - },  
68 - });  
69 - }, 100);  
70 - }  
71 - };  
72 - editSelectDevice();  
73 - //新增清空设备选择  
74 - const clearSelectDevice = () => {  
75 - updateSchema({  
76 - field: 'deviceId',  
77 - componentProps: {  
78 - options: [],  
79 - },  
80 - });  
81 - };  
82 - return {  
83 - updateFieldDeviceId,  
84 - clearSelectDevice,  
85 - editSelectDevice,  
86 - resetFieldsValueFunc,  
87 - getFieldsValueFunc,  
88 - registerAction,  
89 - };  
90 - },  
91 - });  
92 -</script>  
93 -  
94 -<style lang="less">  
95 - .prefixRedDot:before {  
96 - content: '* ';  
97 - color: red;  
98 - vertical-align: middle;  
99 - display: inline-block;  
100 - position: relative;  
101 - top: 20px;  
102 - left: 5px;  
103 - }  
104 -</style>  
1 -<template>  
2 - <div>  
3 - <CollapseContainer style="background-color: #eeeeee">  
4 - <div>  
5 - <BasicForm  
6 - :labelWidth="100"  
7 - :showResetButton="false"  
8 - :showSubmitButton="false"  
9 - :emptySpan="10"  
10 - @register="registerTrigger"  
11 - />  
12 - </div>  
13 - </CollapseContainer>  
14 - </div>  
15 -</template>  
16 -<script lang="ts">  
17 - import { defineComponent, ref } from 'vue';  
18 - import { CollapseContainer } from '/@/components/Container/index';  
19 - import { BasicForm, useForm } from '/@/components/Form/index';  
20 - import { Input } from 'ant-design-vue';  
21 - import { useTriggerDrawerSchema } from '../config';  
22 -  
23 - export default defineComponent({  
24 - components: { CollapseContainer, BasicForm, [Input.name]: Input },  
25 - props: ['deviceInfo', 'editTriggerFather', 'newFilterMapFather'],  
26 - setup(props) {  
27 - const fieldValue: any = ref({});  
28 - const [registerTrigger, { resetFields, setFieldsValue, getFieldsValue, updateSchema }] =  
29 - useForm({  
30 - labelWidth: 100,  
31 - schemas: useTriggerDrawerSchema,  
32 - actionColOptions: { span: 24 },  
33 - });  
34 - const getFieldsValueFunc = () => {  
35 - fieldValue.value = getFieldsValue();  
36 - return fieldValue.value;  
37 - };  
38 - const updateFieldDeviceId = (v) => {  
39 - setTimeout(() => {  
40 - updateSchema({  
41 - field: 'entityId',  
42 - componentProps: {  
43 - options: v,  
44 - },  
45 - });  
46 - }, 10);  
47 - };  
48 - const resetFieldsValueFunc = () => {  
49 - resetFields();  
50 - };  
51 -  
52 - //回显数据  
53 - const setFieldsFormValueFun = () => {  
54 - if (props.editTriggerFather != 1) {  
55 - setTimeout(() => {  
56 - setFieldsValue(props.editTriggerFather);  
57 - setFieldsValue({  
58 - entityId1: props.editTriggerFather.entityId,  
59 - entityId2: props.editTriggerFather.entityId,  
60 - type1: props.editTriggerFather?.triggerCondition?.condition[0]?.key?.type,  
61 - type2: props.editTriggerFather?.triggerCondition?.condition[0]?.predicate?.type,  
62 - operation:  
63 - props.editTriggerFather?.triggerCondition?.condition[0]?.predicate?.operation,  
64 - value:  
65 - props.editTriggerFather?.triggerCondition?.condition[0]?.predicate?.value  
66 - ?.defaultValue,  
67 - });  
68 - }, 10);  
69 - }  
70 - };  
71 -  
72 - setFieldsFormValueFun();  
73 - //新增清空设备选择  
74 - const clearSelectDevice = () => {  
75 - updateSchema({  
76 - field: 'entityId',  
77 - componentProps: {  
78 - options: [],  
79 - },  
80 - });  
81 - };  
82 - const editSelectDevice = () => {  
83 - if (props.newFilterMapFather != 1) {  
84 - setTimeout(() => {  
85 - updateSchema({  
86 - field: 'entityId',  
87 - componentProps: {  
88 - options: props.newFilterMapFather,  
89 - },  
90 - });  
91 - }, 100);  
92 - }  
93 - };  
94 - editSelectDevice();  
95 - //新增清空场景触发器选择  
96 - const clearSelectScene = () => {  
97 - updateSchema({  
98 - field: 'sceneLinkageId',  
99 - componentProps: {  
100 - options: [],  
101 - },  
102 - });  
103 - };  
104 - const editSelectScene = (v) => {  
105 - updateSchema({  
106 - field: 'sceneLinkageId',  
107 - componentProps: {  
108 - options: v,  
109 - },  
110 - });  
111 - };  
112 - return {  
113 - updateFieldDeviceId,  
114 - resetFieldsValueFunc,  
115 - clearSelectScene,  
116 - editSelectScene,  
117 - clearSelectDevice,  
118 - editSelectDevice,  
119 - getFieldsValueFunc,  
120 - registerTrigger,  
121 - };  
122 - },  
123 - });  
124 -</script>  
125 -  
126 -<style>  
127 - .ant-slider-handle {  
128 - display: none !important;  
129 - }  
130 -</style>  
1 -import { BasicColumn, FormSchema } from '/@/components/Table';  
2 -import { ref } from 'vue';  
3 -import {  
4 - screenLinkOrganizationGetApi,  
5 - screenLinkPagePutApi,  
6 -} from '/@/api/ruleengine/ruleengineApi';  
7 -import { h } from 'vue';  
8 -import { Switch } from 'ant-design-vue';  
9 -import { useMessage } from '/@/hooks/web/useMessage';  
10 -import { copyTransFun } from '/@/utils/fnUtils';  
11 -  
12 -/**  
13 - * 所使用的枚举值  
14 - */  
15 -  
16 -export enum TriggerEnum {  
17 - IS_DEVICE_ACT = 'DEVICE_TRIGGER',  
18 - IS_TIME_ACT = 'SCHEDULE_TRIGGER',  
19 - IS_SCENE_ACT = 'SCENE_TRIGGER',  
20 - IS_HAND_ACT = 'HAND_ACT',  
21 - IS_MSG_NOTIFY = 'MSG_NOTIFY',  
22 - IS_DEVICE_STATUS = 'DEVICE_STATUS',  
23 - IS_TIME_ALL = 'SCHEDULE_TRIGGER',  
24 -}  
25 -  
26 -export enum AttributeActionEnum {  
27 - IS_ATTRIBUTE_ACT = 'ATTRIBUTE',  
28 - IS_UP_DOWN_ACT = 'TIME_SERIES',  
29 -}  
30 -  
31 -export enum AttrAndWenDuEnum {  
32 - IS_ALL_ATTR = 'ALL_ATTR',  
33 - IS_WENDU_ACT = 'NUMERIC',  
34 - IS_SHIDU = 'NUMERIC',  
35 - IS_CONDITION_WENDU = 'NUMERIC2',  
36 - IS_CONDITION_SHIDU = 'NUMERIC1',  
37 -}  
38 -export const isConditionShiDu = (type: string) => {  
39 - return type === AttrAndWenDuEnum.IS_CONDITION_SHIDU;  
40 -};  
41 -export const isConditionWenDu = (type: string) => {  
42 - return type === AttrAndWenDuEnum.IS_CONDITION_WENDU;  
43 -};  
44 -  
45 -export const isShiDu = (type: string) => {  
46 - return type === AttrAndWenDuEnum.IS_SHIDU;  
47 -};  
48 -  
49 -export const isWenDu = (type: string) => {  
50 - return type === AttrAndWenDuEnum.IS_WENDU_ACT;  
51 -};  
52 -  
53 -export const isTimeAll = (type: string) => {  
54 - return type === TriggerEnum.IS_TIME_ACT;  
55 -};  
56 -  
57 -export const isMsg = (type: string) => {  
58 - return type === TriggerEnum.IS_MSG_NOTIFY;  
59 -};  
60 -  
61 -export const isUpAndDown = (type: string) => {  
62 - return type === AttributeActionEnum.IS_UP_DOWN_ACT;  
63 -};  
64 -  
65 -export const isDevice = (type: string) => {  
66 - return type === TriggerEnum.IS_DEVICE_ACT;  
67 -};  
68 -  
69 -export const isTime = (type: string) => {  
70 - return type === TriggerEnum.IS_TIME_ACT;  
71 -};  
72 -  
73 -export const isScene = (type: string) => {  
74 - return type === TriggerEnum.IS_SCENE_ACT;  
75 -};  
76 -  
77 -export const isHand = (type: string) => {  
78 - return type === TriggerEnum.IS_HAND_ACT;  
79 -};  
80 -  
81 -export const columns: BasicColumn[] = [  
82 - {  
83 - title: '场景联动名称',  
84 - dataIndex: 'name',  
85 - width: 200,  
86 - },  
87 - {  
88 - title: '触发方式',  
89 - dataIndex: 'triggerType',  
90 - format: (text: string, record: Recordable) => {  
91 - return record.triggers[0]?.triggerType == 'DEVICE_TRIGGER'  
92 - ? '设备触发'  
93 - : record.triggers[0]?.triggerType == 'SCHEDULE_TRIGGER'  
94 - ? '定时触发'  
95 - : record.triggers[0]?.triggerType == 'SCENE_TRIGGER'  
96 - ? '场景触发'  
97 - : '手动触发';  
98 - },  
99 - width: 200,  
100 - },  
101 - {  
102 - title: '状态',  
103 - dataIndex: 'status',  
104 - width: 120,  
105 - customRender: ({ record }) => {  
106 - if (!Reflect.has(record, 'pendingStatus')) {  
107 - record.pendingStatus = false;  
108 - }  
109 - return h(Switch, {  
110 - checked: record.status === 1,  
111 - checkedChildren: '已启用',  
112 - unCheckedChildren: '已禁用',  
113 - loading: record.pendingStatus,  
114 - onChange(checked: boolean) {  
115 - record.pendingStatus = true;  
116 - const newStatus = checked ? 1 : 0;  
117 - const { createMessage } = useMessage();  
118 - screenLinkPagePutApi({ id: record.id, status: newStatus })  
119 - .then(() => {  
120 - record.status = newStatus;  
121 - if (record.status == 1) {  
122 - createMessage.success(`已启用`);  
123 - } else {  
124 - createMessage.error('已禁用');  
125 - }  
126 - })  
127 - .catch(() => {  
128 - createMessage.error('已禁用');  
129 - })  
130 - .finally(() => {  
131 - record.pendingStatus = false;  
132 - });  
133 - },  
134 - });  
135 - },  
136 - },  
137 - {  
138 - title: '描述',  
139 - dataIndex: 'description',  
140 - width: 200,  
141 - },  
142 - {  
143 - title: '创建时间',  
144 - dataIndex: 'createTime',  
145 - width: 180,  
146 - },  
147 -];  
148 -  
149 -export const getData = ref(null);  
150 -  
151 -export const formSchema: FormSchema[] = [  
152 - {  
153 - field: 'name',  
154 - label: '场景联动名称',  
155 - colProps: { span: 24 },  
156 - required: true,  
157 - component: 'Input',  
158 - componentProps: {  
159 - maxLength: 36,  
160 - placeholder: '请输入场景联动名称',  
161 - },  
162 - },  
163 - {  
164 - required: true,  
165 - field: 'organizationId',  
166 - label: '所属组织',  
167 - colProps: { span: 24 },  
168 - component: 'ApiTreeSelect',  
169 - componentProps: ({ formModel, formActionType }) => {  
170 - return {  
171 - api: async () => {  
172 - const data = await screenLinkOrganizationGetApi();  
173 - copyTransFun(data as any as any[]);  
174 - return data;  
175 - },  
176 - onChange: async (v) => {  
177 - if (v == undefined) {  
178 - formModel.entityId = undefined;  
179 - const { updateSchema } = formActionType;  
180 - updateSchema({  
181 - field: 'entityId',  
182 - componentProps: {  
183 - options: undefined,  
184 - },  
185 - });  
186 - } else {  
187 - getData.value = v;  
188 - }  
189 - },  
190 - };  
191 - },  
192 - },  
193 - {  
194 - field: 'description',  
195 - label: '描述',  
196 - colProps: { span: 24 },  
197 - component: 'InputTextArea',  
198 - componentProps: {  
199 - maxLength: 255,  
200 - placeholder: '请输入描述',  
201 - },  
202 - },  
203 -];  
204 -  
205 -export const searchFormSchema: FormSchema[] = [  
206 - {  
207 - field: 'organizationId',  
208 - label: '所属组织',  
209 - colProps: { span: 6 },  
210 - component: 'ApiTreeSelect',  
211 - componentProps: {  
212 - api: async () => {  
213 - const data = await screenLinkOrganizationGetApi();  
214 - copyTransFun(data as any as any[]);  
215 - return data;  
216 - },  
217 - },  
218 - },  
219 - {  
220 - field: 'name',  
221 - label: '名称',  
222 - component: 'Input',  
223 - colProps: { span: 6 },  
224 - componentProps: {  
225 - maxLength: 36,  
226 - placeholder: '请输入名称',  
227 - },  
228 - },  
229 - {  
230 - field: 'status',  
231 - label: '设备状态',  
232 - component: 'Select',  
233 - componentProps: {  
234 - placeholder: '请选择状态',  
235 - options: [  
236 - { label: '已启用', value: '1' },  
237 - { label: '未启用', value: '0' },  
238 - ],  
239 - },  
240 - colProps: { span: 6 },  
241 - },  
242 -];  
243 -  
244 -export const useTriggerDrawerSchema: FormSchema[] = [  
245 - {  
246 - field: 'triggerType',  
247 - label: '',  
248 - component: 'Select',  
249 - componentProps: {  
250 - placeholder: '设备触发',  
251 - options: [  
252 - { label: '设备触发', value: 'DEVICE_TRIGGER' },  
253 - { label: '定时触发', value: 'SCHEDULE_TRIGGER' },  
254 - { label: '场景触发', value: 'SCENE_TRIGGER' },  
255 - { label: '手动触发', value: 'HAND_ACT' },  
256 - ],  
257 - },  
258 - colProps: { span: 12 },  
259 - },  
260 - {  
261 - field: 'entityId',  
262 - label: '',  
263 - component: 'Select',  
264 - componentProps: {  
265 - placeholder: '请选择设备',  
266 - },  
267 - ifShow: ({ values }) =>  
268 - !isTime(Reflect.get(values, 'triggerType')) &&  
269 - !isScene(Reflect.get(values, 'triggerType')) &&  
270 - !isHand(Reflect.get(values, 'triggerType')),  
271 - colProps: {  
272 - span: 12,  
273 - },  
274 - },  
275 - {  
276 - field: 'entityId1',  
277 - component: 'Input',  
278 - label: '',  
279 - componentProps: {  
280 - maxLength: 255,  
281 - placeholder: '请输入Cron表达式',  
282 - },  
283 - colProps: {  
284 - span: 12,  
285 - },  
286 - ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'triggerType')),  
287 - },  
288 - {  
289 - field: 'type1',  
290 - label: '',  
291 - component: 'Select',  
292 - componentProps: {  
293 - placeholder: '属性触发',  
294 - options: [  
295 - { label: '属性触发', value: 'ATTRIBUTE' },  
296 - { label: '上下线触发', value: 'TIME_SERIES' },  
297 - ],  
298 - },  
299 - ifShow: ({ values }) =>  
300 - !isTime(Reflect.get(values, 'triggerType')) &&  
301 - !isScene(Reflect.get(values, 'triggerType')) &&  
302 - !isHand(Reflect.get(values, 'triggerType')),  
303 - colProps: { span: 12 },  
304 - },  
305 - {  
306 - field: 'key1',  
307 - label: '',  
308 - component: 'Select',  
309 - componentProps: {  
310 - placeholder: '请选择上下线',  
311 - options: [  
312 - { label: '上下线', value: '1' },  
313 - { label: '上线', value: '2' },  
314 - { label: '下线', value: '3' },  
315 - ],  
316 - },  
317 - colProps: { span: 12 },  
318 - ifShow: ({ values }) =>  
319 - isUpAndDown(Reflect.get(values, 'type1')) &&  
320 - !isTime(Reflect.get(values, 'triggerType')) &&  
321 - !isScene(Reflect.get(values, 'triggerType')) &&  
322 - !isHand(Reflect.get(values, 'triggerType')),  
323 - },  
324 - {  
325 - field: 'type2',  
326 - label: '',  
327 - component: 'Select',  
328 - componentProps: {  
329 - placeholder: '全部属性',  
330 - options: [  
331 - { label: '全部属性', value: 'STRING' },  
332 - { label: 'wendu', value: 'NUMERIC' },  
333 - ],  
334 - },  
335 - ifShow: ({ values }) =>  
336 - !isTime(Reflect.get(values, 'triggerType')) &&  
337 - !isScene(Reflect.get(values, 'triggerType')) &&  
338 - !isHand(Reflect.get(values, 'triggerType')) &&  
339 - !isUpAndDown(Reflect.get(values, 'type1')),  
340 - colProps: { span: 12 },  
341 - },  
342 - {  
343 - field: 'operation',  
344 - label: '',  
345 - component: 'Select',  
346 - componentProps: {  
347 - placeholder: '',  
348 - options: [  
349 - { label: '=', value: 'EQUAL' },  
350 - { label: '<', value: 'LESS' },  
351 - { label: '>', value: 'GREATER' },  
352 - { label: '<=', value: 'LESS_OR_EQUAL' },  
353 - { label: '>=', value: 'GREATER_OR_EQUAL' },  
354 - ],  
355 - },  
356 - ifShow: ({ values }) =>  
357 - isWenDu(Reflect.get(values, 'type2')) &&  
358 - !isUpAndDown(Reflect.get(values, 'type1')) &&  
359 - !isTime(Reflect.get(values, 'triggerType')) &&  
360 - !isScene(Reflect.get(values, 'triggerType')) &&  
361 - !isHand(Reflect.get(values, 'triggerType')),  
362 - colProps: { span: 12 },  
363 - },  
364 - {  
365 - field: 'value',  
366 - component: 'Input',  
367 - label: '',  
368 - componentProps: {  
369 - maxLength: 16,  
370 - placeholder: '请输入比较值',  
371 - },  
372 -  
373 - ifShow: ({ values }) =>  
374 - isWenDu(Reflect.get(values, 'type2')) &&  
375 - !isUpAndDown(Reflect.get(values, 'type1')) &&  
376 - !isTime(Reflect.get(values, 'triggerType')) &&  
377 - !isScene(Reflect.get(values, 'triggerType')) &&  
378 - !isHand(Reflect.get(values, 'triggerType')),  
379 - colProps: {  
380 - span: 12,  
381 - },  
382 - },  
383 -  
384 - {  
385 - field: 'entityId2',  
386 - label: '',  
387 - component: 'Select',  
388 - colProps: {  
389 - span: 12,  
390 - },  
391 - componentProps: {  
392 - placeholder: '请输入场景触发器',  
393 - options: [  
394 - { label: '场景触发器1', value: '1' },  
395 - { label: '场景触发器2', value: '2' },  
396 - { label: '场景触发器3', value: '3' },  
397 - ],  
398 - },  
399 - ifShow: ({ values }) => isScene(Reflect.get(values, 'triggerType')),  
400 - },  
401 -  
402 - {  
403 - field: 'no3',  
404 - label: '',  
405 - component: 'ApiSelect',  
406 - colProps: {  
407 - span: 12,  
408 - },  
409 - componentProps: {  
410 - placeholder: '暂不实现',  
411 - },  
412 - ifShow: ({ values }) => isHand(Reflect.get(values, 'triggerType')),  
413 - },  
414 -];  
415 -  
416 -export const useConditionDrawerSchema: FormSchema[] = [  
417 - {  
418 - field: 'triggerType',  
419 - label: '',  
420 - component: 'Select',  
421 - componentProps: {  
422 - placeholder: '设备状态',  
423 - options: [  
424 - { label: '设备触发', value: 'DEVICE_TRIGGER' },  
425 - { label: '时间范围', value: 'SCHEDULE_TRIGGER' },  
426 - ],  
427 - },  
428 - colProps: { span: 12 },  
429 - },  
430 - {  
431 - field: 'entityId',  
432 - label: '',  
433 - component: 'Select',  
434 - componentProps: {  
435 - placeholder: '请选择设备',  
436 - },  
437 - ifShow: ({ values }) => !isTimeAll(Reflect.get(values, 'triggerType')),  
438 - colProps: {  
439 - span: 12,  
440 - },  
441 - },  
442 - {  
443 - field: 'createTime',  
444 - component: 'DatePicker',  
445 - label: '',  
446 - componentProps: {  
447 - placeholder: '请选择起始时间',  
448 - },  
449 - colProps: {  
450 - span: 12,  
451 - },  
452 - ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'triggerType')),  
453 - },  
454 - {  
455 - field: 'updateTime',  
456 - component: 'DatePicker',  
457 - label: '',  
458 - componentProps: {  
459 - placeholder: '请选择结束时间',  
460 - },  
461 - colProps: {  
462 - span: 12,  
463 - },  
464 - ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'triggerType')),  
465 - },  
466 - {  
467 - field: 'type',  
468 - label: '',  
469 - component: 'Select',  
470 - componentProps: {  
471 - placeholder: '请选择或者输入属性',  
472 - options: [  
473 - { label: 'shidu', value: 'NUMERIC1' },  
474 - { label: 'wendu', value: 'NUMERIC2' },  
475 - ],  
476 - },  
477 - ifShow: ({ values }) => !isTimeAll(Reflect.get(values, 'triggerType')),  
478 - colProps: { span: 12 },  
479 - },  
480 - {  
481 - field: 'operation1',  
482 - label: '',  
483 - component: 'Select',  
484 - componentProps: {  
485 - placeholder: '',  
486 - options: [  
487 - { label: '=', value: 'EQUAL' },  
488 - { label: '<', value: 'LESS' },  
489 - { label: '>', value: 'GREATER' },  
490 - { label: '<=', value: 'LESS_OR_EQUAL' },  
491 - { label: '>=', value: 'GREATER_OR_EQUAL' },  
492 - ],  
493 - },  
494 - ifShow: ({ values }) =>  
495 - isConditionShiDu(Reflect.get(values, 'type')) &&  
496 - !isTimeAll(Reflect.get(values, 'triggerType')),  
497 - colProps: { span: 12 },  
498 - },  
499 - {  
500 - field: 'value1',  
501 - component: 'Input',  
502 - label: '',  
503 - componentProps: {  
504 - maxLength: 16,  
505 - placeholder: '请输入比较值',  
506 - },  
507 -  
508 - ifShow: ({ values }) =>  
509 - isConditionShiDu(Reflect.get(values, 'type')) &&  
510 - !isTimeAll(Reflect.get(values, 'triggerType')),  
511 - colProps: {  
512 - span: 12,  
513 - },  
514 - },  
515 -  
516 - {  
517 - field: 'operation2',  
518 - label: '',  
519 - component: 'Select',  
520 - componentProps: {  
521 - placeholder: '',  
522 - options: [  
523 - { label: '=', value: 'EQUAL' },  
524 - { label: '<', value: 'LESS' },  
525 - { label: '>', value: 'GREATER' },  
526 - { label: '<=', value: 'LESS_OR_EQUAL' },  
527 - { label: '>=', value: 'GREATER_OR_EQUAL' },  
528 - ],  
529 - },  
530 - ifShow: ({ values }) =>  
531 - isConditionWenDu(Reflect.get(values, 'type')) &&  
532 - !isTimeAll(Reflect.get(values, 'triggerType')),  
533 - colProps: { span: 12 },  
534 - },  
535 - {  
536 - field: 'value2',  
537 - component: 'Input',  
538 - label: '',  
539 - componentProps: {  
540 - maxLength: 16,  
541 - placeholder: '请输入比较值',  
542 - },  
543 - ifShow: ({ values }) =>  
544 - isConditionWenDu(Reflect.get(values, 'type')) &&  
545 - !isTimeAll(Reflect.get(values, 'triggerType')),  
546 - colProps: {  
547 - span: 12,  
548 - },  
549 - },  
550 -];  
551 -  
552 -export const useActionDrawerSchema: FormSchema[] = [  
553 - {  
554 - field: 'outTarget',  
555 - label: '',  
556 - component: 'Select',  
557 - required: true,  
558 - componentProps: {  
559 - placeholder: '请选择设备输出',  
560 - options: [  
561 - { label: '设备输出', value: 'DEVICE_OUT' },  
562 - { label: '消息通知', value: 'MSG_NOTIFY' },  
563 - { label: '场景联动', value: 'SCENE_TRIGGER' },  
564 - ],  
565 - },  
566 - colProps: { span: 12 },  
567 - },  
568 - {  
569 - field: 'deviceId',  
570 - label: '',  
571 - component: 'Select',  
572 - componentProps: {  
573 - placeholder: '请选择设备',  
574 - },  
575 - ifShow: ({ values }) =>  
576 - !isScene(Reflect.get(values, 'outTarget')) && !isMsg(Reflect.get(values, 'outTarget')),  
577 - colProps: {  
578 - span: 12,  
579 - },  
580 - },  
581 - {  
582 - field: 'doContext',  
583 - component: 'Input',  
584 - label: '',  
585 - componentProps: {  
586 - maxLength: 255,  
587 - placeholder: '请输入下发指定',  
588 - },  
589 - ifShow: ({ values }) =>  
590 - !isScene(Reflect.get(values, 'outTarget')) && !isMsg(Reflect.get(values, 'outTarget')),  
591 - colProps: {  
592 - span: 12,  
593 - },  
594 - },  
595 - {  
596 - field: 'wu2',  
597 - component: 'Input',  
598 - label: '',  
599 - componentProps: {  
600 - placeholder: '暂不实现',  
601 - },  
602 - colProps: {  
603 - span: 12,  
604 - },  
605 - ifShow: ({ values }) => isMsg(Reflect.get(values, 'outTarget')),  
606 - },  
607 - {  
608 - field: 'wu3',  
609 - label: '',  
610 - component: 'Input',  
611 - componentProps: {  
612 - placeholder: '无',  
613 - style: {  
614 - visibility: 'hidden',  
615 - },  
616 - },  
617 - colProps: { span: 12 },  
618 - ifShow: ({ values }) => isMsg(Reflect.get(values, 'outTarget')),  
619 - },  
620 - {  
621 - field: 'entityId',  
622 - label: '',  
623 - component: 'Select',  
624 - colProps: {  
625 - span: 12,  
626 - },  
627 - componentProps: {  
628 - placeholder: '请选择场景触发器',  
629 - options: [  
630 - { label: '场景触发器1', value: '1' },  
631 - { label: '场景触发器2', value: '2' },  
632 - { label: '场景触发器3', value: '3' },  
633 - { label: '场景触发器4', value: '4' },  
634 - ],  
635 - },  
636 - ifShow: ({ values }) => isScene(Reflect.get(values, 'outTarget')),  
637 - },  
638 - {  
639 - field: 'wu4',  
640 - label: '',  
641 - component: 'Input',  
642 - componentProps: {  
643 - placeholder: '无',  
644 - style: {  
645 - visibility: 'hidden',  
646 - },  
647 - },  
648 - colProps: { span: 12 },  
649 - ifShow: ({ values }) => isScene(Reflect.get(values, 'outTarget')),  
650 - },  
651 -];  
1 -export interface IAddTrigger {  
2 - triggerType: string;  
3 - entityId: string;  
4 - touchWay: string;  
5 - attributeChoose: string;  
6 - compare: string;  
7 - value: string;  
8 -}  
9 -  
10 -export interface IAddCondition {  
11 - triggerType: string;  
12 - entityId: string;  
13 - createTime: string;  
14 - updateTime: string;  
15 - compare: string;  
16 - value: string;  
17 -}  
18 -  
19 -export interface IAddAction {  
20 - outTarget: string;  
21 - deviceId: string;  
22 - command: string;  
23 - sceneLinkageId: string;  
24 -}  
1 -<template>  
2 - <div>  
3 - <BasicTable  
4 - @register="registerTable"  
5 - @selection-change="useSelectionChange"  
6 - :rowSelection="{ type: 'checkbox' }"  
7 - >  
8 - <template #toolbar>  
9 - <a-button type="primary" @click="handleAdd"> 新增场景联动 </a-button>  
10 - <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">  
11 - 批量删除  
12 - </a-button>  
13 - </template>  
14 - <template #action="{ record }">  
15 - <TableAction  
16 - :actions="[  
17 - {  
18 - label: '编辑',  
19 - icon: 'clarity:note-edit-line',  
20 - onClick: handleEdit.bind(null, record),  
21 - },  
22 - {  
23 - label: '删除',  
24 - icon: 'ant-design:delete-outlined',  
25 - color: 'error',  
26 - popConfirm: {  
27 - title: '是否确认删除',  
28 - confirm: handleDeleteOrBatchDelete.bind(null, record),  
29 - },  
30 - },  
31 - ]"  
32 - />  
33 - </template>  
34 - </BasicTable>  
35 - <SceneLinkAgeDrawer  
36 - @register="registerDrawer"  
37 - @success="handleSuccess"  
38 - ref="sceneLinkAgeDrawerRef"  
39 - />  
40 - </div>  
41 -</template>  
42 -<script lang="ts">  
43 - import { defineComponent, getCurrentInstance, ref } from 'vue';  
44 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
45 - import { useDrawer } from '/@/components/Drawer';  
46 - import SceneLinkAgeDrawer from './useDrawer.vue';  
47 - import { columns, searchFormSchema } from './config';  
48 - import { useMessage } from '/@/hooks/web/useMessage';  
49 - import { screenLinkPageGetApi, screenLinkPageDeleteApi } from '/@/api/ruleengine/ruleengineApi';  
50 - import { useBatchDelete } from '/@/hooks/web/useBatchDelete';  
51 -  
52 - export default defineComponent({  
53 - name: 'Index',  
54 - components: { BasicTable, SceneLinkAgeDrawer, TableAction },  
55 - emits: ['default', 'registerTable', 'registerDrawer', 'register'],  
56 - setup() {  
57 - const { proxy } = getCurrentInstance();  
58 - const sceneLinkAgeDrawerRef: any = ref(null);  
59 - const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(  
60 - screenLinkPageDeleteApi,  
61 - handleSuccess  
62 - );  
63 - let selectedRowKeys: Array<string> = [];  
64 - const [registerDrawer, { openDrawer }] = useDrawer();  
65 - const { createMessage } = useMessage();  
66 - const [registerTable, { reload, getSelectRowKeys }] = useTable({  
67 - title: '场景联动列表',  
68 - api: screenLinkPageGetApi,  
69 - columns,  
70 - formConfig: {  
71 - labelWidth: 120,  
72 - schemas: searchFormSchema,  
73 - },  
74 - useSearchForm: true,  
75 - showTableSetting: true,  
76 - bordered: true,  
77 - showIndexColumn: false,  
78 - actionColumn: {  
79 - width: 200,  
80 - title: '操作',  
81 - dataIndex: 'action',  
82 - slots: { customRender: 'action' },  
83 - fixed: 'right',  
84 - },  
85 - ...selectionOptions,  
86 - });  
87 -  
88 - function handleAdd() {  
89 - openDrawer(true, {  
90 - isUpdate: false,  
91 - });  
92 - try {  
93 - setTimeout(() => {  
94 - // proxy.$refs.sceneLinkAgeDrawerRef.defaultAddTrigger();  
95 - // proxy.$refs.sceneLinkAgeDrawerRef.defaultAddCondition();  
96 - proxy.$refs.sceneLinkAgeDrawerRef.defaultAddAction();  
97 - }, 50);  
98 - } catch (e) {  
99 - return e;  
100 - }  
101 - }  
102 -  
103 - const useSelectionChange = () => {  
104 - selectedRowKeys = getSelectRowKeys();  
105 - };  
106 -  
107 - async function handleToolbarDel() {  
108 - await screenLinkPageDeleteApi(selectedRowKeys);  
109 - createMessage.success('删除成功');  
110 - reload();  
111 - }  
112 -  
113 - function handleEdit(record: Recordable) {  
114 - openDrawer(true, {  
115 - record,  
116 - isUpdate: true,  
117 - });  
118 - }  
119 - async function handleDelete(record: Recordable) {  
120 - try {  
121 - let ids = [record.id];  
122 - await screenLinkPageDeleteApi(ids);  
123 - createMessage.success('删除成功');  
124 - reload();  
125 - } catch (e) {  
126 - return e;  
127 - }  
128 - }  
129 - function handleSuccess() {  
130 - reload();  
131 - }  
132 - return {  
133 - sceneLinkAgeDrawerRef,  
134 - useSelectionChange,  
135 - registerTable,  
136 - registerDrawer,  
137 - handleAdd,  
138 - handleToolbarDel,  
139 - handleEdit,  
140 - handleDelete,  
141 - handleSuccess,  
142 - hasBatchDelete,  
143 - handleDeleteOrBatchDelete,  
144 - };  
145 - },  
146 - });  
147 -</script>  
148 -  
149 -<style lang="less" scoped></style>  
1 -<template>  
2 - <BasicDrawer  
3 - v-bind="$attrs"  
4 - @register="registerDrawer"  
5 - showFooter  
6 - :title="getTitle"  
7 - width="1000px"  
8 - @ok="handleSubmit"  
9 - @close="handleClose"  
10 - >  
11 - <div>  
12 - <BasicForm @register="registerForm" />  
13 - <!-- 触发器 -->  
14 - <div style="border-radius: 4px">  
15 - <template  
16 - v-for="(item, index) in isUpdate == false ? addTriggerPushData : editTriggerPushData"  
17 - :key="index"  
18 - >  
19 - <span style="display: none">{{ item + index }}</span>  
20 - <span style="position: relative; top: 3.2vh; left: 0.5vw">触发器 {{ index + 1 }}</span>  
21 - <div style="display: block">  
22 - <AddTriggerForm  
23 - ref="refTriggerChild"  
24 - :editTriggerFather="isUpdate == false ? 1 : item"  
25 - :newFilterMapFather="isUpdate == false ? 1 : newFilterMap"  
26 - :deviceInfo="getDeviceInfo"  
27 - />  
28 - </div>  
29 - <div style="height: 3vh"></div>  
30 - </template>  
31 - <div  
32 - style="  
33 - display: flex;  
34 - width: 11vw;  
35 - height: 4vh;  
36 - flex-direction: row;  
37 - justify-content: space-between;  
38 - "  
39 - >  
40 - <div style="display: flex; width: 4vw; height: 4vh">  
41 - <Button type="primary" style="border-radius: 2px" class="mt-5" @click="addTrigger"  
42 - >新增触发器</Button  
43 - >  
44 - </div>  
45 - <div style="display: flex; width: 4vw; height: 4vh">  
46 - <Button  
47 - v-if="addTriggerPushData.length != 0 || editTriggerPushData.length != 0"  
48 - type="default"  
49 - style="border-radius: 2px; background-color: rgba(237, 111, 111, 1)"  
50 - class="mt-5"  
51 - @click="removeTrigger"  
52 - >  
53 - <span style="color: white">删除</span></Button  
54 - >  
55 - </div>  
56 - </div>  
57 - </div>  
58 - <div style="height: 5vh"></div>  
59 - <!-- 执行条件 -->  
60 - <div style="border-radius: 4px" class="condition-style">  
61 - <template  
62 - v-for="(item, index) in isUpdate == false ? addConditionPushData : editConditionPushData"  
63 - :key="index"  
64 - >  
65 - <span style="display: none">{{ item + index }}</span>  
66 - <span style="position: relative; top: 3.2vh; left: 0.5vw">执行条件 {{ index + 1 }}</span>  
67 -  
68 - <div>  
69 - <AddConditiForm  
70 - :editConditionFather="isUpdate == false ? 1 : item"  
71 - :newConditionMapFather="isUpdate == false ? 1 : newConditionFilterMap"  
72 - :deviceInfo1="getDeviceInfo1"  
73 - ref="refConditionChild"  
74 - />  
75 - </div>  
76 - <div style="height: 3vh"></div>  
77 - </template>  
78 - <div  
79 - style="  
80 - display: flex;  
81 - width: 11vw;  
82 - height: 4vh;  
83 - flex-direction: row;  
84 - justify-content: space-between;  
85 - "  
86 - >  
87 - <div style="display: flex; width: 4vw; height: 4vh">  
88 - <Button type="primary" style="border-radius: 2px" class="mt-5" @click="addCondition"  
89 - >新增执行条件</Button  
90 - >  
91 - </div>  
92 - <div style="display: flex; width: 4vw; height: 4vh">  
93 - <Button  
94 - v-if="addConditionPushData.length != 0 || editConditionPushData.length != 0"  
95 - style="border-radius: 2px; background-color: rgba(237, 111, 111, 1)"  
96 - type="default"  
97 - class="mt-5"  
98 - @click="removeCondition"  
99 - >  
100 - <span style="color: white">删除</span></Button  
101 - >  
102 - </div>  
103 - </div>  
104 - </div>  
105 - <!-- 执行动作 -->  
106 - <div style="height: 5vh"></div>  
107 - <div style="border-radius: 4px">  
108 - <template  
109 - v-for="(item, index) in isUpdate == false ? addActionPushData : editActionPushData"  
110 - :key="index"  
111 - >  
112 - <span style="display: none">{{ item + index }}</span>  
113 - <span style="position: relative; top: 4.2vh; left: 0.65vw">执行动作 {{ index + 1 }}</span>  
114 -  
115 - <div>  
116 - <AddActionForm  
117 - :editActionFather="isUpdate == false ? 1 : item"  
118 - :newActionMapFather="isUpdate == false ? 1 : newActionFilterMap"  
119 - :deviceInfo2="getDeviceInfo2"  
120 - ref="refActionChild"  
121 - />  
122 - </div>  
123 - <div style="height: 3vh"></div>  
124 - </template>  
125 - <div  
126 - style="  
127 - display: flex;  
128 - width: 11vw;  
129 - height: 4vh;  
130 - flex-direction: row;  
131 - justify-content: space-between;  
132 - "  
133 - >  
134 - <div style="display: flex; width: 4vw; height: 4vh">  
135 - <Button type="primary" style="border-radius: 2px" class="mt-5" @click="addAction"  
136 - >新增执行动作</Button  
137 - >  
138 - </div>  
139 - <div style="display: flex; width: 4vw; height: 4vh">  
140 - <Button  
141 - v-if="addActionPushData.length !== 0 || editActionPushData.length !== 0"  
142 - style="border-radius: 2px; background-color: rgba(237, 111, 111, 1)"  
143 - type="default"  
144 - class="mt-5"  
145 - @click="removeAction"  
146 - >  
147 - <span style="color: white">删除</span></Button  
148 - >  
149 - </div>  
150 - </div>  
151 - <div style="height: 5vh"></div>  
152 - </div>  
153 - </div>  
154 - </BasicDrawer>  
155 -</template>  
156 -<script lang="ts">  
157 - import { defineComponent, ref, computed, unref, reactive, getCurrentInstance, watch } from 'vue';  
158 - import { BasicForm, useForm } from '/@/components/Form';  
159 - import { formSchema, getData } from './config';  
160 - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';  
161 - import {  
162 - screenLinkPageAddApi,  
163 - screenLinkPageUpdateApi,  
164 - screenLinkPageByDeptIdGetDevice,  
165 - } from '/@/api/ruleengine/ruleengineApi';  
166 - import { useMessage } from '/@/hooks/web/useMessage';  
167 - import AddTriggerForm from './addForm/trigger.vue';  
168 - import AddConditiForm from './addForm/condition.vue';  
169 - import AddActionForm from './addForm/doaction.vue';  
170 - import { IAddTrigger } from './index';  
171 - import { Button } from '/@/components/Button';  
172 -  
173 - export default defineComponent({  
174 - name: 'ConfigDrawer',  
175 - components: {  
176 - BasicDrawer,  
177 - BasicForm,  
178 - AddTriggerForm,  
179 - AddConditiForm,  
180 - AddActionForm,  
181 - Button,  
182 - },  
183 - emits: ['success', 'register', 'registerForm'],  
184 - setup(_, { emit }) {  
185 - const { proxy } = getCurrentInstance();  
186 - const lastEditRefTriggerChildDataArray = ref<[]>([]);  
187 - const lastRefTriggerChildDataArray = ref<[]>([]);  
188 - const lastRefConditionChildDataArray = ref<[]>([]);  
189 - const lastRefActionChildDataArray = ref<[]>([]);  
190 - let refTriggerChildData: any = reactive({});  
191 - let refConditionChildData: any = reactive({});  
192 - let refActionChildData: any = reactive({});  
193 - const addTriggerData = reactive<IAddTrigger>({  
194 - triggerType: '',  
195 - entityId: '',  
196 - touchWay: '',  
197 - attributeChoose: '',  
198 - compare: '',  
199 - value: '',  
200 - });  
201 - const addTriggerPushData = ref<[]>([]);  
202 - const addConditionPushData = ref<[]>([]);  
203 - const addActionPushData = ref<[]>([]);  
204 - //edit data  
205 - const editTriggerPushData = ref<[]>([]);  
206 - const editConditionPushData = ref<[]>([]);  
207 - const editActionPushData = ref<[]>([]);  
208 - const getChildData = ref(null);  
209 - const refTriggerChild = ref(null);  
210 - const refConditionChild = ref(null);  
211 - const refActionChild = ref(null);  
212 - const getConditionChildData = ref(null);  
213 - const { createMessage } = useMessage();  
214 - const isUpdate = ref(true);  
215 - let getAllFormData: any = reactive({});  
216 - let getValuesFormData: any = reactive({});  
217 - const getId = ref('');  
218 - const getTenantId = ref('');  
219 - const getDeviceInfo = ref(null);  
220 - const getDeviceInfo1 = ref(null);  
221 - const getDeviceInfo2 = ref(null);  
222 - const newFilterMap = ref<[]>([]);  
223 - const newConditionFilterMap = ref<[]>([]);  
224 - const newActionFilterMap = ref<[]>([]);  
225 - let filterNewConditionArr = [];  
226 - const pushEditArray = ref<any>([{}]);  
227 - const pushEditConditionArray = ref<any>([{}]);  
228 - const pushEditActionArray = ref<any>([{}]);  
229 - let filterArrayTrigger = [];  
230 - const filterArrayCondition = ref<[]>([]);  
231 - const filterArrayAction = ref<[]>([]);  
232 - let filterNewTriggerArr = [];  
233 - let triggersObj = {  
234 - triggers: [],  
235 - };  
236 - let conditionsObj = {  
237 - doConditions: [],  
238 - };  
239 - let actionsObj = {  
240 - doActions: [],  
241 - };  
242 - let optionsItemArray = ref<[]>([]);  
243 - const isNoChange = ref(false);  
244 - let kongTriggerObj = {};  
245 - let kongConditionObj = {};  
246 - let kongActionObj = {};  
247 -  
248 - const [registerForm, { resetFields, setFieldsValue, validateFields }] = useForm({  
249 - labelWidth: 120,  
250 - schemas: formSchema,  
251 - showActionButtonGroup: false,  
252 - });  
253 - const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {  
254 - await resetFields();  
255 - setDrawerProps({ confirmLoading: false });  
256 - isUpdate.value = !!data?.isUpdate;  
257 - if (!unref(isUpdate)) {  
258 - try {  
259 - refTriggerChildData = {};  
260 - refConditionChildData = {};  
261 - refActionChildData = {};  
262 - getAllFormData = {};  
263 - triggersObj = {  
264 - triggers: [],  
265 - };  
266 - conditionsObj = {  
267 - doConditions: [],  
268 - };  
269 - actionsObj = {  
270 - doActions: [],  
271 - };  
272 - filterNewTriggerArr.length = 0;  
273 - filterNewConditionArr.length = 0;  
274 - lastRefTriggerChildDataArray.value.length = 0;  
275 - lastRefConditionChildDataArray.value.length = 0;  
276 - lastRefActionChildDataArray.value.length = 0;  
277 - editTriggerPushData.value.length = 0;  
278 - editConditionPushData.value.length = 0;  
279 - editActionPushData.value.length = 0;  
280 - addTriggerPushData.value.length = 0;  
281 - addConditionPushData.value.length = 0;  
282 - addActionPushData.value.length = 0;  
283 - handleClose();  
284 - optionsItemArray.value.length = 0;  
285 - try {  
286 - setTimeout(() => {  
287 - proxy.$refs.refTriggerChild.resetFieldsValueFunc();  
288 - proxy.$refs.refTriggerChild.clearSelectDevice();  
289 - proxy.$refs.refConditionChild.resetFieldsValueFunc();  
290 - proxy.$refs.refConditionChild.clearSelectDevice();  
291 - proxy.$refs.refActionChild.resetFieldsValueFunc();  
292 - proxy.$refs.refActionChild.clearSelectDevice();  
293 - clearActionsAllDevice();  
294 - resetActionsAllArrayFunc();  
295 - }, 10);  
296 - } catch (e) {  
297 - return e;  
298 - }  
299 - } catch (e) {  
300 - return e;  
301 - }  
302 - } else {  
303 - try {  
304 - emit('success');  
305 - kongTriggerObj = {};  
306 - kongConditionObj = {};  
307 - kongActionObj = {};  
308 - pushEditArray.value = [];  
309 - pushEditArray.value.length = 0;  
310 - pushEditConditionArray.value.length = 0;  
311 - pushEditConditionArray.value = [];  
312 - pushEditActionArray.value = [];  
313 - pushEditActionArray.value.length = 0;  
314 - newFilterMap.value = [];  
315 - newConditionFilterMap.value = [];  
316 - newActionFilterMap.value = [];  
317 - clearAllArrayFunc();  
318 - editTriggerPushData.value = [];  
319 - editTriggerPushData.value.length = 0;  
320 - editConditionPushData.value = [];  
321 - editConditionPushData.value.length = 0;  
322 - editActionPushData.value = [];  
323 - editActionPushData.value.length = 0;  
324 - lastEditRefTriggerChildDataArray.value = [];  
325 - getId.value = data.record.id;  
326 - getTenantId.value = data.record.tenantId;  
327 - await setFieldsValue({  
328 - ...data.record,  
329 - });  
330 - editTriggerPushData.value = data.record.triggers;  
331 - isNoChange.value = true;  
332 - editConditionPushData.value = data.record.doConditions;  
333 - editActionPushData.value = data.record.doActions;  
334 - const options = await screenLinkPageByDeptIdGetDevice({  
335 - organizationId: data.record.organizationId,  
336 - });  
337 - data.record.triggers.forEach((f1) => {  
338 - options.items?.forEach((f2) => {  
339 - if (f2.tbDeviceId == f1.entityId) {  
340 - newFilterMap.value.push({  
341 - value: f2.tbDeviceId,  
342 - label: f2.name,  
343 - });  
344 - }  
345 - });  
346 - });  
347 - data.record.doConditions.forEach((f1) => {  
348 - options.items?.forEach((f2) => {  
349 - if (f2.tbDeviceId == f1.entityId) {  
350 - newConditionFilterMap.value.push({  
351 - value: f2.tbDeviceId,  
352 - label: f2.name,  
353 - });  
354 - }  
355 - });  
356 - });  
357 - data.record.doActions.forEach((f1) => {  
358 - options.items?.forEach((f2) => {  
359 - if (f2.tbDeviceId == f1.deviceId) {  
360 - newActionFilterMap.value.push({  
361 - value: f2.tbDeviceId,  
362 - label: f2.name,  
363 - });  
364 - }  
365 - });  
366 - });  
367 - } catch (e) {  
368 - return e;  
369 - }  
370 - }  
371 - });  
372 - const getTitle = computed(() => (!unref(isUpdate) ? '新增场景联动' : '编辑场景联动'));  
373 - const handleClose = () => {  
374 - pushEditArray.value.length = 0;  
375 - pushEditConditionArray.value.length = 0;  
376 - pushEditActionArray.value.length = 0;  
377 - lastRefTriggerChildDataArray.value.length = 0;  
378 - lastRefTriggerChildDataArray.value = [];  
379 - lastRefConditionChildDataArray.value.length = 0;  
380 - lastRefActionChildDataArray.value.length = 0;  
381 - lastRefActionChildDataArray.value = [];  
382 - filterArrayTrigger.length = 0;  
383 - filterArrayCondition.value.length = 0;  
384 - filterArrayAction.value.length = 0;  
385 - };  
386 -  
387 - const clearAllArrayFunc = () => {  
388 - unref(addTriggerPushData).length = 0;  
389 - unref(addConditionPushData).length = 0;  
390 - unref(addActionPushData).length = 0;  
391 - lastRefTriggerChildDataArray.value.length = 0;  
392 - lastRefConditionChildDataArray.value.length = 0;  
393 - lastRefActionChildDataArray.value.length = 0;  
394 - lastEditRefTriggerChildDataArray.value.length = 0;  
395 - };  
396 - const resetActionsAllArrayFunc = () => {  
397 - try {  
398 - proxy.$refs.refActionChild.resetFieldsValueFunc();  
399 - } catch (e) {  
400 - return e;  
401 - }  
402 - };  
403 - const clearActionsAllDevice = () => {  
404 - try {  
405 - proxy.$refs.refActionChild.clearSelectDevice();  
406 - } catch (e) {  
407 - return e;  
408 - }  
409 - };  
410 - watch(getData, async (newV) => {  
411 - const options = await screenLinkPageByDeptIdGetDevice({ organizationId: newV });  
412 - options.items.forEach((v) => {  
413 - return (v.value = v.tbDeviceId), (v.label = v.name);  
414 - });  
415 - optionsItemArray.value = options.items;  
416 - updateDeviceIdFunc(optionsItemArray.value);  
417 - try {  
418 - proxy.$refs.refActionChild.updateFieldDeviceId(optionsItemArray.value);  
419 - } catch (e) {  
420 - return e;  
421 - }  
422 - });  
423 -  
424 - const updateDeviceIdFunc = (v) => {  
425 - try {  
426 - proxy.$refs.refTriggerChild.updateFieldDeviceId(v);  
427 - proxy.$refs.refConditionChild.updateFieldDeviceId(v);  
428 - proxy.$refs.refActionChild.updateFieldDeviceId(v);  
429 - } catch (e) {  
430 - return e;  
431 - }  
432 - };  
433 -  
434 - //获取触发器方法  
435 - const refTriggerChildDataFunc = () => {  
436 - try {  
437 - refTriggerChildData = proxy.$refs.refTriggerChild.getFieldsValueFunc();  
438 - } catch (e) {  
439 - return e;  
440 - }  
441 - };  
442 - //获取执行条件方法  
443 - const refConditionChildDataFunc = () => {  
444 - try {  
445 - refConditionChildData = proxy.$refs.refConditionChild.getFieldsValueFunc();  
446 - } catch (e) {  
447 - return e;  
448 - }  
449 - };  
450 - //获取执行动作方法  
451 - const refActionChildDataFunc = () => {  
452 - try {  
453 - refActionChildData = proxy.$refs.refActionChild.getFieldsValueFunc();  
454 - } catch (e) {  
455 - return e;  
456 - }  
457 - };  
458 -  
459 - const getDefaultValue = () => {  
460 - if (!unref(isUpdate)) {  
461 - refTriggerChildDataFunc();  
462 - refConditionChildDataFunc();  
463 - refActionChildDataFunc();  
464 - let newTriggerArray = addTriggerPushData.value.concat(refTriggerChildData);  
465 - let newConditionArray = addConditionPushData.value.concat(refConditionChildData);  
466 - let newActionArray = addActionPushData.value.concat(refActionChildData);  
467 - newTriggerArray = newTriggerArray.map((m) => {  
468 - return {  
469 - triggerType: m?.triggerType,  
470 - entityId: m?.entityId || m?.entityId1 || m?.entityId2,  
471 - triggerCondition: {  
472 - condition: [  
473 - {  
474 - key: {  
475 - key: m.key1 == null ? 'CO2' : m.key1,  
476 - type: m.type1 == null ? 'TIME_SERIES' : m.type1,  
477 - },  
478 - valueType: m.type2 == null ? 'NUMERIC' : m.type2,  
479 - value: {},  
480 - predicate: {  
481 - type: m.type2 == null ? 'NUMERIC' : m.type2,  
482 - value: {  
483 - defaultValue: Number(m.value) == null ? 0 : Number(m.value),  
484 - },  
485 - operation: m.operation == null ? 'GREATER_OR_EQUAL' : m.operation,  
486 - },  
487 - },  
488 - ],  
489 - spec: {  
490 - type: 'SIMPLE',  
491 - },  
492 - },  
493 - };  
494 - });  
495 - newConditionArray = newConditionArray.map((m) => {  
496 - return {  
497 - triggerType: m?.triggerType,  
498 - entityId: m?.entityId,  
499 - triggerCondition: {  
500 - condition: [  
501 - {  
502 - key: {  
503 - type: 'TIME_SERIES',  
504 - key: 'CO2',  
505 - },  
506 - valueType:  
507 - m.type == 'NUMERIC1'  
508 - ? 'NUMERIC'  
509 - : m.type == 'NUMERIC2'  
510 - ? 'NUMERIC'  
511 - : 'NUMERIC',  
512 - value: {},  
513 - predicate: {  
514 - type:  
515 - m.type == 'NUMERIC1'  
516 - ? 'NUMERIC'  
517 - : m.type == 'NUMERIC2'  
518 - ? 'NUMERIC'  
519 - : 'NUMERIC',  
520 - value: {  
521 - defaultValue:  
522 - Number(m.value1) == null  
523 - ? 0  
524 - : Number(m.value1) || Number(m.value2) == null  
525 - ? 0  
526 - : Number(m.value2),  
527 - },  
528 - operation: m.operation1 || m.operatio2,  
529 - },  
530 - },  
531 - ],  
532 - spec: {  
533 - type: 'SIMPLE',  
534 - },  
535 - },  
536 - };  
537 - });  
538 - newTriggerArray.shift();  
539 - newConditionArray.shift();  
540 - newActionArray.shift();  
541 - delete getAllFormData.id;  
542 - delete getAllFormData.getTenantId;  
543 - triggersObj = {  
544 - triggers: newTriggerArray,  
545 - };  
546 - conditionsObj = {  
547 - doConditions: newConditionArray,  
548 - };  
549 - actionsObj = {  
550 - doActions: newActionArray,  
551 - };  
552 - Object.assign(getAllFormData, triggersObj, conditionsObj, actionsObj);  
553 - } else {  
554 - editTriggerPushData.value.forEach((f) => {  
555 - kongTriggerObj = f;  
556 - pushEditArray.value.push(kongTriggerObj);  
557 - });  
558 - editConditionPushData.value.forEach((f) => {  
559 - kongConditionObj = f;  
560 - pushEditConditionArray.value.push(kongConditionObj);  
561 - });  
562 - editActionPushData.value.forEach((f) => {  
563 - kongActionObj = f;  
564 - pushEditActionArray.value.push(kongActionObj);  
565 - });  
566 - refTriggerChildDataFunc();  
567 - let newTriggerArray = pushEditArray.value.concat(refTriggerChildData);  
568 - newTriggerArray = newTriggerArray.filter((f) => Object.keys(f).length !== 0);  
569 - newTriggerArray.shift();  
570 - triggersObj = {  
571 - triggers: isNoChange.value ? editTriggerPushData.value : newTriggerArray,  
572 - };  
573 - refConditionChildDataFunc();  
574 - let newConditionArray = pushEditConditionArray.value.concat(refConditionChildData);  
575 - newConditionArray = newConditionArray.filter((f) => Object.keys(f).length !== 0);  
576 - newConditionArray.shift();  
577 - conditionsObj = {  
578 - doConditions: newConditionArray,  
579 - };  
580 - refActionChildDataFunc();  
581 - let newActionArray = pushEditActionArray.value.concat(refActionChildData);  
582 - newActionArray = newActionArray.filter((f) => Object.keys(f).length !== 0);  
583 - newActionArray.shift();  
584 - actionsObj = {  
585 - doActions: newActionArray,  
586 - };  
587 - Object.assign(getAllFormData, triggersObj, conditionsObj, actionsObj);  
588 - }  
589 - };  
590 -  
591 - const handleSubmit = async () => {  
592 - if (!unref(isUpdate)) {  
593 - getDefaultValue();  
594 - getValuesFormData = await validateFields();  
595 - if (!getValuesFormData) return;  
596 - let isKongNum = 0;  
597 - getAllFormData.doActions.forEach((f) => {  
598 - isKongNum = Object.keys(f).length;  
599 - });  
600 -  
601 - if (getAllFormData.doActions.length == 1 && isKongNum == 0)  
602 - return createMessage.error('请填写执行动作');  
603 - Object.assign(getAllFormData, getValuesFormData);  
604 - await screenLinkPageAddApi(getAllFormData);  
605 - createMessage.success('场景联动新增成功');  
606 - closeDrawer();  
607 - emit('success');  
608 - } else {  
609 - getDefaultValue();  
610 - getValuesFormData = await validateFields();  
611 - Object.assign(getAllFormData, getValuesFormData);  
612 - getAllFormData.id = getId.value;  
613 - getAllFormData.tenantId = getTenantId.value;  
614 - refTriggerChildData = {};  
615 - pushEditArray.value.length = 0;  
616 - pushEditConditionArray.value.length = 0;  
617 - pushEditActionArray.value.length = 0;  
618 - await screenLinkPageUpdateApi(getAllFormData);  
619 - createMessage.success('场景联动编辑成功');  
620 - closeDrawer();  
621 - emit('success');  
622 - }  
623 - };  
624 - //新增触发器  
625 - const addTrigger = () => {  
626 - if (!unref(isUpdate)) {  
627 - refTriggerChildDataFunc();  
628 - unref(addTriggerPushData).push(refTriggerChildData as never);  
629 - addTriggerPushData.value = addTriggerPushData.value.map((m) => {  
630 - return {  
631 - triggerType: m?.triggerType,  
632 - entityId: m?.entityId || m?.entityId1 || m?.entityId2,  
633 - triggerCondition: {  
634 - condition: [  
635 - {  
636 - key: {  
637 - key: m.key1 == null ? 'CO2' : m.key1,  
638 - type: m.type1 == null ? 'TIME_SERIES' : m.type1,  
639 - },  
640 - valueType: m.type2 == null ? 'NUMERIC' : m.type2,  
641 - value: {},  
642 - predicate: {  
643 - type: m.type2 == null ? 'NUMERIC' : m.type2,  
644 - value: {  
645 - defaultValue: Number(m.value) == null ? 0 : Number(m.value),  
646 - },  
647 - operation: m.operation == null ? 'GREATER_OR_EQUAL' : m.operation,  
648 - },  
649 - },  
650 - ],  
651 - spec: {  
652 - type: 'SIMPLE',  
653 - },  
654 - },  
655 - };  
656 - });  
657 - try {  
658 - setTimeout(() => {  
659 - proxy.$refs.refTriggerChild.updateFieldDeviceId(optionsItemArray.value);  
660 - }, 50);  
661 - } catch (e) {  
662 - return e;  
663 - }  
664 - } else {  
665 - isNoChange.value = false;  
666 - unref(editTriggerPushData).push(refTriggerChildData as never);  
667 - refTriggerChildDataFunc();  
668 - pushEditArray.value.push(refTriggerChildData);  
669 - pushEditArray.value = pushEditArray.value.map((m) => {  
670 - return {  
671 - triggerType: m?.triggerType,  
672 - entityId: m?.entityId || m?.entityId1 || m?.entityId2,  
673 - triggerCondition: {  
674 - condition: [  
675 - {  
676 - key: {  
677 - key: m.key1 == null ? 'CO2' : m.key1,  
678 - type: m.type1 == null ? 'TIME_SERIES' : m.type1,  
679 - },  
680 - valueType: m.type2 == null ? 'NUMERIC' : m.type2,  
681 - value: {},  
682 - predicate: {  
683 - type: m.type2 == null ? 'NUMERIC' : m.type2,  
684 - value: {  
685 - defaultValue: Number(m.value) == null ? 0 : Number(m.value),  
686 - },  
687 - operation: m.operation == null ? 'GREATER_OR_EQUAL' : m.operation,  
688 - },  
689 - },  
690 - ],  
691 - spec: {  
692 - type: 'SIMPLE',  
693 - },  
694 - },  
695 - };  
696 - });  
697 - try {  
698 - setTimeout(() => {  
699 - proxy.$refs.refTriggerChild.updateFieldDeviceId(optionsItemArray.value);  
700 - }, 50);  
701 - } catch (e) {  
702 - return e;  
703 - }  
704 - refTriggerChildData = {};  
705 - }  
706 - };  
707 - const removeTrigger = () => {  
708 - if (!unref(isUpdate)) {  
709 - try {  
710 - unref(addTriggerPushData).pop();  
711 - } catch (e) {  
712 - return e;  
713 - }  
714 - } else {  
715 - try {  
716 - unref(editTriggerPushData).pop();  
717 - } catch (e) {  
718 - return e;  
719 - }  
720 - }  
721 - };  
722 -  
723 - //新增执行条件  
724 - const addCondition = () => {  
725 - if (!unref(isUpdate)) {  
726 - refConditionChildDataFunc();  
727 - unref(addConditionPushData).push(refConditionChildData as never);  
728 - addConditionPushData.value = addConditionPushData.value.map((m) => {  
729 - return {  
730 - triggerType: m?.triggerType,  
731 - entityId: m?.entityId,  
732 - triggerCondition: {  
733 - condition: [  
734 - {  
735 - key: {  
736 - type: 'TIME_SERIES',  
737 - key: 'CO2',  
738 - },  
739 - valueType:  
740 - m.type == 'NUMERIC1'  
741 - ? 'NUMERIC'  
742 - : m.type == 'NUMERIC2'  
743 - ? 'NUMERIC'  
744 - : 'NUMERIC',  
745 - value: {},  
746 - predicate: {  
747 - type:  
748 - m.type == 'NUMERIC1'  
749 - ? 'NUMERIC'  
750 - : m.type == 'NUMERIC2'  
751 - ? 'NUMERIC'  
752 - : 'NUMERIC',  
753 - value: {  
754 - defaultValue:  
755 - Number(m.value1) == null  
756 - ? 0  
757 - : Number(m.value1) || Number(m.value2) == null  
758 - ? 0  
759 - : Number(m.value2),  
760 - },  
761 - operation: m.operation1 || m.operatio2,  
762 - },  
763 - },  
764 - ],  
765 - spec: {  
766 - type: 'SIMPLE',  
767 - },  
768 - },  
769 - };  
770 - });  
771 - try {  
772 - setTimeout(() => {  
773 - proxy.$refs.refConditionChild.updateFieldDeviceId(optionsItemArray.value);  
774 - }, 50);  
775 - } catch (e) {  
776 - return e;  
777 - }  
778 - } else {  
779 - isNoChange.value = false;  
780 - unref(editConditionPushData).push(refConditionChildData as never);  
781 - refConditionChildDataFunc();  
782 - pushEditConditionArray.value.push(refConditionChildData);  
783 - pushEditConditionArray.value = pushEditConditionArray.value.map((m) => {  
784 - return {  
785 - triggerType: m?.triggerType,  
786 - entityId: m?.entityId,  
787 - triggerCondition: {  
788 - condition: [  
789 - {  
790 - key: {  
791 - type: 'TIME_SERIES',  
792 - key: 'CO2',  
793 - },  
794 - valueType:  
795 - m.type == 'NUMERIC1'  
796 - ? 'NUMERIC'  
797 - : m.type == 'NUMERIC2'  
798 - ? 'NUMERIC'  
799 - : 'NUMERIC',  
800 - value: {},  
801 - predicate: {  
802 - type:  
803 - m.type == 'NUMERIC1'  
804 - ? 'NUMERIC'  
805 - : m.type == 'NUMERIC2'  
806 - ? 'NUMERIC'  
807 - : 'NUMERIC',  
808 - value: {  
809 - defaultValue:  
810 - Number(m.value1) == null  
811 - ? 0  
812 - : Number(m.value1) || Number(m.value2) == null  
813 - ? 0  
814 - : Number(m.value2),  
815 - },  
816 - operation: m.operation1 || m.operatio2,  
817 - },  
818 - },  
819 - ],  
820 - spec: {  
821 - type: 'SIMPLE',  
822 - },  
823 - },  
824 - };  
825 - });  
826 - try {  
827 - setTimeout(() => {  
828 - proxy.$refs.refConditionChild.updateFieldDeviceId(optionsItemArray.value);  
829 - }, 50);  
830 - } catch (e) {  
831 - return e;  
832 - }  
833 - refConditionChildData = {};  
834 - }  
835 - };  
836 - const removeCondition = () => {  
837 - if (!unref(isUpdate)) {  
838 - try {  
839 - unref(addConditionPushData).pop();  
840 - } catch (e) {  
841 - return e;  
842 - }  
843 - } else {  
844 - try {  
845 - unref(editConditionPushData).pop();  
846 - } catch (e) {  
847 - return e;  
848 - }  
849 - }  
850 - };  
851 -  
852 - //默认新增执行动作  
853 - const defaultAddAction = () => {  
854 - if (unref(addActionPushData).length == 0) {  
855 - addAction();  
856 - }  
857 - };  
858 - //新增执行动作  
859 - const addAction = () => {  
860 - if (!unref(isUpdate)) {  
861 - refActionChildDataFunc();  
862 - unref(addActionPushData).push(refActionChildData as never);  
863 - try {  
864 - setTimeout(() => {  
865 - proxy.$refs.refActionChild.updateFieldDeviceId(optionsItemArray.value);  
866 - }, 50);  
867 - } catch (e) {  
868 - return e;  
869 - }  
870 - } else {  
871 - isNoChange.value = false;  
872 - unref(editActionPushData).push(refActionChildData as never);  
873 - refActionChildDataFunc();  
874 - pushEditActionArray.value.push(refActionChildData);  
875 - try {  
876 - setTimeout(() => {  
877 - proxy.$refs.refActionChild.updateFieldDeviceId(optionsItemArray.value);  
878 - }, 50);  
879 - } catch (e) {  
880 - return e;  
881 - }  
882 - refActionChildData = {};  
883 - }  
884 - };  
885 - const removeAction = () => {  
886 - if (!unref(isUpdate)) {  
887 - try {  
888 - unref(addActionPushData).pop();  
889 - } catch (e) {  
890 - return e;  
891 - }  
892 - } else {  
893 - try {  
894 - unref(editActionPushData).pop();  
895 - } catch (e) {  
896 - return e;  
897 - }  
898 - }  
899 - };  
900 -  
901 - return {  
902 - updateDeviceIdFunc,  
903 - handleClose,  
904 - newFilterMap,  
905 - newConditionFilterMap,  
906 - newActionFilterMap,  
907 - editTriggerPushData,  
908 - editConditionPushData,  
909 - editActionPushData,  
910 - isUpdate,  
911 - clearActionsAllDevice,  
912 - getDeviceInfo,  
913 - getDeviceInfo1,  
914 - getDeviceInfo2,  
915 - resetActionsAllArrayFunc,  
916 - addActionPushData,  
917 - defaultAddAction,  
918 - refActionChild,  
919 - addAction,  
920 - removeAction,  
921 - addConditionPushData,  
922 - refConditionChild,  
923 - addCondition,  
924 - removeCondition,  
925 - clearAllArrayFunc,  
926 - removeTrigger,  
927 - addTriggerPushData,  
928 - addTriggerData,  
929 - addTrigger,  
930 - getConditionChildData,  
931 - refTriggerChild,  
932 - getChildData,  
933 - getAllFormData,  
934 - registerDrawer,  
935 - registerForm,  
936 - getTitle,  
937 - handleSubmit,  
938 - };  
939 - },  
940 - });  
941 -</script>  
942 -  
943 -<style lang="less" scoped>  
944 - .condition-style {  
945 - :deep .ant-calendar-picker {  
946 - width: 24.9vw !important;  
947 - }  
948 - }  
949 -</style>  
1 -<template>  
2 - <div>  
3 - <BasicModal  
4 - v-bind="$attrs"  
5 - @register="registerModal"  
6 - :showFooter="false"  
7 - :title="dataSource?.sysNotice?.title"  
8 - width="50%"  
9 - centered  
10 - :showCancelBtn="false"  
11 - :showOkBtn="false"  
12 - @cancel="handleClose"  
13 - >  
14 - <PageWrapper dense contentFullHeight contentBackground>  
15 - <div class="detail-notice-info">  
16 - <span class="mr-6"  
17 - ><UserOutlined class="mr-2" />发送者:{{ dataSource?.user?.realName }}</span  
18 - >  
19 - <span class="mr-6"  
20 - ><SolutionOutlined class="mr-2" />通知类型:{{  
21 - dataSource?.sysNotice?.type === 'NOTICE'  
22 - ? '公告'  
23 - : dataSource?.sysNotice?.type === 'MEETING'  
24 - ? '会议'  
25 - : dataSource?.sysNotice?.type === 'OTHER'  
26 - ? '其他'  
27 - : ''  
28 - }}</span  
29 - >  
30 - <span class="mr-6"  
31 - ><FieldTimeOutlined class="mr-2" />发送时间{{ dataSource?.sysNotice.senderDate }}</span  
32 - >  
33 - </div>  
34 - <!--eslint-disable-next-line vue/no-v-html-->  
35 - <p v-html="dataSource?.sysNotice?.content"></p>  
36 - </PageWrapper>  
37 - </BasicModal>  
38 - </div>  
39 -</template>  
40 -<script lang="ts">  
41 - import { defineComponent, ref, unref } from 'vue';  
42 - import { BasicModal, useModalInner } from '/@/components/Modal';  
43 - import { UserOutlined, SolutionOutlined, FieldTimeOutlined } from '@ant-design/icons-vue';  
44 - import { PageWrapper } from '/@/components/Page';  
45 - import { notifyMyGetDetailApi } from '/@/api/stationnotification/stationnotifyApi';  
46 - export default defineComponent({  
47 - name: 'MyNoticeDrawer',  
48 - components: { BasicModal, PageWrapper, UserOutlined, SolutionOutlined, FieldTimeOutlined },  
49 - emits: ['success', 'register'],  
50 - setup(_, { emit }) {  
51 - const dataSource = ref();  
52 - const [registerModal] = useModalInner(async (data) => {  
53 - dataSource.value = data.record;  
54 - });  
55 - const handleClose = async () => {  
56 - // 如果已读,就不刷新表格了  
57 - if (unref(dataSource).readStatus === '1') return;  
58 - await notifyMyGetDetailApi(unref(dataSource).id);  
59 - emit('success');  
60 - };  
61 - return {  
62 - registerModal,  
63 - handleClose,  
64 - dataSource,  
65 - };  
66 - },  
67 - });  
68 -</script>  
69 -  
70 -<style lang="less" scoped>  
71 - .detail-notice-info {  
72 - color: #999;  
73 - border-top: 1px solid #ccc;  
74 - border-bottom: 1px solid #ccc;  
75 - padding-top: 5px;  
76 - padding-bottom: 5px;  
77 - }  
78 -</style>  
1 -import { BasicColumn, FormSchema } from '/@/components/Table';  
2 -import { Tag } from 'ant-design-vue';  
3 -import { DescItem } from '/@/components/Description/index';  
4 -  
5 -import { h } from 'vue';  
6 -  
7 -export const columns: BasicColumn[] = [  
8 - {  
9 - title: '标题',  
10 - dataIndex: 'sysNotice.title',  
11 - width: 200,  
12 - },  
13 - {  
14 - title: '类型',  
15 - dataIndex: 'type',  
16 - width: 200,  
17 - format: (text: string, record: Recordable) => {  
18 - return record.sysNotice.type === 'NOTICE'  
19 - ? '公告'  
20 - : record.sysNotice.type === 'MEETING'  
21 - ? '会议'  
22 - : record.sysNotice.type === 'OTHER'  
23 - ? '其他'  
24 - : '无';  
25 - },  
26 - },  
27 - {  
28 - title: '发送者',  
29 - dataIndex: 'sysNotice.senderName',  
30 - width: 200,  
31 - },  
32 - {  
33 - title: '发送时间',  
34 - dataIndex: 'sysNotice.senderDate',  
35 - width: 200,  
36 - },  
37 - {  
38 - title: '阅读状态',  
39 - dataIndex: 'readStatus',  
40 - width: 200,  
41 - customRender: ({ record }) => {  
42 - const status = record.readStatus;  
43 - const enable = status == 0 ? '未读' : status == 1 ? '已读' : '其他';  
44 - const color = enable == '未读' ? 'yellow' : enable == '已读' ? 'green' : 'red';  
45 - const text = enable == '未读' ? '未读' : enable == '已读' ? '已读' : '其他';  
46 - return h(Tag, { color }, () => text);  
47 - },  
48 - },  
49 -];  
50 -  
51 -export const searchFormSchema: FormSchema[] = [  
52 - {  
53 - field: 'type',  
54 - label: '通知类型',  
55 - colProps: { span: 6 },  
56 - component: 'Select',  
57 - componentProps: {  
58 - placeholder: '请选择类型',  
59 - options: [  
60 - {  
61 - label: '公告',  
62 - value: 'NOTICE',  
63 - },  
64 - {  
65 - label: '会议',  
66 - value: 'MEETING',  
67 - },  
68 - {  
69 - label: '其他',  
70 - value: 'OTHER',  
71 - },  
72 - ],  
73 - },  
74 - },  
75 -];  
76 -  
77 -export const DescDetailSchema: DescItem[] = [  
78 - {  
79 - field: 'sysNotice.senderName',  
80 - label: '发送者',  
81 - },  
82 - {  
83 - field: 'sysNotice.senderDate',  
84 - label: '发送时间',  
85 - },  
86 - {  
87 - field: 'sysNotice.type',  
88 - label: '类型',  
89 - render: (text) => {  
90 - return text === 'NOTICE'  
91 - ? '公告'  
92 - : text === 'MEETING'  
93 - ? '会议'  
94 - : text === 'OTHER'  
95 - ? '其他'  
96 - : '';  
97 - },  
98 - },  
99 -];  
1 -<template>  
2 - <div>  
3 - <BasicTable @register="registerTable">  
4 - <template #action="{ record }">  
5 - <TableAction  
6 - :actions="[  
7 - {  
8 - label: '查看',  
9 - tooltip: '查看',  
10 - icon: 'ant-design:eye-outlined',  
11 - onClick: handleView.bind(null, record),  
12 - },  
13 - ]"  
14 - />  
15 - </template>  
16 - </BasicTable>  
17 - <CatNoticeModal @register="registerModal" @success="handleSuccess" />  
18 - </div>  
19 -</template>  
20 -<script lang="ts">  
21 - import { defineComponent } from 'vue';  
22 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
23 - import { useModal } from '/@/components/Modal';  
24 - import CatNoticeModal from './CatNoticeModal.vue';  
25 - import { columns, searchFormSchema } from './config.d';  
26 - import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi';  
27 - export default defineComponent({  
28 - name: 'LoginForm',  
29 - components: { BasicTable, CatNoticeModal, TableAction },  
30 - setup() {  
31 - const [registerModal, { openModal }] = useModal();  
32 - const [registerTable, { reload }] = useTable({  
33 - api: notifyMyGetrPageApi,  
34 - columns,  
35 - formConfig: {  
36 - labelWidth: 120,  
37 - schemas: searchFormSchema,  
38 - },  
39 - useSearchForm: true,  
40 - showTableSetting: true,  
41 - bordered: true,  
42 - showIndexColumn: false,  
43 - actionColumn: {  
44 - width: 200,  
45 - title: '操作',  
46 - dataIndex: 'action',  
47 - slots: { customRender: 'action' },  
48 - fixed: 'right',  
49 - },  
50 - });  
51 -  
52 - function handleView(record: Recordable) {  
53 - openModal(true, {  
54 - record,  
55 - });  
56 - }  
57 -  
58 - function handleSuccess() {  
59 - reload();  
60 - }  
61 - return {  
62 - registerTable,  
63 - registerModal,  
64 - handleView,  
65 - handleSuccess,  
66 - };  
67 - },  
68 - });  
69 -</script>  
1 -import { h } from 'vue';  
2 -import { BasicColumn, FormSchema } from '/@/components/Table';  
3 -import { Tinymce } from '/@/components/Tinymce/index';  
4 -import { getOrganizationList } from '/@/api/system/system';  
5 -import { copyTransFun } from '/@/utils/fnUtils';  
6 -import { Tag } from 'ant-design-vue';  
7 -  
8 -export enum IsOrgEnum {  
9 - IS_ORG_ENUM = '1',  
10 -}  
11 -export const isOrg = (type: string) => {  
12 - return type === IsOrgEnum.IS_ORG_ENUM;  
13 -};  
14 -  
15 -export const columns: BasicColumn[] = [  
16 - {  
17 - title: '类型',  
18 - dataIndex: 'type',  
19 - width: 200,  
20 - format: (_text: string, record: Recordable) => {  
21 - return record.type === 'NOTICE'  
22 - ? '公告'  
23 - : record.type === 'MEETING'  
24 - ? '会议'  
25 - : record.type === 'OTHER'  
26 - ? '其他'  
27 - : '';  
28 - },  
29 - },  
30 - {  
31 - title: '标题',  
32 - dataIndex: 'title',  
33 - width: 200,  
34 - },  
35 - {  
36 - title: '内容',  
37 - dataIndex: 'content',  
38 - width: 120,  
39 - format: (text: string, record: Recordable) => {  
40 - return !record.content ? '' : record.content.slice(3, record.content.length - 4);  
41 - },  
42 - },  
43 - {  
44 - title: '发送者',  
45 - dataIndex: 'senderName',  
46 - width: 200,  
47 - format: (text: string, record: Recordable) => {  
48 - return record.senderName ? record.senderName : '无';  
49 - },  
50 - },  
51 - {  
52 - title: '状态',  
53 - dataIndex: 'status',  
54 - width: 200,  
55 - customRender: ({ record }) => {  
56 - const status = record.status;  
57 - const enable = status === '已发布' ? '已发布' : status === '草稿' ? '草稿' : '其他';  
58 - const color = enable === '已发布' ? 'green' : enable === '草稿' ? 'yellow' : 'red';  
59 - const text = enable === '已发布' ? '已发布' : enable === '草稿' ? '草稿' : '其他';  
60 - return h(Tag, { color: color }, () => text);  
61 - },  
62 - },  
63 -];  
64 -  
65 -export const formSchema: FormSchema[] = [  
66 - {  
67 - field: 'type',  
68 - label: '类型',  
69 - colProps: { span: 24 },  
70 - required: true,  
71 - component: 'RadioGroup',  
72 - componentProps: {  
73 - options: [  
74 - {  
75 - label: '公告',  
76 - value: 'NOTICE',  
77 - },  
78 - {  
79 - label: '会议',  
80 - value: 'MEETING',  
81 - },  
82 - {  
83 - label: '其他',  
84 - value: 'OTHER',  
85 - },  
86 - ],  
87 - },  
88 - },  
89 - {  
90 - field: 'title',  
91 - label: '标题',  
92 - required: true,  
93 - colProps: { span: 24 },  
94 - component: 'Input',  
95 - componentProps: {  
96 - placeholder: '请输入标题',  
97 - maxLength: 200,  
98 - },  
99 - },  
100 - {  
101 - field: 'content',  
102 - component: 'Input',  
103 - colProps: { span: 24 },  
104 - label: '通知内容',  
105 - required: true,  
106 - render: ({ model, field }) => {  
107 - return h(Tinymce, {  
108 - value: model[field],  
109 - onChange: (value: string) => {  
110 - model[field] = value;  
111 - },  
112 - });  
113 - },  
114 - },  
115 - {  
116 - field: 'receiverType',  
117 - required: true,  
118 - label: '接收者',  
119 - colProps: { span: 13 },  
120 - component: 'Select',  
121 - componentProps: {  
122 - placeholder: '接收者',  
123 - options: [  
124 - { label: '全部', value: '0' },  
125 - { label: '组织', value: '1' },  
126 - ],  
127 - },  
128 - },  
129 - {  
130 - field: 'organizationId',  
131 - label: '所属组织',  
132 - colProps: { span: 13 },  
133 - component: 'ApiTreeSelect',  
134 - required: true,  
135 - componentProps: {  
136 - multiple: true,  
137 - api: async () => {  
138 - const data = await getOrganizationList();  
139 - copyTransFun(data as any as any[]);  
140 - return data;  
141 - },  
142 - },  
143 - ifShow: ({ values }) => isOrg(Reflect.get(values, 'receiverType')),  
144 - },  
145 -];  
146 -  
147 -export const searchFormSchema: FormSchema[] = [  
148 - {  
149 - field: 'type',  
150 - label: '通知类型',  
151 - colProps: { span: 6 },  
152 - component: 'Select',  
153 - componentProps: {  
154 - placeholder: '请选择类型',  
155 - options: [  
156 - {  
157 - label: '公告',  
158 - value: 'NOTICE',  
159 - },  
160 - {  
161 - label: '会议',  
162 - value: 'MEETING',  
163 - },  
164 - {  
165 - label: '其他',  
166 - value: 'OTHER',  
167 - },  
168 - ],  
169 - },  
170 - },  
171 -];  
172 -export const detailColumns: BasicColumn[] = [  
173 - {  
174 - title: '接收者',  
175 - dataIndex: 'user.realName',  
176 - width: 200,  
177 - },  
178 - {  
179 - title: '阅读状态',  
180 - dataIndex: 'readStatus',  
181 - width: 200,  
182 - slots: { customRender: 'readStatus' },  
183 - },  
184 - {  
185 - title: '阅读时间',  
186 - dataIndex: 'readDate',  
187 - width: 200,  
188 - },  
189 -];  
1 -<template>  
2 - <div>  
3 - <BasicTable @register="registerTable">  
4 - <template #toolbar>  
5 - <a-button type="primary" @click="handleAdd">新增通知</a-button>  
6 - <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">  
7 - 批量删除  
8 - </a-button>  
9 - </template>  
10 - <template #action="{ record }">  
11 - <TableAction  
12 - :actions="[  
13 - {  
14 - label: '查看',  
15 - icon: 'ant-design:eye-outlined',  
16 - onClick: handleView.bind(null, record),  
17 - ifShow: (_action) => {  
18 - return record.status === '已发布';  
19 - },  
20 - },  
21 - {  
22 - label: '编辑',  
23 - icon: 'clarity:note-edit-line',  
24 - onClick: handleEdit.bind(null, record),  
25 - ifShow: (_action) => {  
26 - return record.status === '草稿';  
27 - },  
28 - },  
29 - {  
30 - label: '删除',  
31 - icon: 'ant-design:delete-outlined',  
32 - color: 'error',  
33 - popConfirm: {  
34 - title: '是否确认删除',  
35 - confirm: handleDeleteOrBatchDelete.bind(null, record),  
36 - },  
37 - },  
38 - ]"  
39 - />  
40 - </template>  
41 - </BasicTable>  
42 - <NotifyManagerDrawer  
43 - @register="registerAdd"  
44 - @success="handleSuccess"  
45 - ref="NotifyManagerDrawerRef"  
46 - />  
47 - <tableViewChild @register="registerDrawer" />  
48 - </div>  
49 -</template>  
50 -<script lang="ts">  
51 - import { defineComponent, ref } from 'vue';  
52 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
53 - import { useDrawer } from '/@/components/Drawer';  
54 - import NotifyManagerDrawer from './useDrawer.vue';  
55 - import tableViewChild from './viewDetailDrawer.vue';  
56 - import { columns, searchFormSchema } from './config.d';  
57 - import { notifyGetTableApi, notifyDeleteApi } from '/@/api/stationnotification/stationnotifyApi';  
58 - import { useBatchDelete } from '/@/hooks/web/useBatchDelete';  
59 - export default defineComponent({  
60 - name: 'Notificationmannager',  
61 - components: { BasicTable, NotifyManagerDrawer, TableAction, tableViewChild },  
62 - setup() {  
63 - const [registerDrawer, { openDrawer }] = useDrawer();  
64 - const [registerAdd, { openDrawer: openDrawerAdd }] = useDrawer();  
65 -  
66 - // 批量删除  
67 - const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(  
68 - notifyDeleteApi,  
69 - handleSuccess  
70 - );  
71 - const NotifyManagerDrawerRef = ref();  
72 - const [registerTable, { reload }] = useTable({  
73 - api: notifyGetTableApi,  
74 - columns,  
75 - formConfig: {  
76 - labelWidth: 120,  
77 - schemas: searchFormSchema,  
78 - },  
79 - useSearchForm: true,  
80 - showTableSetting: true,  
81 - bordered: true,  
82 - showIndexColumn: false,  
83 - actionColumn: {  
84 - width: 200,  
85 - title: '操作',  
86 - dataIndex: 'action',  
87 - slots: { customRender: 'action' },  
88 - fixed: 'right',  
89 - },  
90 - ...selectionOptions,  
91 - });  
92 -  
93 - function handleAdd() {  
94 - openDrawerAdd(true, {  
95 - isUpdate: false,  
96 - });  
97 - NotifyManagerDrawerRef.value.setFieldsValue({ content: '' });  
98 - }  
99 -  
100 - const handleView = (record: Recordable) => {  
101 - openDrawer(true, {  
102 - record,  
103 - });  
104 - };  
105 - function handleEdit(record: Recordable) {  
106 - openDrawerAdd(true, {  
107 - record,  
108 - isUpdate: true,  
109 - });  
110 - }  
111 - function handleSuccess() {  
112 - reload();  
113 - }  
114 - return {  
115 - hasBatchDelete,  
116 - handleView,  
117 - registerAdd,  
118 - registerTable,  
119 - registerDrawer,  
120 - handleAdd,  
121 - handleEdit,  
122 - handleSuccess,  
123 - handleDeleteOrBatchDelete,  
124 - NotifyManagerDrawerRef,  
125 - };  
126 - },  
127 - });  
128 -</script>  
1 -<template>  
2 - <div>  
3 - <BasicDrawer  
4 - v-bind="$attrs"  
5 - @register="registerDrawer"  
6 - :title="getTitle"  
7 - width="800px"  
8 - showFooter  
9 - >  
10 - <BasicForm @register="registerForm" />  
11 - <template #footer>  
12 - <a-button @click="handleCancel">取消</a-button>  
13 - <a-button @click="handleSaveDraft">保存草稿</a-button>  
14 - <a-button type="primary" @click="handleSend">发布通知</a-button>  
15 - </template>  
16 - </BasicDrawer>  
17 - </div>  
18 -</template>  
19 -<script lang="ts">  
20 - import { defineComponent, computed, unref, ref } from 'vue';  
21 - import { BasicForm, useForm } from '/@/components/Form';  
22 - import { formSchema } from './config.d';  
23 - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';  
24 - import {  
25 - notifyAddDraftApi,  
26 - notifyAddLeaseApi,  
27 - } from '/@/api/stationnotification/stationnotifyApi';  
28 - import { useMessage } from '/@/hooks/web/useMessage';  
29 - export default defineComponent({  
30 - name: 'ConfigDrawer',  
31 - components: { BasicDrawer, BasicForm },  
32 - emits: ['success', 'register'],  
33 - setup(_, { emit }) {  
34 - const { createMessage } = useMessage();  
35 - const isUpdate = ref<Boolean>();  
36 - const getTitle = computed(() => (!unref(isUpdate) ? '新增通知' : '编辑通知'));  
37 - const noticeId = ref('');  
38 - const [registerForm, { setFieldsValue, resetFields, validate, getFieldsValue }] = useForm({  
39 - labelWidth: 120,  
40 - schemas: formSchema,  
41 - showActionButtonGroup: false,  
42 - });  
43 - const [registerDrawer, { closeDrawer }] = useDrawerInner(async (data) => {  
44 - await resetFields();  
45 - isUpdate.value = data.isUpdate;  
46 - //编辑  
47 - if (data.isUpdate) {  
48 - noticeId.value = data.record.id;  
49 - Reflect.set(data.record, 'receiverType', data.record.receiverType === '全部' ? '0' : '1');  
50 - if (data.record.receiverType === '1') {  
51 - if (!data.record.pointId.length) return;  
52 - const organizationId = data.record.pointId.split(',');  
53 - Reflect.set(data.record, 'organizationId', organizationId);  
54 - }  
55 - setFieldsValue(data.record);  
56 - }  
57 - });  
58 - // 发布通知  
59 - const handleSend = async () => {  
60 - await validate();  
61 - const field = getFieldsValue();  
62 - const pointId = field.receiverType === '1' ? field.organizationId + '' : null;  
63 - // 新增情况  
64 - if (!unref(isUpdate)) {  
65 - const addNotice = {  
66 - ...field,  
67 - pointId,  
68 - };  
69 - await notifyAddLeaseApi(addNotice);  
70 - } else {  
71 - const editNotice = {  
72 - ...field,  
73 - pointId,  
74 - id: unref(noticeId),  
75 - };  
76 - await notifyAddLeaseApi(editNotice);  
77 - }  
78 - emit('success');  
79 - closeDrawer();  
80 - createMessage.success('发布成功');  
81 - };  
82 - // 保存草稿  
83 - const handleSaveDraft = async () => {  
84 - await validate();  
85 - const field = getFieldsValue();  
86 - const pointId = field.receiverType === '1' ? field.organizationId + '' : null;  
87 - if (!unref(isUpdate)) {  
88 - const saveDraft = {  
89 - ...field,  
90 - pointId,  
91 - };  
92 - await notifyAddDraftApi(saveDraft);  
93 - } else {  
94 - const editDraft = {  
95 - ...field,  
96 - pointId,  
97 - id: unref(noticeId),  
98 - };  
99 - await notifyAddDraftApi(editDraft);  
100 - }  
101 - emit('success');  
102 - closeDrawer();  
103 - createMessage.success('保存草稿成功');  
104 - };  
105 - const handleCancel = () => {  
106 - // resetFields();  
107 - closeDrawer();  
108 - };  
109 - return {  
110 - getTitle,  
111 - handleSend,  
112 - handleCancel,  
113 - handleSaveDraft,  
114 - registerForm,  
115 - registerDrawer,  
116 - setFieldsValue,  
117 - };  
118 - },  
119 - });  
120 -</script>  
1 -<template>  
2 - <div>  
3 - <BasicDrawer  
4 - v-bind="$attrs"  
5 - @register="registerDrawer"  
6 - :showFooter="false"  
7 - :title="descInfo?.title"  
8 - destroyOnClose  
9 - width="70%"  
10 - >  
11 - <div v-html="descInfo?.content"></div>  
12 - <Description @register="registerDesc" class="mt-4" />  
13 - <BasicTable @register="registerTable" class="mt-4">  
14 - <template #readStatus="{ record }">  
15 - <Tag :color="record.readStatus === '0' ? 'orange' : 'green'">  
16 - {{ record.readStatus === '0' ? '未读' : '已读' }}  
17 - </Tag>  
18 - </template>  
19 - </BasicTable>  
20 - </BasicDrawer>  
21 - </div>  
22 -</template>  
23 -<script lang="ts">  
24 - import { defineComponent, ref } from 'vue';  
25 - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';  
26 - import { Description, DescItem, useDescription } from '/@/components/Description/index';  
27 - import {  
28 - getNotifyDetailPage,  
29 - noticeByIdGetInfo,  
30 - } from '/@/api/stationnotification/stationnotifyApi';  
31 - import { useTable, BasicTable } from '/@/components/Table';  
32 - import { detailColumns } from './config.d';  
33 - import { Tag } from 'ant-design-vue';  
34 - const schema: DescItem[] = [  
35 - {  
36 - field: 'senderName',  
37 - label: '发送者',  
38 - },  
39 - {  
40 - field: 'type',  
41 - label: '类型',  
42 - render: (_, { type }) => {  
43 - return type === 'NOTICE'  
44 - ? '公告'  
45 - : type === 'MEETING'  
46 - ? '会议'  
47 - : type === 'OTHER'  
48 - ? '其他'  
49 - : '';  
50 - },  
51 - },  
52 - {  
53 - field: 'senderDate',  
54 - label: '发送时间',  
55 - },  
56 - ];  
57 - export default defineComponent({  
58 - name: 'ConfigDrawer',  
59 - components: { BasicDrawer, Description, BasicTable, Tag },  
60 - emits: ['success', 'register'],  
61 - setup() {  
62 - let descInfo = ref();  
63 - let noticeId;  
64 - const [registerDrawer] = useDrawerInner(async (data) => {  
65 - let getDescInfo = await noticeByIdGetInfo(data.record.id);  
66 - noticeId = data.record.id;  
67 - descInfo.value = getDescInfo;  
68 - reload();  
69 - });  
70 - const [registerTable, { reload }] = useTable({  
71 - api: getNotifyDetailPage,  
72 - columns: detailColumns,  
73 - bordered: true,  
74 - showTableSetting: true,  
75 - showIndexColumn: false,  
76 - immediate: false,  
77 - beforeFetch: getNoticeId,  
78 - });  
79 - function getNoticeId(data) {  
80 - Reflect.set(data, 'noticeId', noticeId);  
81 - }  
82 -  
83 - const [registerDesc] = useDescription({  
84 - bordered: true,  
85 - data: descInfo,  
86 - schema,  
87 - });  
88 - return {  
89 - descInfo,  
90 - registerDesc,  
91 - registerTable,  
92 - registerDrawer,  
93 - };  
94 - },  
95 - });  
96 -</script>  
1 -<template>  
2 - <div>  
3 - <PageWrapper  
4 - title="第一次使用请修改当前用户密码,待修改完成后退出登录,才能使用本系统!"  
5 - content="修改成功后会自动退出当前登录!"  
6 - class="p-4"  
7 - >  
8 - <div class="py-8 bg-white flex flex-col justify-center items-center">  
9 - <BasicForm @register="register" />  
10 - <div class="flex justify-center">  
11 - <a-button @click="resetFields"> 重置 </a-button>  
12 - <a-button class="!ml-4" type="primary" @click="handleSubmit"> 确认 </a-button>  
13 - </div>  
14 - </div>  
15 - </PageWrapper>  
16 - </div>  
17 -</template>  
18 -<script lang="ts">  
19 - import { defineComponent } from 'vue';  
20 - import { PageWrapper } from '/@/components/Page';  
21 - import { BasicForm, useForm } from '/@/components/Form';  
22 - import { USER_INFO_KEY } from '/@/enums/cacheEnum';  
23 - import { getAuthCache } from '/@/utils/auth';  
24 - import { formSchema } from './pwd.data';  
25 - import { resetPassword } from '/@/api/system/system';  
26 - import { useMultipleTabStore } from '/@/store/modules/multipleTab';  
27 - import { useUserStore } from '/@/store/modules/user';  
28 - import { useAppStore } from '/@/store/modules/app';  
29 - import { usePermissionStore } from '/@/store/modules/permission';  
30 - import { useMessage } from '/@/hooks/web/useMessage';  
31 - export default defineComponent({  
32 - name: 'ChangePassword',  
33 - components: { BasicForm, PageWrapper },  
34 - setup() {  
35 - const [register, { validate, resetFields }] = useForm({  
36 - size: 'large',  
37 - labelWidth: 100,  
38 - showActionButtonGroup: false,  
39 - schemas: formSchema,  
40 - });  
41 - const tabStore = useMultipleTabStore();  
42 - const userStore = useUserStore();  
43 - const appStore = useAppStore();  
44 - const permissionStore = usePermissionStore();  
45 - const { createMessage } = useMessage();  
46 - const userInfo = getAuthCache(USER_INFO_KEY);  
47 - // console.log(userInfo, 'userInfo');  
48 - async function handleSubmit() {  
49 - try {  
50 - const values = await validate();  
51 - const { passwordOld, passwordNew } = values;  
52 - const params = {  
53 - userId: userInfo.userId,  
54 - password: passwordOld,  
55 - resetPassword: passwordNew,  
56 - };  
57 -  
58 - await resetPassword(params).then((result) => {  
59 - if (result.data) {  
60 - createMessage.success('修改成功');  
61 - // /dashboard/analysis  
62 - setTimeout(function () {  
63 - localStorage.clear();  
64 - appStore.resetAllState();  
65 - permissionStore.resetState();  
66 - tabStore.resetState();  
67 - userStore.resetState();  
68 - location.reload();  
69 - }, 500);  
70 - }  
71 - });  
72 - } catch (error) {}  
73 - }  
74 - return { register, resetFields, handleSubmit };  
75 - },  
76 - });  
77 -</script>  
1 -import { FormSchema } from '/@/components/Form';  
2 -import { InputRegExp } from '/@/enums/regexpEnum';  
3 -export const formSchema: FormSchema[] = [  
4 - {  
5 - field: 'passwordOld',  
6 - label: '当前密码',  
7 - component: 'InputPassword',  
8 - required: true,  
9 - },  
10 - {  
11 - field: 'passwordNew',  
12 - label: '新密码',  
13 - component: 'StrengthMeter',  
14 - componentProps: {  
15 - placeholder: '新密码',  
16 - },  
17 - rules: [  
18 - {  
19 - required: true,  
20 - message: '请输入新密码',  
21 - },  
22 - ],  
23 - },  
24 - {  
25 - field: 'confirmPassword',  
26 - label: '确认密码',  
27 - component: 'InputPassword',  
28 -  
29 - dynamicRules: ({ values }) => {  
30 - return [  
31 - {  
32 - required: true,  
33 - validator: (_, value) => {  
34 - if (!value) {  
35 - return Promise.reject('密码不能为空');  
36 - }  
37 - if (value !== values.passwordNew) {  
38 - return Promise.reject('两次输入的密码不一致!');  
39 - }  
40 -  
41 - const pwdRegex = new RegExp(InputRegExp.PASSWORD_INPUT);  
42 - if (!pwdRegex.test(value)) {  
43 - return Promise.reject(  
44 - '密码中必须包含大小写 字母、数字、特称字符,至少8个字符,最多30个字符'  
45 - );  
46 - }  
47 - return Promise.resolve();  
48 - },  
49 - },  
50 - ];  
51 - },  
52 - },  
53 -];  
1 -import type { FormSchema } from '/@/components/Form/index';  
2 -export const schemas: FormSchema[] = [  
3 - {  
4 - field: 'name',  
5 - component: 'Input',  
6 - label: '平台名称',  
7 - colProps: {  
8 - span: 24,  
9 - },  
10 - componentProps: {  
11 - maxLength: 255,  
12 - placeholder: '请输入平台名称',  
13 - },  
14 - dynamicRules: () => {  
15 - return [  
16 - {  
17 - required: false,  
18 - validator: (_, value) => {  
19 - if (String(value).length > 255) {  
20 - return Promise.reject('字数不超过255个字');  
21 - }  
22 - return Promise.resolve();  
23 - },  
24 - },  
25 - ];  
26 - },  
27 - },  
28 - {  
29 - field: 'logo',  
30 - component: 'Upload',  
31 - label: 'APP Logo',  
32 - colProps: {  
33 - span: 24,  
34 - },  
35 - slot: 'logoUpload',  
36 - },  
37 - {  
38 - field: 'background',  
39 - component: 'Input',  
40 - label: '登录页背景图片',  
41 - colProps: {  
42 - span: 24,  
43 - },  
44 - slot: 'bgUpload',  
45 - },  
46 - {  
47 - field: 'backgroundColor',  
48 - component: 'AutoComplete',  
49 - label: '登录页背景颜色',  
50 - colProps: {  
51 - span: 24,  
52 - },  
53 - slot: 'colorInput',  
54 - },  
55 - {  
56 - field: 'background',  
57 - component: 'Input',  
58 - label: '首页轮播图',  
59 - colProps: {  
60 - span: 24,  
61 - },  
62 - slot: 'homeSwiper',  
63 - },  
64 -];  
1 -import type { FormSchema } from '/@/components/Form/index';  
2 -  
3 -export const schemas: FormSchema[] = [  
4 - {  
5 - field: 'name',  
6 - component: 'Input',  
7 - label: '平台名称',  
8 - colProps: {  
9 - span: 24,  
10 - },  
11 - componentProps: {  
12 - maxLength: 255,  
13 - placeholder: '请输入平台名称',  
14 - },  
15 - dynamicRules: () => {  
16 - return [  
17 - {  
18 - required: false,  
19 - validator: (_, value) => {  
20 - if (String(value).length > 255) {  
21 - return Promise.reject('字数不超过255个字');  
22 - }  
23 - return Promise.resolve();  
24 - },  
25 - },  
26 - ];  
27 - },  
28 - },  
29 - {  
30 - field: 'logo',  
31 - component: 'Upload',  
32 - label: '平台Logo',  
33 - colProps: {  
34 - span: 24,  
35 - },  
36 - slot: 'logoUpload',  
37 - },  
38 - {  
39 - field: 'icon',  
40 - component: 'Upload',  
41 - label: '浏览器Icon图标',  
42 - colProps: {  
43 - span: 24,  
44 - },  
45 - slot: 'iconUpload',  
46 - },  
47 - {  
48 - field: 'background',  
49 - component: 'Input',  
50 - label: '登录页背景图片',  
51 - colProps: {  
52 - span: 24,  
53 - },  
54 - slot: 'bgUpload',  
55 - },  
56 - {  
57 - field: 'backgroundColor',  
58 - component: 'AutoComplete',  
59 - label: '登录页背景颜色',  
60 - colProps: {  
61 - span: 24,  
62 - },  
63 - slot: 'colorInput',  
64 - },  
65 - {  
66 - field: 'copyright',  
67 - component: 'Input',  
68 - label: '页面底部版权信息',  
69 - colProps: {  
70 - span: 24,  
71 - },  
72 - componentProps: {  
73 - maxLength: 100,  
74 - placeholder: '请输入页面底部版权信息',  
75 - },  
76 - dynamicRules: () => {  
77 - return [  
78 - {  
79 - required: false,  
80 - validator: (_, value) => {  
81 - if (String(value).length > 100) {  
82 - return Promise.reject('字数不超过100个字');  
83 - }  
84 - return Promise.resolve();  
85 - },  
86 - },  
87 - ];  
88 - },  
89 - },  
90 - {  
91 - field: 'presentedOurselves',  
92 - component: 'Input',  
93 - label: '备案信息',  
94 - colProps: {  
95 - span: 24,  
96 - },  
97 - componentProps: {  
98 - maxLength: 50,  
99 - placeholder: '请输入备案信息',  
100 - },  
101 - dynamicRules: () => {  
102 - return [  
103 - {  
104 - required: false,  
105 - validator: (_, value) => {  
106 - if (String(value).length > 50) {  
107 - return Promise.reject('字数不超过50个字');  
108 - }  
109 - return Promise.resolve();  
110 - },  
111 - },  
112 - ];  
113 - },  
114 - },  
115 - {  
116 - field: 'domain',  
117 - component: 'Input',  
118 - label: '绑定域名',  
119 - colProps: {  
120 - span: 24,  
121 - },  
122 - componentProps: {  
123 - maxLength: 100,  
124 - placeholder: '请输入绑定域名',  
125 - },  
126 - dynamicRules: () => {  
127 - return [  
128 - {  
129 - required: false,  
130 - validator: (_, value) => {  
131 - if (String(value).length > 100) {  
132 - return Promise.reject('字数不超过100个字');  
133 - }  
134 - return Promise.resolve();  
135 - },  
136 - },  
137 - ];  
138 - },  
139 - },  
140 -];  
1 -import type { FormSchema } from '/@/components/Form/index';  
2 -import { getAreaList } from '/@/api/oem/index';  
3 -import { emailRule, phoneRule } from '/@/utils/rules';  
4 -  
5 -export const schemas: FormSchema[] = [  
6 - {  
7 - field: 'name',  
8 - component: 'Input',  
9 - label: '公司名称',  
10 - colProps: {  
11 - span: 24,  
12 - },  
13 - componentProps: {  
14 - maxLength: 100,  
15 - placeholder: '请输入公司名称',  
16 - },  
17 - dynamicRules: () => {  
18 - return [  
19 - {  
20 - required: false,  
21 - validator: (_, value) => {  
22 - if (String(value).length > 100) {  
23 - return Promise.reject('字数不超过100个字');  
24 - }  
25 - return Promise.resolve();  
26 - },  
27 - },  
28 - ];  
29 - },  
30 - },  
31 - {  
32 - field: 'abbreviation',  
33 - component: 'Input',  
34 - label: '公司简称',  
35 - colProps: {  
36 - span: 24,  
37 - },  
38 - componentProps: {  
39 - maxLength: 100,  
40 - placeholder: '请输入公司简称',  
41 - },  
42 - dynamicRules: () => {  
43 - return [  
44 - {  
45 - required: false,  
46 - validator: (_, value) => {  
47 - if (String(value).length > 100) {  
48 - return Promise.reject('字数不超过100个字');  
49 - }  
50 - return Promise.resolve();  
51 - },  
52 - },  
53 - ];  
54 - },  
55 - },  
56 - {  
57 - field: 'officialWebsite',  
58 - component: 'Input',  
59 - label: '公司官网',  
60 - colProps: {  
61 - span: 24,  
62 - },  
63 - componentProps: {  
64 - maxLength: 255,  
65 - placeholder: '请输入公司官网',  
66 - },  
67 - dynamicRules: () => {  
68 - return [  
69 - {  
70 - required: false,  
71 - validator: (_, value) => {  
72 - if (String(value).length > 255) {  
73 - return Promise.reject('字数不超过255个字');  
74 - }  
75 - return Promise.resolve();  
76 - },  
77 - },  
78 - ];  
79 - },  
80 - },  
81 - {  
82 - field: 'email',  
83 - component: 'Input',  
84 - label: '公司邮箱',  
85 - colProps: {  
86 - span: 24,  
87 - },  
88 - componentProps: {  
89 - placeholder: '请输入公司邮箱',  
90 - },  
91 - rules: emailRule,  
92 - },  
93 - {  
94 - field: 'synopsis',  
95 - component: 'InputTextArea',  
96 - label: '公司简介',  
97 - colProps: {  
98 - span: 24,  
99 - },  
100 - componentProps: {  
101 - maxLength: 500,  
102 - placeholder: '请输入公司简介',  
103 - autoSize: { minRows: 8, maxRows: 12 },  
104 - },  
105 - dynamicRules: () => {  
106 - return [  
107 - {  
108 - required: false,  
109 - validator: (_, value) => {  
110 - if (String(value).length > 500) {  
111 - return Promise.reject('字数不超过500个字');  
112 - }  
113 - return Promise.resolve();  
114 - },  
115 - },  
116 - ];  
117 - },  
118 - },  
119 - {  
120 - field: 'nameCountry',  
121 - component: 'ApiSelect',  
122 - label: '国家/地区',  
123 - colProps: {  
124 - span: 24,  
125 - },  
126 - componentProps: {  
127 - api: getAreaList,  
128 - params: { parentId: 0 },  
129 - labelField: 'name',  
130 - valueField: 'code',  
131 - placeholder: '国家/地区',  
132 - },  
133 - },  
134 - {  
135 - field: 'prov',  
136 - label: '所在城市',  
137 - component: 'Input',  
138 - colProps: {  
139 - span: 24,  
140 - },  
141 -  
142 - slot: 'customProv',  
143 - },  
144 - {  
145 - field: 'address',  
146 - component: 'Input',  
147 - label: '详细地址',  
148 - colProps: {  
149 - span: 24,  
150 - },  
151 - componentProps: {  
152 - maxLength: 100,  
153 - placeholder: '请输入详细地址',  
154 - },  
155 - dynamicRules: () => {  
156 - return [  
157 - {  
158 - required: false,  
159 - validator: (_, value) => {  
160 - if (String(value).length > 100) {  
161 - return Promise.reject('字数不超过100个字');  
162 - }  
163 - return Promise.resolve();  
164 - },  
165 - },  
166 - ];  
167 - },  
168 - },  
169 -  
170 - {  
171 - field: 'contacts',  
172 - component: 'Input',  
173 - label: '联系人',  
174 - colProps: {  
175 - span: 24,  
176 - },  
177 - componentProps: {  
178 - maxLength: 25,  
179 - placeholder: '请输入联系人',  
180 - },  
181 - dynamicRules: () => {  
182 - return [  
183 - {  
184 - required: false,  
185 - validator: (_, value) => {  
186 - if (String(value).length > 25) {  
187 - return Promise.reject('字数不超过25个字');  
188 - }  
189 - return Promise.resolve();  
190 - },  
191 - },  
192 - ];  
193 - },  
194 - },  
195 - {  
196 - field: 'tel',  
197 - component: 'Input',  
198 - label: '联系电话',  
199 - colProps: {  
200 - span: 24,  
201 - },  
202 - componentProps: {  
203 - placeholder: '请输入联系电话',  
204 - },  
205 - rules: phoneRule,  
206 - },  
207 - {  
208 - field: 'qrcode',  
209 - label: '二维码',  
210 - component: 'Input',  
211 - colProps: {  
212 - span: 24,  
213 - },  
214 - slot: 'qrcode',  
215 - },  
216 - {  
217 - field: 'id',  
218 - label: '唯一id',  
219 - component: 'Input',  
220 - show: false,  
221 - componentProps: {  
222 - maxLength: 36,  
223 - placeholder: '请输入唯一id',  
224 - },  
225 - },  
226 -];  
227 -  
228 -export const provSchemas: FormSchema[] = [  
229 - {  
230 - field: 'nameProv',  
231 - component: 'ApiSelect',  
232 - label: '',  
233 - colProps: {  
234 - span: 6,  
235 - },  
236 - componentProps({ formModel, formActionType }) {  
237 - const { updateSchema } = formActionType;  
238 - return {  
239 - api: getAreaList,  
240 - labelField: 'name',  
241 - valueField: 'code',  
242 - placeholder: '省份',  
243 - params: { parentId: 1 },  
244 - async onChange(value) {  
245 - if (value === undefined) {  
246 - formModel.nameCity = undefined; // reset city value  
247 - formModel.nameCoun = undefined;  
248 - formModel.nameTown = undefined;  
249 - updateSchema([  
250 - {  
251 - field: 'nameCity',  
252 - componentProps: {  
253 - options: [],  
254 - placeholder: '城市',  
255 - },  
256 - },  
257 - {  
258 - field: 'nameCoun',  
259 - componentProps: {  
260 - options: [],  
261 - placeholder: '区/县',  
262 - },  
263 - },  
264 - {  
265 - field: 'nameTown',  
266 - componentProps: {  
267 - options: [],  
268 - placeholder: '城镇/街道',  
269 - },  
270 - },  
271 - ]);  
272 - } else {  
273 - const nameCity = await getAreaList({ parentId: value });  
274 - nameCity.forEach((item) => {  
275 - item.label = item.name;  
276 - item.value = item.code;  
277 - });  
278 - formModel.nameCity = undefined; // reset city value  
279 - formModel.nameCoun = undefined;  
280 - formModel.nameTown = undefined;  
281 - updateSchema({  
282 - field: 'nameCity',  
283 - componentProps: {  
284 - options: nameCity,  
285 - placeholder: '城市',  
286 - async onChange(value) {  
287 - if (value === undefined) {  
288 - formModel.nameCoun = undefined; // reset city value  
289 - formModel.nameTown = undefined;  
290 - updateSchema([  
291 - {  
292 - field: 'nameCoun',  
293 - componentProps: {  
294 - options: [],  
295 - },  
296 - },  
297 - {  
298 - field: 'nameTown',  
299 - componentProps: {  
300 - options: [],  
301 - },  
302 - },  
303 - ]);  
304 - } else {  
305 - // 获取区数据  
306 - const nameCoun = await getAreaList({ parentId: value });  
307 - nameCoun.forEach((item) => {  
308 - item.label = item.name;  
309 - item.value = item.code;  
310 - });  
311 - updateSchema({  
312 - field: 'nameCoun',  
313 - componentProps: {  
314 - // 请选择区  
315 - options: nameCoun,  
316 - async onChange(value) {  
317 - if (value === undefined) {  
318 - formModel.nameTown = undefined;  
319 - updateSchema({  
320 - field: 'nameTown',  
321 - componentProps: {  
322 - placeholder: '城镇/街道',  
323 - options: [],  
324 - },  
325 - });  
326 - } else {  
327 - const nameTown = await getAreaList({ parentId: value });  
328 - nameTown.forEach((item) => {  
329 - item.label = item.name;  
330 - item.value = item.code;  
331 - });  
332 - updateSchema({  
333 - field: 'nameTown',  
334 - componentProps: {  
335 - placeholder: '城镇/街道',  
336 - options: nameTown,  
337 - },  
338 - });  
339 - }  
340 - },  
341 - },  
342 - });  
343 - }  
344 - },  
345 - },  
346 - });  
347 - }  
348 - },  
349 - };  
350 - },  
351 - },  
352 - {  
353 - field: 'nameCity',  
354 - component: 'Select',  
355 - label: '',  
356 - colProps: {  
357 - span: 6,  
358 - },  
359 - },  
360 - {  
361 - field: 'nameCoun',  
362 - component: 'Select',  
363 - label: '',  
364 - colProps: {  
365 - span: 6,  
366 - },  
367 - componentProps: {  
368 - placeholder: '区/县',  
369 - },  
370 - },  
371 - {  
372 - field: 'nameTown',  
373 - component: 'Select',  
374 - label: '',  
375 - colProps: {  
376 - span: 6,  
377 - },  
378 - componentProps: {  
379 - placeholder: '城镇/街道',  
380 - },  
381 - },  
382 -];  
1 -<template>  
2 - <div class="card">  
3 - <Card :bordered="false" class="card">  
4 - <BasicForm @register="registerForm">  
5 - <template #logoUpload>  
6 - <Upload  
7 - name="avatar"  
8 - list-type="picture-card"  
9 - class="avatar-uploader"  
10 - :show-upload-list="false"  
11 - @preview="handlePreview"  
12 - :customRequest="customUploadLogoPic"  
13 - :before-upload="beforeUploadLogoPic"  
14 - >  
15 - <img v-if="logoPic" :src="logoPic" />  
16 - <div v-else>  
17 - <div style="margin-top: 1.875rem">  
18 - <PlusOutlined style="font-size: 2.5rem" />  
19 - </div>  
20 - <div  
21 - class="ant-upload-text flex"  
22 - style="width: 180px; height: 100px; align-items: center; font-size: 0.5625rem"  
23 - >  
24 - 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过500KB</div  
25 - >  
26 - </div>  
27 - </Upload>  
28 - </template>  
29 - <template #bgUpload>  
30 - <Upload  
31 - name="avatar"  
32 - list-type="picture-card"  
33 - class="avatar-uploader"  
34 - :show-upload-list="false"  
35 - :customRequest="customUploadBgPic"  
36 - :before-upload="beforeUploadBgPic"  
37 - >  
38 - <img v-if="bgPic" :src="bgPic" alt="avatar" />  
39 - <div v-else>  
40 - <div style="margin-top: 1.875rem">  
41 - <PlusOutlined style="font-size: 2.5rem" />  
42 - </div>  
43 - <div  
44 - class="ant-upload-text flex"  
45 - style="width: 280px; height: 100px; align-items: center; font-size: 0.5625rem"  
46 - >  
47 - 支持.PNG、.JPG格式,建议尺寸为1080*1620px,大小不超过5M</div  
48 - >  
49 - </div>  
50 - </Upload>  
51 - </template>  
52 - <template #colorInput="{ model, field }"  
53 - ><Input disabled v-model:value="model[field]">  
54 - <template #prefix> <input type="color" v-model="model[field]" /> </template  
55 - ></Input>  
56 - </template>  
57 -  
58 - <template #homeSwiper>  
59 - <Upload  
60 - v-model:file-list="fileList"  
61 - list-type="picture-card"  
62 - @preview="handlePreview"  
63 - :customRequest="customUploadHomeSwiper"  
64 - :before-upload="beforeUploadHomeSwiper"  
65 - >  
66 - <div v-if="fileList.length < 5">  
67 - <div style="margin-top: 1.875rem">  
68 - <PlusOutlined style="font-size: 2.5rem" />  
69 - </div>  
70 - <div  
71 - class="ant-upload-text flex"  
72 - style="width: 150px; height: 70px; align-items: center; font-size: 0.5625rem"  
73 - >支持.PNG、.JPG格式,建议尺寸为800*600px,大小不超过3M</div  
74 - >  
75 - </div>  
76 - </Upload>  
77 - <Modal :visible="previewVisible" :footer="null" @cancel="handleCancel">  
78 - <img alt="example" style="width: 100%" :src="previewImage" />  
79 - </Modal>  
80 - </template>  
81 - </BasicForm>  
82 - </Card>  
83 - <Loading v-bind="compState" />  
84 - <a-button  
85 - @click="handleUpdateInfo"  
86 - size="large"  
87 - type="primary"  
88 - style="margin-top: 20px; border-radius: 5px"  
89 - >保存信息</a-button  
90 - >  
91 - </div>  
92 -</template>  
93 -  
94 -<script lang="ts">  
95 - import { defineComponent, ref, unref, onMounted } from 'vue';  
96 - import { BasicForm, useForm } from '/@/components/Form/index';  
97 - import { Loading } from '/@/components/Loading/index';  
98 - import { Card, Upload, Input, Modal } from 'ant-design-vue';  
99 - import { PlusOutlined } from '@ant-design/icons-vue';  
100 - import { schemas } from '../config/AppDraw.config';  
101 - import { FileItem, FileInfo } from '../types/index';  
102 - import { logoUpload, bgUpload } from '/@/api/oem/index';  
103 - import { useMessage } from '/@/hooks/web/useMessage';  
104 - import { getAppDesign, updateAppDesign } from '/@/api/oem/index';  
105 - export default defineComponent({  
106 - components: {  
107 - Card,  
108 - BasicForm,  
109 - Upload,  
110 - Loading,  
111 - PlusOutlined,  
112 - Input,  
113 - Modal,  
114 - },  
115 - setup() {  
116 - const compState = ref({  
117 - absolute: false,  
118 - loading: false,  
119 - tip: '拼命加载中...',  
120 - });  
121 - const { createMessage } = useMessage();  
122 - const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({  
123 - schemas,  
124 - showSubmitButton: false,  
125 - showResetButton: false,  
126 - labelWidth: 150,  
127 - wrapperCol: {  
128 - span: 10,  
129 - },  
130 - });  
131 - const previewVisible = ref<boolean>(false);  
132 - const previewImage = ref<string | undefined>('');  
133 - function getBase64(file: File) {  
134 - return new Promise((resolve, reject) => {  
135 - const reader = new FileReader();  
136 - reader.readAsDataURL(file);  
137 - reader.onload = () => resolve(reader.result);  
138 - reader.onerror = (error) => reject(error);  
139 - });  
140 - }  
141 - const handleCancel = () => {  
142 - previewVisible.value = false;  
143 - };  
144 - const handlePreview = async (file: FileItem) => {  
145 - if (!file.url && !file.preview) {  
146 - file.preview = (await getBase64(file.originFileObj)) as string;  
147 - }  
148 - previewImage.value = file.url || file.preview;  
149 - previewVisible.value = true;  
150 - };  
151 - const handleChange = ({ fileList: newFileList }: FileInfo) => {  
152 - fileList.value = newFileList;  
153 - };  
154 -  
155 - // logo图片上传  
156 - const logoPic = ref();  
157 - async function customUploadLogoPic({ file }) {  
158 - if (beforeUploadLogoPic(file)) {  
159 - const formData = new FormData();  
160 - formData.append('file', file);  
161 - const response = await logoUpload(formData);  
162 - if (response.fileStaticUri) {  
163 - logoPic.value = response.fileStaticUri;  
164 - }  
165 - }  
166 - }  
167 - const beforeUploadLogoPic = (file) => {  
168 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
169 - if (!isJpgOrPng) {  
170 - createMessage.error('只能上传图片文件!');  
171 - }  
172 - const isLt2M = (file.size as number) / 1024 < 500;  
173 - if (!isLt2M) {  
174 - createMessage.error('图片大小不能超过500KB!');  
175 - }  
176 - return isJpgOrPng && isLt2M;  
177 - };  
178 -  
179 - // 登录页背景上传  
180 - const bgPic = ref();  
181 - async function customUploadBgPic({ file }) {  
182 - if (beforeUploadBgPic(file)) {  
183 - const formData = new FormData();  
184 - formData.append('file', file);  
185 - const response = await bgUpload(formData);  
186 - if (response.fileStaticUri) {  
187 - bgPic.value = response.fileStaticUri;  
188 - }  
189 - }  
190 - }  
191 - const beforeUploadBgPic = (file) => {  
192 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
193 - if (!isJpgOrPng) {  
194 - createMessage.error('只能上传图片文件!');  
195 - }  
196 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
197 - if (!isLt2M) {  
198 - createMessage.error('图片大小不能超过5MB!');  
199 - }  
200 - return isJpgOrPng && isLt2M;  
201 - };  
202 - // 首页轮播图  
203 - const fileList = ref<FileItem[]>([]);  
204 - async function customUploadHomeSwiper({ file }) {  
205 - if (beforeUploadHomeSwiper(file)) {  
206 - const formData = new FormData();  
207 - formData.append('file', file);  
208 -  
209 - const response = await bgUpload(formData);  
210 - if (response.fileStaticUri) {  
211 - fileList.value.push({  
212 - uid: -Math.random() + '',  
213 - name: response.fileName,  
214 - status: 'done',  
215 - url: response.fileStaticUri,  
216 - });  
217 - const fileArr = fileList.value.filter((item) => {  
218 - return item.percent !== 0;  
219 - });  
220 - fileList.value = fileArr;  
221 - }  
222 - }  
223 - }  
224 -  
225 - const beforeUploadHomeSwiper = (file) => {  
226 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
227 - if (!isJpgOrPng) {  
228 - createMessage.error('只能上传图片文件!');  
229 - }  
230 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
231 - if (!isLt2M) {  
232 - createMessage.error('图片大小不能超过5MB!');  
233 - }  
234 - return isJpgOrPng && isLt2M;  
235 - };  
236 -  
237 - const handleUpdateInfo = async () => {  
238 - try {  
239 - const fieldValue = getFieldsValue();  
240 - // 做换字段  
241 - const homeSwiper = fileList.value.map((item) => item.url);  
242 - const rotation = homeSwiper.join(',');  
243 -  
244 - compState.value.loading = true;  
245 - await updateAppDesign({  
246 - ...fieldValue,  
247 - background: unref(bgPic),  
248 - icon: unref(bgPic),  
249 - logo: unref(logoPic),  
250 - rotation,  
251 - });  
252 - compState.value.loading = false;  
253 - createMessage.success('保存信息成功');  
254 - } catch (e) {  
255 - createMessage.error('保存信息失败');  
256 - }  
257 - };  
258 -  
259 - onMounted(async () => {  
260 - const res = await getAppDesign();  
261 - const rotation = res.rotation ? res.rotation.split(',') : [];  
262 - const arr: any[] = [];  
263 - for (let item of rotation) {  
264 - arr.push({  
265 - uid: -Math.random() + '',  
266 - name: '111',  
267 - url: item,  
268 - status: 'done',  
269 - });  
270 - }  
271 - setFieldsValue(res);  
272 - logoPic.value = res.logo;  
273 - bgPic.value = res.background;  
274 - if (arr[0]?.url === '') return;  
275 - fileList.value = arr;  
276 - });  
277 - return {  
278 - compState,  
279 - fileList,  
280 - registerForm,  
281 - handleUpdateInfo,  
282 - handleCancel,  
283 - handlePreview,  
284 - customUploadLogoPic,  
285 - beforeUploadLogoPic,  
286 - customUploadBgPic,  
287 - beforeUploadBgPic,  
288 - customUploadHomeSwiper,  
289 - beforeUploadHomeSwiper,  
290 - handleChange,  
291 - logoPic,  
292 - bgPic,  
293 - previewVisible,  
294 - previewImage,  
295 - };  
296 - },  
297 - });  
298 -</script>  
299 -  
300 -<style lang="less" scoped>  
301 - .ant-upload-select-picture-card i {  
302 - font-size: 32px;  
303 - color: #999;  
304 - }  
305 -  
306 - .ant-upload-select-picture-card .ant-upload-text {  
307 - margin-top: 8px;  
308 - color: #666;  
309 - }  
310 -</style>  
1 -<template>  
2 - <div class="card">  
3 - <Card :bordered="false" class="card">  
4 - <BasicForm @register="registerForm">  
5 - <template #logoUpload>  
6 - <Upload  
7 - name="avatar"  
8 - list-type="picture-card"  
9 - class="avatar-uploader"  
10 - :show-upload-list="false"  
11 - :customRequest="customUploadLogoPic"  
12 - :before-upload="beforeUploadLogoPic"  
13 - >  
14 - <img v-if="logoPic" :src="logoPic" />  
15 - <div v-else>  
16 - <div style="margin-top: 1.875rem">  
17 - <PlusOutlined style="font-size: 2.5rem" />  
18 - </div>  
19 - <div  
20 - class="ant-upload-text flex"  
21 - style="width: 180px; height: 100px; align-items: center; font-size: 0.5625rem"  
22 - >  
23 - 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过500KB</div  
24 - >  
25 - </div>  
26 - </Upload>  
27 - </template>  
28 - <template #iconUpload>  
29 - <Upload  
30 - name="avatar"  
31 - list-type="picture-card"  
32 - class="avatar-uploader"  
33 - :show-upload-list="false"  
34 - :customRequest="customUploadIconPic"  
35 - :before-upload="beforeUploadIconPic"  
36 - >  
37 - <div v-if="iconPic">  
38 - <img :src="iconPic" class="m-auto" />  
39 - <div style="background-color: #ccc; margin-top: 20px">重新上传</div>  
40 - </div>  
41 - <div v-else>  
42 - <div style="margin-top: 20px">  
43 - <PlusOutlined style="font-size: 30px" />  
44 - </div>  
45 - <div  
46 - class="ant-upload-text flex"  
47 - style="width: 130px; height: 70px; align-items: center; font-size: 0.5625rem"  
48 - >  
49 - 支持.ICON格式,建议尺寸为16*16px</div  
50 - >  
51 - </div>  
52 - </Upload>  
53 - </template>  
54 - <template #bgUpload>  
55 - <Upload  
56 - name="avatar"  
57 - list-type="picture-card"  
58 - class="avatar-uploader"  
59 - :show-upload-list="false"  
60 - :customRequest="customUploadBgPic"  
61 - :before-upload="beforeUploadBgPic"  
62 - >  
63 - <img v-if="bgPic" :src="bgPic" alt="avatar" />  
64 - <div v-else>  
65 - <div style="margin-top: 1.875rem">  
66 - <PlusOutlined style="font-size: 2.5rem" />  
67 - </div>  
68 - <div  
69 - class="ant-upload-text flex"  
70 - style="width: 280px; height: 130px; align-items: center; font-size: 0.5625rem"  
71 - >  
72 - 支持.PNG、.JPG格式,建议尺寸为1920*1080px以上,大小不超过5M</div  
73 - >  
74 - </div>  
75 - </Upload>  
76 - </template>  
77 -  
78 - <template #colorInput="{ model, field }"  
79 - ><Input disabled v-model:value="model[field]">  
80 - <template #prefix> <input type="color" v-model="model[field]" /> </template  
81 - ></Input>  
82 - </template>  
83 - </BasicForm>  
84 - </Card>  
85 - <Loading v-bind="compState" />  
86 - <a-button  
87 - @click="handleUpdateInfo"  
88 - size="large"  
89 - type="primary"  
90 - style="margin-top: 20px; border-radius: 5px"  
91 - >保存信息</a-button  
92 - >  
93 - </div>  
94 -</template>  
95 -  
96 -<script lang="ts">  
97 - import { defineComponent, ref, onMounted, unref } from 'vue';  
98 - import { Card, Upload, Input } from 'ant-design-vue';  
99 - import { BasicForm, useForm } from '/@/components/Form/index';  
100 - import { schemas } from '../config/CVIDraw.config';  
101 - import { Loading } from '/@/components/Loading/index';  
102 - import { useMessage } from '/@/hooks/web/useMessage';  
103 - import type { FileItem } from '/@/components/Upload/src/typing';  
104 - import { logoUpload, iconUpload, bgUpload, getPlatForm, updatePlatForm } from '/@/api/oem/index';  
105 - import { PlusOutlined } from '@ant-design/icons-vue';  
106 - import { useUserStore } from '/@/store/modules/user';  
107 - import { createLocalStorage } from '/@/utils/cache/index';  
108 - import { useTitle } from '@vueuse/core';  
109 - import { useGlobSetting } from '/@/hooks/setting';  
110 - export default defineComponent({  
111 - components: {  
112 - BasicForm,  
113 - Card,  
114 - Loading,  
115 - Upload,  
116 - Input,  
117 - PlusOutlined,  
118 - },  
119 - setup() {  
120 - const compState = ref({  
121 - absolute: false,  
122 - loading: false,  
123 - tip: '拼命加载中...',  
124 - });  
125 - const { createMessage } = useMessage();  
126 - const userStore = useUserStore();  
127 - const storage = createLocalStorage();  
128 - const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({  
129 - schemas,  
130 - showSubmitButton: false,  
131 - showResetButton: false,  
132 - labelWidth: 150,  
133 - wrapperCol: {  
134 - span: 10,  
135 - },  
136 - });  
137 -  
138 - const logoPic = ref();  
139 - const iconPic = ref();  
140 - const bgPic = ref();  
141 - // logo图片上传  
142 - async function customUploadLogoPic({ file }) {  
143 - if (beforeUploadLogoPic(file)) {  
144 - const formData = new FormData();  
145 - formData.append('file', file);  
146 - const response = await logoUpload(formData);  
147 - if (response.fileStaticUri) {  
148 - logoPic.value = response.fileStaticUri;  
149 - }  
150 - }  
151 - }  
152 - const beforeUploadLogoPic = (file: FileItem) => {  
153 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
154 - if (!isJpgOrPng) {  
155 - createMessage.error('只能上传图片文件!');  
156 - }  
157 - const isLt2M = (file.size as number) / 1024 < 500;  
158 - if (!isLt2M) {  
159 - createMessage.error('图片大小不能超过500KB!');  
160 - }  
161 - return isJpgOrPng && isLt2M;  
162 - };  
163 - // Icon上传  
164 - async function customUploadIconPic({ file }) {  
165 - if (beforeUploadIconPic(file)) {  
166 - const formData = new FormData();  
167 - formData.append('file', file);  
168 - const response = await iconUpload(formData);  
169 - if (response.fileStaticUri) {  
170 - iconPic.value = response.fileStaticUri;  
171 - }  
172 - }  
173 - }  
174 - const beforeUploadIconPic = (file: FileItem) => {  
175 - const isJpgOrPng = file.type === 'image/x-icon';  
176 - if (!isJpgOrPng) {  
177 - createMessage.error('只能上传.icon图片文件!');  
178 - }  
179 - const isLt2M = (file.size as number) / 1024 < 500;  
180 - if (!isLt2M) {  
181 - createMessage.error('图片大小不能超过500KB!');  
182 - }  
183 - return isJpgOrPng && isLt2M;  
184 - };  
185 - // 登录页背景上传  
186 - async function customUploadBgPic({ file }) {  
187 - if (beforeUploadBgPic(file)) {  
188 - const formData = new FormData();  
189 - formData.append('file', file);  
190 - const response = await bgUpload(formData);  
191 - if (response.fileStaticUri) {  
192 - bgPic.value = response.fileStaticUri;  
193 - }  
194 - }  
195 - }  
196 - const beforeUploadBgPic = (file: FileItem) => {  
197 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
198 - if (!isJpgOrPng) {  
199 - createMessage.error('只能上传图片文件!');  
200 - }  
201 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
202 - if (!isLt2M) {  
203 - createMessage.error('图片大小不能超过5MB!');  
204 - }  
205 - return isJpgOrPng && isLt2M;  
206 - };  
207 -  
208 - // 更新  
209 - const handleUpdateInfo = async () => {  
210 - try {  
211 - const fieldValue = getFieldsValue();  
212 - compState.value.loading = true;  
213 - const newFieldValue = {  
214 - ...fieldValue,  
215 - logo: unref(logoPic),  
216 - icon: unref(iconPic),  
217 - background: unref(bgPic),  
218 - };  
219 - await updatePlatForm(newFieldValue);  
220 - compState.value.loading = false;  
221 - createMessage.success('保存信息成功');  
222 -  
223 - setPlatFormInfo(newFieldValue);  
224 - } catch (e) {  
225 - createMessage.error('保存信息失败');  
226 - }  
227 - };  
228 - // 设置平台信息  
229 - function setPlatFormInfo(newFieldValue) {  
230 - // 保存store  
231 - userStore.setPlatInfo(newFieldValue);  
232 - // 保存本地缓存  
233 - storage.set('platInfo', newFieldValue);  
234 - const { title } = useGlobSetting();  
235 - useTitle(`OEM定制 - ${newFieldValue.name === '' ? title : newFieldValue.name}`);  
236 - }  
237 -  
238 - onMounted(async () => {  
239 - const res = await getPlatForm();  
240 - setFieldsValue(res);  
241 - logoPic.value = res.logo;  
242 - iconPic.value = res.icon;  
243 - bgPic.value = res.background;  
244 - });  
245 - return {  
246 - registerForm,  
247 - logoPic,  
248 - iconPic,  
249 - bgPic,  
250 - customUploadLogoPic,  
251 - beforeUploadLogoPic,  
252 - customUploadIconPic,  
253 - beforeUploadIconPic,  
254 - customUploadBgPic,  
255 - beforeUploadBgPic,  
256 - compState,  
257 - handleUpdateInfo,  
258 - };  
259 - },  
260 - });  
261 -</script>  
262 -  
263 -<style lang="less" scoped></style>  
1 -<template>  
2 - <div class="card">  
3 - <Card :bordered="false" class="card">  
4 - <BasicForm @register="registerForm">  
5 - <template #qrcode>  
6 - <Upload  
7 - name="avatar"  
8 - list-type="picture-card"  
9 - class="avatar-uploader"  
10 - :show-upload-list="false"  
11 - :customRequest="customUploadqrcodePic"  
12 - :before-upload="beforeUploadqrcodePic"  
13 - >  
14 - <img v-if="qrcodePic" :src="qrcodePic" alt="avatar" />  
15 - <div v-else>  
16 - <div style="margin-top: 1.875rem">  
17 - <PlusOutlined style="font-size: 2.5rem" />  
18 - </div>  
19 - <div  
20 - class="ant-upload-text flex"  
21 - style="width: 180px; height: 100px; align-items: center; font-size: 0.5625rem"  
22 - >  
23 - 支持.PNG、.JPG格式,建议尺寸为300*300px,大小不超过2M</div  
24 - >  
25 - </div>  
26 - </Upload>  
27 - </template>  
28 - <template #customProv>  
29 - <BasicForm @register="registerCustomForm" />  
30 - </template>  
31 - </BasicForm>  
32 - </Card>  
33 - <Loading v-bind="compState" />  
34 - <a-button  
35 - @click="handleUpdateInfo"  
36 - size="large"  
37 - type="primary"  
38 - style="margin-top: 1rem; border-radius: 0.5rem"  
39 - >更新基本信息</a-button  
40 - >  
41 - </div>  
42 -</template>  
43 -  
44 -<script lang="ts">  
45 - import { defineComponent, onMounted, ref } from 'vue';  
46 - import { Card, Upload } from 'ant-design-vue';  
47 - import { BasicForm, useForm } from '/@/components/Form/index';  
48 - import { schemas, provSchemas } from '../config/enterPriseInfo.config';  
49 - import { getAreaList, getEnterPriseDetail, updateEnterPriseDetail } from '/@/api/oem/index';  
50 - import { Loading } from '/@/components/Loading';  
51 - import { useMessage } from '/@/hooks/web/useMessage';  
52 - import { useUserStore } from '/@/store/modules/user';  
53 - import { createLocalStorage } from '/@/utils/cache';  
54 - import { PlusOutlined } from '@ant-design/icons-vue';  
55 - import { qrcodeUpload } from '/@/api/oem/index';  
56 - import type { FileItem } from '/@/components/Upload/src/typing';  
57 - import type { CityItem, Code } from '../types';  
58 - export default defineComponent({  
59 - components: {  
60 - Card,  
61 - BasicForm,  
62 - Loading,  
63 - Upload,  
64 - PlusOutlined,  
65 - },  
66 - setup() {  
67 - const compState = ref({  
68 - absolute: false,  
69 - loading: false,  
70 - tip: '拼命加载中...',  
71 - });  
72 - const [registerForm, { getFieldsValue, setFieldsValue, validate }] = useForm({  
73 - labelWidth: 80,  
74 - schemas,  
75 - showResetButton: false,  
76 - showSubmitButton: false,  
77 - wrapperCol: {  
78 - span: 12,  
79 - },  
80 - });  
81 -  
82 - const [  
83 - registerCustomForm,  
84 - { getFieldsValue: getNameTown, updateSchema, setFieldsValue: setNameTown },  
85 - ] = useForm({  
86 - labelWidth: 80,  
87 - schemas: provSchemas,  
88 - showResetButton: false,  
89 - showSubmitButton: false,  
90 - compact: true,  
91 - actionColOptions: {  
92 - span: 0,  
93 - },  
94 - });  
95 -  
96 - const { createMessage } = useMessage();  
97 -  
98 - const qrcodePic = ref();  
99 - const customUploadqrcodePic = async ({ file }) => {  
100 - if (beforeUploadqrcodePic(file)) {  
101 - const formData = new FormData();  
102 - formData.append('file', file);  
103 - const response = await qrcodeUpload(formData);  
104 - if (response.fileStaticUri) {  
105 - qrcodePic.value = response.fileStaticUri;  
106 - }  
107 - }  
108 - };  
109 - const beforeUploadqrcodePic = (file: FileItem) => {  
110 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
111 - if (!isJpgOrPng) {  
112 - createMessage.error('只能上传图片文件!');  
113 - }  
114 - const isLt2M = (file.size as number) / 1024 / 1024 < 2;  
115 - if (!isLt2M) {  
116 - createMessage.error('图片大小不能超过2MB!');  
117 - }  
118 - return isJpgOrPng && isLt2M;  
119 - };  
120 - // 更新  
121 - const handleUpdateInfo = async () => {  
122 - try {  
123 - const fieldsValue = getFieldsValue();  
124 - const { nameTown } = getNameTown();  
125 - const newFieldValue: any = {  
126 - ...fieldsValue,  
127 - codeTown: nameTown,  
128 - qrCode: qrcodePic.value,  
129 - };  
130 - delete newFieldValue.nameProv;  
131 - delete newFieldValue.nameCity;  
132 - delete newFieldValue.nameCoun;  
133 - delete newFieldValue.nameTown;  
134 -  
135 - // 表单校验  
136 - await validate();  
137 - compState.value.loading = true;  
138 - await updateEnterPriseDetail(newFieldValue);  
139 - createMessage.success('更新信息成功');  
140 - setEnterPriseInfo(newFieldValue);  
141 - } finally {  
142 - compState.value.loading = false;  
143 - }  
144 - };  
145 -  
146 - const userStore = useUserStore();  
147 - const storage = createLocalStorage();  
148 -  
149 - // 设置企业信息  
150 - function setEnterPriseInfo(newFieldValue) {  
151 - // 保存store  
152 - userStore.setEnterPriseInfo(newFieldValue);  
153 - // 保存本地缓存  
154 - storage.set('enterpriseInfo', newFieldValue);  
155 - }  
156 -  
157 - // 地区显示回显和数据联动  
158 - async function updateCityData(  
159 - cities: CityItem[],  
160 - couns: CityItem[],  
161 - towns: CityItem[],  
162 - code: Code  
163 - ) {  
164 - // 加工后端返回字段  
165 -  
166 - cities.forEach((item) => {  
167 - item.label = item.name;  
168 - item.value = item.code;  
169 - });  
170 -  
171 - couns.forEach((item) => {  
172 - item.label = item.name;  
173 - item.value = item.code;  
174 - });  
175 - towns.forEach((item) => {  
176 - item.label = item.name;  
177 - item.value = item.code;  
178 - });  
179 - const { codeProv, codeCity, codeCoun, codeTown } = code;  
180 - updateSchema([  
181 - {  
182 - field: 'nameCity',  
183 - componentProps: ({ formModel }) => {  
184 - return {  
185 - options: cities,  
186 - async onChange(value) {  
187 - if (value === undefined) {  
188 - formModel.nameCoun = undefined; // reset city value  
189 - formModel.nameTown = undefined;  
190 - updateSchema([  
191 - {  
192 - field: 'nameCoun',  
193 - componentProps: {  
194 - options: [],  
195 - },  
196 - },  
197 - {  
198 - field: 'nameTown',  
199 - componentProps: {  
200 - options: [],  
201 - },  
202 - },  
203 - ]);  
204 - } else {  
205 - let couns: CityItem[] = await getAreaList({ parentId: value });  
206 - couns.forEach((item) => {  
207 - item.label = item.name;  
208 - item.value = item.code;  
209 - });  
210 - formModel.nameCoun = undefined; // reset city value  
211 - formModel.nameTown = undefined;  
212 - updateSchema({  
213 - field: 'nameCoun',  
214 - componentProps: {  
215 - // 请选择区  
216 - options: couns,  
217 - async onChange(value) {  
218 - if (value === undefined) {  
219 - formModel.nameTown = undefined;  
220 - } else {  
221 - let towns: CityItem[] = await getAreaList({ parentId: value });  
222 - towns.forEach((item) => {  
223 - item.label = item.name;  
224 - item.value = item.code;  
225 - });  
226 - formModel.nameTown = undefined;  
227 - updateSchema({  
228 - field: 'nameTown',  
229 - componentProps: {  
230 - placeholder: '城镇/街道',  
231 - options: towns,  
232 - },  
233 - });  
234 - }  
235 - },  
236 - },  
237 - });  
238 - }  
239 - },  
240 - };  
241 - },  
242 - },  
243 - {  
244 - field: 'nameCoun',  
245 - componentProps: {  
246 - options: couns,  
247 - async onChange(value) {  
248 - if (value === undefined) {  
249 - setNameTown({  
250 - nameTown: undefined,  
251 - });  
252 - updateSchema({  
253 - field: 'nameTown',  
254 - componentProps: {  
255 - placeholder: '城镇/街道',  
256 - options: [],  
257 - },  
258 - });  
259 - } else {  
260 - let towns = await getAreaList({ parentId: value });  
261 - towns.forEach((item) => {  
262 - item.label = item.name;  
263 - item.value = item.code;  
264 - });  
265 - setNameTown({  
266 - nameTown: undefined,  
267 - });  
268 - updateSchema({  
269 - field: 'nameTown',  
270 - componentProps: {  
271 - placeholder: '城镇/街道',  
272 - options: towns,  
273 - },  
274 - });  
275 - }  
276 - },  
277 - },  
278 - },  
279 - {  
280 - field: 'nameTown',  
281 - componentProps: {  
282 - options: towns,  
283 - },  
284 - },  
285 - ]);  
286 - setNameTown({  
287 - nameProv: codeProv,  
288 - nameCity: codeCity,  
289 - nameCoun: codeCoun,  
290 - nameTown: codeTown,  
291 - });  
292 - }  
293 -  
294 - onMounted(async () => {  
295 - const res = await getEnterPriseDetail();  
296 - if (res.sysTown) {  
297 - const { cities, couns, towns, codeCountry, codeProv, codeCity, codeCoun, codeTown } =  
298 - res.sysTown;  
299 - const code = {  
300 - codeCountry,  
301 - codeProv,  
302 - codeCity,  
303 - codeCoun,  
304 - codeTown,  
305 - };  
306 - updateCityData(cities, couns, towns, code);  
307 - setFieldsValue({ nameCountry: codeCountry });  
308 - }  
309 - setFieldsValue(res);  
310 - console.log(res);  
311 - qrcodePic.value = res.qrCode;  
312 - });  
313 -  
314 - return {  
315 - registerForm,  
316 - compState,  
317 - qrcodePic,  
318 - handleUpdateInfo,  
319 - customUploadqrcodePic,  
320 - beforeUploadqrcodePic,  
321 - registerCustomForm,  
322 - };  
323 - },  
324 - });  
325 -</script>  
1 -<template>  
2 - <div class="platform flex">  
3 - <Card class="tab-card" :bordered="false">  
4 - <Tabs v-model:activeKey="activeKey" tab-position="left">  
5 - <Tabs.TabPane key="企业信息" tab="企业信息" />  
6 - <Tabs.TabPane key="平台定制" tab="平台定制" />  
7 - <Tabs.TabPane key="APP定制" tab="APP定制" />  
8 - </Tabs>  
9 - </Card>  
10 -  
11 - <div style="width: 100%">  
12 - <Card class="card" :title="activeKey" :bordered="false" :bodyStyle="{ display: 'none' }" />  
13 - <EnterpriseInfo v-if="activeKey === '企业信息'" />  
14 - <CVIDraw v-else-if="activeKey === '平台定制'" />  
15 - <AppDraw v-else />  
16 - </div>  
17 - </div>  
18 -</template>  
19 -  
20 -<script lang="ts" setup>  
21 - import { Tabs, Card } from 'ant-design-vue';  
22 - import { ref } from 'vue';  
23 - import EnterpriseInfo from './cpns/EnterpriseInfo.vue';  
24 - import CVIDraw from './cpns/CVIDraw.vue';  
25 - import AppDraw from './cpns/AppDraw.vue';  
26 -  
27 - const activeKey = ref('企业信息');  
28 -</script>  
29 -  
30 -<style lang="less" scoped>  
31 - .title {  
32 - width: 97.4%;  
33 - height: 50px;  
34 - margin: 1rem;  
35 - line-height: 50px;  
36 - font-size: 18px;  
37 - padding-left: 10px;  
38 - background-color: #fff;  
39 - }  
40 - .tab-card {  
41 - margin: 1rem 0 1rem 1rem;  
42 - }  
43 - .card {  
44 - margin: 1rem;  
45 - }  
46 -</style>  
1 -export interface FileItem {  
2 - uid: string;  
3 - name?: string;  
4 - status?: string;  
5 - response?: string;  
6 - percent?: number;  
7 - url?: string;  
8 - preview?: string;  
9 - originFileObj?: any;  
10 -}  
11 -  
12 -export interface FileInfo {  
13 - file: FileItem;  
14 - fileList: FileItem[];  
15 -}  
16 -  
17 -export interface CityItem {  
18 - code: number;  
19 - level: string;  
20 - name: string;  
21 - parentId: number;  
22 - label?: string;  
23 - value?: number;  
24 -}  
25 -export interface Code {  
26 - codeCountry: number;  
27 - codeProv: number;  
28 - codeCity: number;  
29 - codeCoun: number;  
30 - codeTown: number;  
31 -}