Commit b042fdeb59f1bf37d90b970654831f9eae5460bf

Authored by sqy
1 parent 656b64d2

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

Showing 53 changed files with 11 additions and 9957 deletions
1 1 import { generate } from '@ant-design/colors';
2 2
3   -export const primaryColor = '#0960bd';
  3 +export const primaryColor = '#377DFF';
4 4
5 5 export const darkMode = 'light';
6 6
... ...
... ... @@ -10,21 +10,21 @@ export default {
10 10 status: 'status',
11 11 },
12 12 notice: {
13   - webSiteNotice: 'web site notice',
  13 + webSiteNotice: 'platform notice',
14 14 noticeManagement: 'notice management',
15 15 myNotice: 'my notice',
16 16 },
17 17
18 18 device: {
19 19 deviceManagement: 'device management',
20   - device: 'device',
  20 + device: 'device management',
21 21 deviceProfile: 'device profile',
22 22 },
23 23 tenant: {
24 24 tenant: 'tenant',
25 25 tenantManagement: 'tenant management',
26 26 tenantSetting: 'tenant config',
27   - tenantOEM: 'OEM customization',
  27 + tenantOEM: 'platform customization',
28 28 tenantRule: 'tenant rule',
29 29 },
30 30
... ... @@ -49,23 +49,9 @@ export default {
49 49 alarmManagement: 'alarm management',
50 50 geographicPosition: 'geographic position',
51 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 55 system: {
70 56 system: 'system',
71 57 accountManagement: 'account management',
... ...
... ... @@ -10,13 +10,13 @@ export default {
10 10 status: '状态',
11 11 },
12 12 notice: {
13   - webSiteNotice: '站内通知',
  13 + webSiteNotice: '平台通知',
14 14 noticeManagement: '通知管理',
15 15 myNotice: '我的通知',
16 16 },
17 17 device: {
18 18 deviceManagement: '设备管理',
19   - device: '设备',
  19 + device: '设备管理',
20 20 deviceProfile: '设备配置',
21 21 },
22 22
... ... @@ -24,7 +24,7 @@ export default {
24 24 tenant: '租户',
25 25 tenantManagement: '租户管理',
26 26 tenantSetting: '租户配置',
27   - tenantOEM: 'OEM定制',
  27 + tenantOEM: '平台定制',
28 28 tenantRule: '租户角色',
29 29 },
30 30 organization: {
... ... @@ -34,20 +34,7 @@ export default {
34 34 toolEditOrganization: '编辑组织',
35 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 38 RuleEngine: {
52 39 ruleEngine: '规则引擎',
53 40 sceneLinkage: '场景联动',
... ... @@ -62,7 +49,7 @@ export default {
62 49 alarmManagement: '告警管理',
63 50 geographicPosition: '地理位置',
64 51 alarmContact: '告警联系人',
65   - alarmCenter: '告警中心',
  52 + alarmCenter: '告警记录',
66 53 },
67 54 system: {
68 55 system: '系统管理',
... ...
... ... @@ -78,7 +78,7 @@ const setting: ProjectConfig = {
78 78 // Menu configuration
79 79 menuSetting: {
80 80 // sidebar menu bg color
81   - bgColor: SIDE_BAR_BG_COLOR_LIST[0],
  81 + bgColor: SIDE_BAR_BG_COLOR_LIST[3],
82 82 // Whether to fix the left menu
83 83 fixed: true,
84 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   -}