Commit 7f2df5aab5a3302d7e3557344776f22d1fb03ed8

Authored by xp.Huang
2 parents 7498544c e42fbe00

Merge branch 'dev-fix-ww' into 'main_dev'

fix: 修复teabmition BUG

See merge request yunteng/thingskit-front!562
... ... @@ -51,6 +51,7 @@ export interface DeviceModel {
51 51 organizationId: string;
52 52 customerId?: string;
53 53 alias?: string;
  54 + tbDeviceId?: string;
54 55 }
55 56
56 57 export interface DeviceProfileModel {
... ...
... ... @@ -81,11 +81,8 @@ export const genModbusCommand = (data: GenModbusCommandType) => {
81 81 };
82 82
83 83 export const immediateExecute = (data: ImmediateExecuteTaskType) => {
84   - return defHttp.post<Record<'data', boolean>>(
85   - {
86   - url: Api.IMMEDIATE_EXECUTE,
87   - params: data,
88   - },
89   - { joinParamsToUrl: true }
90   - );
  84 + return defHttp.post<Record<'data', boolean>>({
  85 + url: Api.IMMEDIATE_EXECUTE,
  86 + params: data,
  87 + });
91 88 };
... ...
... ... @@ -108,7 +108,7 @@
108 108 </script>
109 109
110 110 <template>
111   - <div class="p-2 bg-gray-200" :style="{ height: `${height - 16}px` }">
  111 + <div class="p-2 bg-gray-200" :style="{ height: `${height}px` }">
112 112 <div ref="jsonEditorElRef" class="jsoneditor"></div>
113 113 </div>
114 114 </template>
... ... @@ -119,6 +119,11 @@
119 119
120 120 :deep(.jsoneditor) {
121 121 border: none !important;
  122 +
  123 + .ace-jsoneditor,
  124 + textarea.jsoneditor-text {
  125 + min-height: auto;
  126 + }
122 127 }
123 128 }
124 129 </style>
... ...
... ... @@ -133,6 +133,7 @@
133 133 } = props.schema;
134 134
135 135 if (isFunction(dynamicRules)) {
  136 + console.log(dynamicRules(unref(getValues)));
136 137 return dynamicRules(unref(getValues)) as ValidationRule[];
137 138 }
138 139
... ...
... ... @@ -279,7 +279,6 @@
279 279 setSelectedOptions,
280 280 setSelectedTotal,
281 281 reloadPending,
282   - reloadPending,
283 282 reloadSelected,
284 283 };
285 284
... ... @@ -408,7 +407,7 @@
408 407 :key="item.value"
409 408 >
410 409 <span>
411   - {{ item.alias + '/' + item.name }}
  410 + {{ item.alias || item.name }}
412 411 </span>
413 412 </Tag>
414 413 <Tag class="!px-2 !py-1 !bg-gray-50 !border-gray-100" v-if="getSurplusOptionsLength">
... ...
1 1 import { BasicColumn, FormSchema } from '/@/components/Table';
2   -import { getOrganizationList } from '/@/api/system/system';
3   -import { copyTransFun } from '/@/utils/fnUtils';
4 2 import { findDictItemByCode } from '/@/api/system/dict';
5   -
  3 +import { useComponentRegister } from '/@/components/Form';
  4 +import { OrgTreeSelect } from '../../common/OrgTreeSelect';
  5 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
6 6 // 表格列数据
7 7 export const columns: BasicColumn[] = [
8 8 {
... ... @@ -98,19 +98,8 @@ export const formSchema: FormSchema[] = [
98 98 {
99 99 field: 'organizationId',
100 100 label: '所属组织',
101   - component: 'ApiTreeSelect',
  101 + component: 'OrgTreeSelect',
102 102 required: true,
103   - componentProps: () => {
104   - return {
105   - maxLength: 250,
106   - placeholder: '请选择所属组织',
107   - api: async () => {
108   - const data = await getOrganizationList();
109   - copyTransFun(data as any as any[]);
110   - return data;
111   - },
112   - };
113   - },
114 103 },
115 104 {
116 105 field: 'alarmContactId',
... ...
1 1 import { BasicColumn, FormSchema } from '/@/components/Table';
2   -import { getOrganizationList } from '/@/api/system/system';
3   -import { copyTransFun } from '/@/utils/fnUtils';
4 2 import { emailRule, phoneRule } from '/@/utils/rules';
5   -
  3 +import { useComponentRegister } from '/@/components/Form';
  4 +import { OrgTreeSelect } from '../../common/OrgTreeSelect';
  5 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
6 6 // 表格列数据
7 7 export const columns: BasicColumn[] = [
8 8 {
... ... @@ -78,14 +78,7 @@ export const formSchema: FormSchema[] = [
78 78 field: 'organizationId',
79 79 label: '所属组织',
80 80 required: true,
81   - component: 'ApiTreeSelect',
82   - componentProps: {
83   - api: async () => {
84   - const data = await getOrganizationList();
85   - copyTransFun(data as any as any[]);
86   - return data;
87   - },
88   - },
  81 + component: 'OrgTreeSelect',
89 82 },
90 83 {
91 84 field: 'phone',
... ...
1   -import { BasicColumn, FormSchema } from '/@/components/Table';
2   -import { getOrganizationList } from '/@/api/system/system';
3   -import { copyTransFun } from '/@/utils/fnUtils';
4   -import type { FormSchema as QFormSchema } from '/@/components/Form/index';
5   -
6   -import { CameraVideoUrl, CameraMaxLength } from '/@/utils/rules';
7   -import { h } from 'vue';
8   -import SnHelpMessage from './SnHelpMessage.vue';
9   -
10   -export enum CameraPermission {
11   - PREVIEW = 'api:yt:video:get',
12   - CREATE = 'api:yt:video:post',
13   - UPDATE = 'api:yt:video:update',
14   - DELETE = 'api:yt:video:delete',
15   -}
16   -
17   -export enum AccessMode {
18   - ManuallyEnter = 0,
19   - Streaming = 1,
20   -}
21   -
22   -export enum PlayProtocol {
23   - HTTP = 0,
24   - HTTPS = 1,
25   -}
26   -
27   -export enum StreamType {
28   - MASTER = 0,
29   - CHILD = 1,
30   - THIRD = 2,
31   -}
32   -
33   -export enum PageMode {
34   - SPLIT_SCREEN_MODE = 'splitScreen',
35   - LIST_MODE = 'listMode',
36   - FULL_SCREEN_MODE = 'fullScreenMode',
37   -}
38   -
39   -export enum MediaType {
40   - MP4 = 'mp4',
41   - M3U8 = 'm3u8',
42   -}
43   -
44   -// 表格列数据
45   -export const columns: BasicColumn[] = [
46   - {
47   - title: '封面',
48   - dataIndex: 'avatar',
49   - width: 80,
50   - slots: { customRender: 'img' },
51   - },
52   - {
53   - title: '名字',
54   - dataIndex: 'name',
55   - width: 120,
56   - },
57   - {
58   - title: '摄像头编号/监控点编号',
59   - dataIndex: 'sn',
60   - width: 220,
61   - },
62   - {
63   - title: '视频流',
64   - dataIndex: 'videoUrl',
65   - width: 120,
66   - },
67   - {
68   - title: '所属组织',
69   - dataIndex: 'organizationName',
70   - width: 160,
71   - },
72   - {
73   - title: '获取方式',
74   - dataIndex: 'accessMode',
75   - width: 100,
76   - slots: { customRender: 'accessMode' },
77   - },
78   - {
79   - title: '创建时间',
80   - dataIndex: 'createTime',
81   - width: 140,
82   - },
83   -];
84   -
85   -// 查询字段
86   -export const searchFormSchema: FormSchema[] = [
87   - {
88   - field: 'name',
89   - label: '摄像头名字',
90   - component: 'Input',
91   - colProps: { span: 8 },
92   - componentProps: {
93   - maxLength: 36,
94   - placeholder: '请输入摄像头名字',
95   - },
96   - },
97   -];
98   -
99   -// 弹框配置项
100   -export const formSchema: QFormSchema[] = [
101   - {
102   - field: 'avatar',
103   - label: '视频封面',
104   - slot: 'iconSelect',
105   - component: 'Input',
106   - },
107   - {
108   - field: 'name',
109   - label: '视频名字',
110   - required: true,
111   - component: 'Input',
112   - componentProps: {
113   - placeholder: '请输入视频名字',
114   - maxLength: 30,
115   - },
116   - rules: [...CameraMaxLength, { required: true, message: '视频名是必填项' }],
117   - },
118   - {
119   - field: 'organizationId',
120   - label: '所属组织',
121   - required: true,
122   - component: 'ApiTreeSelect',
123   - componentProps: {
124   - api: async () => {
125   - const data = await getOrganizationList();
126   - copyTransFun(data as any as any[]);
127   - return data;
128   - },
129   - },
130   - },
131   - {
132   - label: '视频流获取方式',
133   - field: 'accessMode',
134   - component: 'RadioGroup',
135   - rules: [{ required: true, message: '视频流获取方式为必选项', type: 'number' }],
136   - defaultValue: AccessMode.ManuallyEnter,
137   - componentProps({ formActionType }) {
138   - return {
139   - defaultValue: AccessMode.ManuallyEnter,
140   - placeholder: '请选择视频流获取方式',
141   - options: [
142   - { label: '手动输入', value: AccessMode.ManuallyEnter },
143   - { label: '流媒体获取', value: AccessMode.Streaming },
144   - ],
145   - onChange() {
146   - formActionType.setFieldsValue({
147   - brand: null,
148   - sn: null,
149   - videoUrl: null,
150   - videoPlatformId: null,
151   - });
152   - },
153   - };
154   - },
155   - },
156   - {
157   - field: 'brand',
158   - label: '视频厂家',
159   - component: 'Input',
160   - ifShow({ values }) {
161   - return values.accessMode === AccessMode.ManuallyEnter;
162   - },
163   - componentProps: {
164   - maxLength: 36,
165   - placeholder: '请输入视频厂家',
166   - },
167   - },
168   - {
169   - field: 'sn',
170   - label: '摄像头编号',
171   - required: true,
172   - component: 'Input',
173   - rules: [...CameraVideoUrl, { required: true, message: '摄像头编号是必填项' }],
174   - ifShow({ values }) {
175   - return values.accessMode === AccessMode.ManuallyEnter;
176   - },
177   - componentProps: {
178   - maxLength: 36,
179   - placeholder: '请输入摄像头编号',
180   - },
181   - },
182   - {
183   - field: 'videoUrl',
184   - label: '视频流',
185   - component: 'Input',
186   - required: true,
187   - ifShow({ values }) {
188   - return values.accessMode === AccessMode.ManuallyEnter;
189   - },
190   - componentProps: {
191   - placeholder: '请输入视频流',
192   - maxLength: 255,
193   - },
194   - rules: [{ required: true, message: '视频流是必填项' }, ...CameraVideoUrl],
195   - },
196   -
197   - {
198   - field: 'videoPlatformId',
199   - label: '流媒体配置',
200   - component: 'Select',
201   - ifShow({ values }) {
202   - return values.accessMode === AccessMode.Streaming;
203   - },
204   - slot: 'videoPlatformIdSlot',
205   - componentProps: {
206   - placeholder: '请选择流媒体配置',
207   - },
208   - },
209   - {
210   - field: 'streamType',
211   - label: '码流',
212   - component: 'RadioGroup',
213   - defaultValue: StreamType.MASTER,
214   - ifShow({ values }) {
215   - return values.accessMode === AccessMode.Streaming;
216   - },
217   - componentProps: {
218   - placeholder: '请选择码流',
219   - defaultValue: StreamType.MASTER,
220   - options: [
221   - { label: '主码流', value: StreamType.MASTER },
222   - { label: '子码流', value: StreamType.CHILD },
223   - { label: '第三码流', value: StreamType.THIRD },
224   - ],
225   - },
226   - },
227   - {
228   - field: 'playProtocol',
229   - label: '播放协议',
230   - component: 'RadioGroup',
231   - defaultValue: PlayProtocol.HTTP,
232   - ifShow({ values }) {
233   - return values.accessMode === AccessMode.Streaming;
234   - },
235   - helpMessage: ['平台使用https的hls协议,需联系海康开放平台专家支持。'],
236   - componentProps: {
237   - placeholder: '请选择播放协议',
238   - defaultValue: PlayProtocol.HTTP,
239   - options: [
240   - { label: 'http', value: PlayProtocol.HTTP },
241   - { label: 'https', value: PlayProtocol.HTTPS },
242   - ],
243   - },
244   - },
245   - {
246   - field: 'sn',
247   - label: h(SnHelpMessage) as any,
248   - component: 'Input',
249   - rules: [...CameraVideoUrl, { required: true, message: '摄像头编号是必填项' }],
250   - ifShow({ values }) {
251   - return values.accessMode === AccessMode.Streaming;
252   - },
253   - componentProps: {
254   - placeholder: '请输入监控点编号',
255   - },
256   - },
257   -];
  1 +import { BasicColumn, FormSchema } from '/@/components/Table';
  2 +import { FormSchema as QFormSchema, useComponentRegister } from '/@/components/Form/index';
  3 +
  4 +import { CameraVideoUrl, CameraMaxLength } from '/@/utils/rules';
  5 +import { h } from 'vue';
  6 +import SnHelpMessage from './SnHelpMessage.vue';
  7 +import { OrgTreeSelect } from '../../common/OrgTreeSelect';
  8 +
  9 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
  10 +
  11 +export enum CameraPermission {
  12 + PREVIEW = 'api:yt:video:get',
  13 + CREATE = 'api:yt:video:post',
  14 + UPDATE = 'api:yt:video:update',
  15 + DELETE = 'api:yt:video:delete',
  16 +}
  17 +
  18 +export enum AccessMode {
  19 + ManuallyEnter = 0,
  20 + Streaming = 1,
  21 +}
  22 +
  23 +export enum PlayProtocol {
  24 + HTTP = 0,
  25 + HTTPS = 1,
  26 +}
  27 +
  28 +export enum StreamType {
  29 + MASTER = 0,
  30 + CHILD = 1,
  31 + THIRD = 2,
  32 +}
  33 +
  34 +export enum PageMode {
  35 + SPLIT_SCREEN_MODE = 'splitScreen',
  36 + LIST_MODE = 'listMode',
  37 + FULL_SCREEN_MODE = 'fullScreenMode',
  38 +}
  39 +
  40 +export enum MediaType {
  41 + MP4 = 'mp4',
  42 + M3U8 = 'm3u8',
  43 +}
  44 +
  45 +// 表格列数据
  46 +export const columns: BasicColumn[] = [
  47 + {
  48 + title: '封面',
  49 + dataIndex: 'avatar',
  50 + width: 80,
  51 + slots: { customRender: 'img' },
  52 + },
  53 + {
  54 + title: '名字',
  55 + dataIndex: 'name',
  56 + width: 120,
  57 + },
  58 + {
  59 + title: '摄像头编号/监控点编号',
  60 + dataIndex: 'sn',
  61 + width: 220,
  62 + },
  63 + {
  64 + title: '视频流',
  65 + dataIndex: 'videoUrl',
  66 + width: 120,
  67 + },
  68 + {
  69 + title: '所属组织',
  70 + dataIndex: 'organizationName',
  71 + width: 160,
  72 + },
  73 + {
  74 + title: '获取方式',
  75 + dataIndex: 'accessMode',
  76 + width: 100,
  77 + slots: { customRender: 'accessMode' },
  78 + },
  79 + {
  80 + title: '创建时间',
  81 + dataIndex: 'createTime',
  82 + width: 140,
  83 + },
  84 +];
  85 +
  86 +// 查询字段
  87 +export const searchFormSchema: FormSchema[] = [
  88 + {
  89 + field: 'name',
  90 + label: '摄像头名字',
  91 + component: 'Input',
  92 + colProps: { span: 8 },
  93 + componentProps: {
  94 + maxLength: 36,
  95 + placeholder: '请输入摄像头名字',
  96 + },
  97 + },
  98 +];
  99 +
  100 +// 弹框配置项
  101 +export const formSchema: QFormSchema[] = [
  102 + {
  103 + field: 'avatar',
  104 + label: '视频封面',
  105 + slot: 'iconSelect',
  106 + component: 'Input',
  107 + },
  108 + {
  109 + field: 'name',
  110 + label: '视频名字',
  111 + required: true,
  112 + component: 'Input',
  113 + componentProps: {
  114 + placeholder: '请输入视频名字',
  115 + maxLength: 30,
  116 + },
  117 + rules: [...CameraMaxLength, { required: true, message: '视频名是必填项' }],
  118 + },
  119 + {
  120 + field: 'organizationId',
  121 + label: '所属组织',
  122 + required: true,
  123 + component: 'OrgTreeSelect',
  124 + },
  125 + {
  126 + label: '视频流获取方式',
  127 + field: 'accessMode',
  128 + component: 'RadioGroup',
  129 + rules: [{ required: true, message: '视频流获取方式为必选项', type: 'number' }],
  130 + defaultValue: AccessMode.ManuallyEnter,
  131 + componentProps({ formActionType }) {
  132 + return {
  133 + defaultValue: AccessMode.ManuallyEnter,
  134 + placeholder: '请选择视频流获取方式',
  135 + options: [
  136 + { label: '手动输入', value: AccessMode.ManuallyEnter },
  137 + { label: '流媒体获取', value: AccessMode.Streaming },
  138 + ],
  139 + onChange() {
  140 + formActionType.setFieldsValue({
  141 + brand: null,
  142 + sn: null,
  143 + videoUrl: null,
  144 + videoPlatformId: null,
  145 + });
  146 + },
  147 + };
  148 + },
  149 + },
  150 + {
  151 + field: 'brand',
  152 + label: '视频厂家',
  153 + component: 'Input',
  154 + ifShow({ values }) {
  155 + return values.accessMode === AccessMode.ManuallyEnter;
  156 + },
  157 + componentProps: {
  158 + maxLength: 36,
  159 + placeholder: '请输入视频厂家',
  160 + },
  161 + },
  162 + {
  163 + field: 'sn',
  164 + label: '摄像头编号',
  165 + required: true,
  166 + component: 'Input',
  167 + rules: [...CameraVideoUrl, { required: true, message: '摄像头编号是必填项' }],
  168 + ifShow({ values }) {
  169 + return values.accessMode === AccessMode.ManuallyEnter;
  170 + },
  171 + componentProps: {
  172 + maxLength: 36,
  173 + placeholder: '请输入摄像头编号',
  174 + },
  175 + },
  176 + {
  177 + field: 'videoUrl',
  178 + label: '视频流',
  179 + component: 'Input',
  180 + required: true,
  181 + ifShow({ values }) {
  182 + return values.accessMode === AccessMode.ManuallyEnter;
  183 + },
  184 + componentProps: {
  185 + placeholder: '请输入视频流',
  186 + maxLength: 255,
  187 + },
  188 + rules: [{ required: true, message: '视频流是必填项' }, ...CameraVideoUrl],
  189 + },
  190 +
  191 + {
  192 + field: 'videoPlatformId',
  193 + label: '流媒体配置',
  194 + component: 'Select',
  195 + ifShow({ values }) {
  196 + return values.accessMode === AccessMode.Streaming;
  197 + },
  198 + slot: 'videoPlatformIdSlot',
  199 + componentProps: {
  200 + placeholder: '请选择流媒体配置',
  201 + },
  202 + },
  203 + {
  204 + field: 'streamType',
  205 + label: '码流',
  206 + component: 'RadioGroup',
  207 + defaultValue: StreamType.MASTER,
  208 + ifShow({ values }) {
  209 + return values.accessMode === AccessMode.Streaming;
  210 + },
  211 + componentProps: {
  212 + placeholder: '请选择码流',
  213 + defaultValue: StreamType.MASTER,
  214 + options: [
  215 + { label: '主码流', value: StreamType.MASTER },
  216 + { label: '子码流', value: StreamType.CHILD },
  217 + { label: '第三码流', value: StreamType.THIRD },
  218 + ],
  219 + },
  220 + },
  221 + {
  222 + field: 'playProtocol',
  223 + label: '播放协议',
  224 + component: 'RadioGroup',
  225 + defaultValue: PlayProtocol.HTTP,
  226 + ifShow({ values }) {
  227 + return values.accessMode === AccessMode.Streaming;
  228 + },
  229 + helpMessage: ['平台使用https的hls协议,需联系海康开放平台专家支持。'],
  230 + componentProps: {
  231 + placeholder: '请选择播放协议',
  232 + defaultValue: PlayProtocol.HTTP,
  233 + options: [
  234 + { label: 'http', value: PlayProtocol.HTTP },
  235 + { label: 'https', value: PlayProtocol.HTTPS },
  236 + ],
  237 + },
  238 + },
  239 + {
  240 + field: 'sn',
  241 + label: h(SnHelpMessage) as any,
  242 + component: 'Input',
  243 + rules: [...CameraVideoUrl, { required: true, message: '摄像头编号是必填项' }],
  244 + ifShow({ values }) {
  245 + return values.accessMode === AccessMode.Streaming;
  246 + },
  247 + componentProps: {
  248 + placeholder: '请输入监控点编号',
  249 + },
  250 + },
  251 +];
... ...
... ... @@ -5,8 +5,11 @@
5 5 import { computed, ref, unref } from 'vue';
6 6 import OrganizationDrawer from '/@/views/system/organization/OrganizationDrawer.vue';
7 7 import { useDrawer } from '/@/components/Drawer';
  8 + import { OrganizationListItem } from '/@/api/system/model/systemModel';
  9 + import { useRole } from '/@/hooks/business/useRole';
8 10
9 11 const [registerDrawer, { openDrawer }] = useDrawer();
  12 + const { isCustomerUser } = useRole();
10 13
11 14 const props = withDefaults(
12 15 defineProps<{
... ... @@ -19,6 +22,8 @@
19 22 }
20 23 );
21 24
  25 + const needReload = ref(true);
  26 +
22 27 const emit = defineEmits(['change']);
23 28
24 29 const handleOpenCreate = () => {
... ... @@ -27,7 +32,9 @@
27 32
28 33 const timespan = ref(Date.now());
29 34
30   - const getBindProps = computed(() => {
  35 + const orgList = ref<Recordable[]>([]);
  36 +
  37 + const getBindProps = computed<Recordable>(() => {
31 38 const { value, apiTreeSelectProps = {} } = props;
32 39 const { params = {} } = apiTreeSelectProps;
33 40 return {
... ... @@ -37,7 +44,17 @@
37 44 maxLength: 250,
38 45 ...apiTreeSelectProps,
39 46 value,
40   - api: getOrganizationList,
  47 + api: async (params: OrganizationListItem) => {
  48 + try {
  49 + if (!unref(needReload)) return unref(orgList);
  50 + const result = ((await getOrganizationList(params)) as unknown as Recordable[]) || [];
  51 + orgList.value = result;
  52 + needReload.value = false;
  53 + return result;
  54 + } catch (error) {
  55 + return unref(orgList);
  56 + }
  57 + },
41 58 params: { ...params, _t: unref(timespan) },
42 59 onChange: (...args: any[]) => {
43 60 emit('change', ...args);
... ... @@ -45,7 +62,13 @@
45 62 };
46 63 });
47 64
  65 + const getShowCreate = computed(() => {
  66 + const { showCreate } = props;
  67 + return unref(isCustomerUser) ? false : showCreate;
  68 + });
  69 +
48 70 const handleReload = () => {
  71 + needReload.value = true;
49 72 timespan.value = Date.now();
50 73 };
51 74 </script>
... ... @@ -53,7 +76,7 @@
53 76 <template>
54 77 <section class="flex">
55 78 <ApiTreeSelect v-bind="getBindProps" />
56   - <Button v-if="showCreate" type="link" @click="handleOpenCreate">新增组织</Button>
57   - <OrganizationDrawer v-if="showCreate" @register="registerDrawer" @success="handleReload" />
  79 + <Button v-if="getShowCreate" type="link" @click="handleOpenCreate">新增组织</Button>
  80 + <OrganizationDrawer v-if="getShowCreate" @register="registerDrawer" @success="handleReload" />
58 81 </section>
59 82 </template>
... ...
1 1 import { BasicColumn, FormSchema } from '/@/components/Table';
2   -import { getOrganizationList } from '/@/api/system/system';
3   -import { copyTransFun } from '/@/utils/fnUtils';
4 2 import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
5 3 import { createImgPreview } from '/@/components/Preview';
6 4 import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter';
  5 +import { useComponentRegister } from '/@/components/Form';
  6 +import { OrgTreeSelect } from '../../common/OrgTreeSelect';
  7 +
  8 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
7 9 export enum Platform {
8 10 PHONE = 'phone',
9 11 PC = 'pc',
... ... @@ -126,14 +128,7 @@ export const formSchema: FormSchema[] = [
126 128 field: 'organizationId',
127 129 label: '所属组织',
128 130 required: true,
129   - component: 'ApiTreeSelect',
130   - componentProps: {
131   - api: async () => {
132   - const data = await getOrganizationList();
133   - copyTransFun(data as any as any[]);
134   - return data;
135   - },
136   - },
  131 + component: 'OrgTreeSelect',
137 132 },
138 133 {
139 134 field: 'platform',
... ...
1 1 import { FormSchema } from '/@/components/Table';
2   -import { getOrganizationList } from '/@/api/system/system';
3   -import { copyTransFun } from '/@/utils/fnUtils';
4 2 import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
5 3 import { createImgPreview } from '/@/components/Preview';
6 4 import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter';
  5 +import { useComponentRegister } from '/@/components/Form';
  6 +import { OrgTreeSelect } from '../common/OrgTreeSelect';
  7 +
  8 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
  9 +
7 10 export enum Platform {
8 11 PHONE = 0,
9 12 PC = 1,
... ... @@ -80,29 +83,8 @@ export const formSchema: FormSchema[] = [
80 83 field: 'organizationId',
81 84 label: '所属组织',
82 85 required: true,
83   - component: 'ApiTreeSelect',
84   - componentProps: {
85   - api: async () => {
86   - const data = await getOrganizationList();
87   - copyTransFun(data as any as any[]);
88   - return data;
89   - },
90   - },
  86 + component: 'OrgTreeSelect',
91 87 },
92   - // {
93   - // field: 'state',
94   - // label: '发布状态',
95   - // required: true,
96   - // component: 'RadioGroup',
97   - // defaultValue: Platform.PC,
98   - // componentProps: {
99   - // defaultValue: Platform.PC,
100   - // options: [
101   - // { label: '未发布', value: Platform.PC },
102   - // { label: '已发布', value: Platform.PHONE },
103   - // ],
104   - // },
105   - // },
106 88 {
107 89 field: 'remark',
108 90 label: '备注',
... ...
... ... @@ -182,7 +182,7 @@
182 182 Reflect.set(params, 'scope', 'LATEST_TELEMETRY');
183 183 Reflect.set(params, 'entityType', 'DEVICE');
184 184 }
185   - socketMessage.sendValue.tsSubCmds.push(params);
  185 + socketMessage.sendValue.tsSubCmds = [params];
186 186 const { send, close } = useWebSocket(socketMessage.server, {
187 187 onConnected() {
188 188 send(JSON.stringify(socketMessage.sendValue));
... ...
1   -import { BasicColumn, FormSchema } from '/@/components/Table';
2   -import { h } from 'vue';
3   -import { Tag } from 'ant-design-vue';
4   -import { findDictItemByCode } from '/@/api/system/dict';
5   -import { USER_INFO_KEY } from '/@/enums/cacheEnum';
6   -import { getAuthCache } from '/@/utils/auth';
7   -import { isAdmin } from '/@/enums/roleEnum';
8   -
9   -// 表格配置
10   -export const columns: BasicColumn[] = [
11   - {
12   - title: '接口名称',
13   - dataIndex: 'interfaceName',
14   - width: 150,
15   - },
16   - {
17   - title: '接口类型',
18   - dataIndex: 'interfaceType',
19   - width: 80,
20   - format(text) {
21   - return text === 'SYSTEM' ? '系统默认' : '自定义';
22   - },
23   - },
24   - {
25   - title: '请求方式',
26   - dataIndex: 'requestContentType',
27   - width: 90,
28   - format(text) {
29   - return Number(text) === 0 ? '普通请求' : Number(text) === 1 ? 'SQL请求' : 'websocket请求';
30   - },
31   - },
32   - {
33   - title: '接口内容',
34   - dataIndex: 'content',
35   - width: 80,
36   - slots: { customRender: 'content' },
37   - },
38   - {
39   - title: '状态',
40   - dataIndex: 'state',
41   - width: 80,
42   - customRender: ({ record }) => {
43   - const color = record.state == 1 ? 'green' : 'red';
44   - const text = record.state == 1 ? '发布' : '未发布';
45   - return h(Tag, { color: color }, () => text);
46   - },
47   - },
48   -];
49   -
50   -// 查询配置
51   -export const searchFormSchema: FormSchema[] = [
52   - {
53   - field: 'name',
54   - label: '接口名称',
55   - component: 'Input',
56   - colProps: { span: 7 },
57   - componentProps: {
58   - maxLength: 36,
59   - placeholder: '请输入接口名称',
60   - },
61   - },
62   - {
63   - field: 'state',
64   - label: '发布状态',
65   - component: 'Select',
66   - colProps: { span: 7 },
67   - componentProps: {
68   - options: [
69   - {
70   - label: '发布',
71   - value: 1,
72   - },
73   - {
74   - label: '未发布',
75   - value: 0,
76   - },
77   - ],
78   - placeholder: '请选择发布状态',
79   - },
80   - },
81   - {
82   - field: 'interfaceType',
83   - label: '接口类型',
84   - component: 'Select',
85   - colProps: { span: 7 },
86   - componentProps: {
87   - options: [
88   - {
89   - label: '系统默认',
90   - value: 'SYSTEM',
91   - },
92   - {
93   - label: '自定义',
94   - value: 'CUSTOM',
95   - },
96   - ],
97   - placeholder: '请选择接口类型',
98   - },
99   - ifShow: ({}) => {
100   - const userInfo: any = getAuthCache(USER_INFO_KEY);
101   - const role: string = userInfo?.roles[0];
102   - if (isAdmin(role)) return true;
103   - else return false;
104   - },
105   - },
106   -];
107   -
108   -//表单配置
109   -export const schemas: FormSchema[] = [
110   - {
111   - field: 'interfaceName',
112   - label: '接口名称',
113   - colProps: { span: 24 },
114   - required: true,
115   - component: 'Input',
116   - componentProps: {
117   - maxLength: 255,
118   - placeholder: '请输入接口名称',
119   - },
120   - },
121   - // {
122   - // field: 'interfaceType',
123   - // component: 'ApiRadioGroup',
124   - // label: '接口类型',
125   - // required: true,
126   - // colProps: {
127   - // span: 8,
128   - // },
129   - // defaultValue: 'SYSTEM',
130   - // componentProps: {
131   - // api: findDictItemByCode,
132   - // params: {
133   - // dictCode: 'interface_Type',
134   - // },
135   - // labelField: 'itemText',
136   - // valueField: 'itemValue',
137   - // },
138   - // },
139   - {
140   - field: 'interfaceType',
141   - component: 'ApiRadioGroup',
142   - label: '接口类型',
143   - required: true,
144   - colProps: {
145   - span: 8,
146   - },
147   - defaultValue: 'CUSTOM',
148   - componentProps: {
149   - options: [
150   - {
151   - label: '系统默认',
152   - value: 'SYSTEM',
153   - },
154   - {
155   - label: '自定义',
156   - value: 'CUSTOM',
157   - },
158   - ],
159   - },
160   - ifShow: ({}) => {
161   - const userInfo: any = getAuthCache(USER_INFO_KEY);
162   - const role: string = userInfo?.roles[0];
163   - if (isAdmin(role)) return true;
164   - else return false;
165   - },
166   - },
167   - {
168   - field: 'requestContentType',
169   - label: '请求方式',
170   - component: 'ApiSelect',
171   - required: true,
172   - colProps: { span: 24 },
173   - defaultValue: '0',
174   - componentProps: ({ formActionType }) => {
175   - const { updateSchema, setFieldsValue } = formActionType;
176   - return {
177   - api: findDictItemByCode,
178   - params: {
179   - dictCode: 'dataview_select_methods',
180   - },
181   - placeholder: '请选择请求方式',
182   - labelField: 'itemText',
183   - valueField: 'itemValue',
184   - getPopupContainer: () => document.body,
185   - async onChange(e) {
186   - setFieldsValue({
187   - requestOriginUrl: '',
188   - requestHttpTypeAndUrl: {
189   - requestHttpType: undefined,
190   - requestUrl: '',
191   - },
192   - });
193   - updateSchema({
194   - field: 'requestHttpTypeAndUrl',
195   - componentProps: {
196   - type: e,
197   - },
198   - });
199   - updateSchema({
200   - field: 'requestOriginUrl',
201   - componentProps: {
202   - placeholder: `${
203   - e === '0' ? '示例:http://127.0.0.1' : e === '2' ? '示例:ws://127.0.0.1' : ''
204   - }`,
205   - },
206   - });
207   - },
208   - };
209   - },
210   - },
211   - {
212   - field: 'originUrlType',
213   - label: '地址类型',
214   - component: 'ApiSelect',
215   - required: true,
216   - colProps: { span: 24 },
217   - defaultValue: 'server_url',
218   - componentProps: ({ formActionType }) => {
219   - const { setFieldsValue } = formActionType;
220   - return {
221   - placeholder: '请选择地址类型',
222   - api: findDictItemByCode,
223   - params: {
224   - dictCode: 'dataview_select_origin_type',
225   - },
226   - labelField: 'itemText',
227   - valueField: 'itemValue',
228   - onChange: (e) => {
229   - if (e) {
230   - setFieldsValue({
231   - requestOriginUrl: '',
232   - });
233   - }
234   - },
235   - };
236   - },
237   - },
238   - {
239   - field: 'requestOriginUrl',
240   - label: '源地址',
241   - colProps: { span: 24 },
242   - required: true,
243   - component: 'Input',
244   - componentProps: ({ formActionType }) => {
245   - const { getFieldsValue } = formActionType;
246   - const type = getFieldsValue()?.requestContentType;
247   - return {
248   - placeholder: `${
249   - type === '0' ? '示例:http://127.0.0.1' : type === '2' ? '示例:ws://127.0.0.1' : ''
250   - }`,
251   - };
252   - },
253   - ifShow: ({ values }) => values['originUrlType'] === 'custom_url',
254   - },
255   - {
256   - field: 'requestHttpTypeAndUrl',
257   - label: '请求类型&地址',
258   - component: 'InputGroup',
259   - required: true,
260   - colProps: { span: 24 },
261   - componentProps: ({ formActionType }) => {
262   - const { getFieldsValue } = formActionType;
263   - return {
264   - type: getFieldsValue().requestContentType,
265   - };
266   - },
267   - },
268   - {
269   - field: 'fillAddress',
270   - label: '完整地址',
271   - component: 'Input',
272   - slot: 'slotFillAddress',
273   - colProps: { span: 24 },
274   - ifShow: ({ values }) => {
275   - return values['originUrlType'] === 'custom_url' && values['requestOriginUrl'];
276   - },
277   - },
278   - {
279   - field: 'slotServerAddress',
280   - label: '完整地址',
281   - component: 'Input',
282   - slot: 'slotServerAddress',
283   - colProps: { span: 24 },
284   - ifShow: ({ values }) => {
285   - return values['originUrlType'] === 'server_url';
286   - },
287   - },
288   - {
289   - field: 'requestSQLKey',
290   - label: '键名',
291   - colProps: { span: 6 },
292   - component: 'Input',
293   - defaultValue: 'sql',
294   - componentProps: {
295   - disabled: true,
296   - },
297   - ifShow: ({ values }) => values['requestContentType'] === '1',
298   - },
299   - {
300   - field: 'requestSQLContent',
301   - label: '键值',
302   - colProps: { span: 24 },
303   - component: 'InputTextArea',
304   - defaultValue: 'select * from where',
305   - componentProps: {
306   - maxLength: 255,
307   - placeholder: '请输入键值',
308   - rows: 6,
309   - },
310   - ifShow: ({ values }) => values['requestContentType'] === '1',
311   - },
312   - {
313   - field: 'slot',
314   - label: '参数设置',
315   - component: 'Input',
316   - slot: 'selectMethods',
317   - colProps: { span: 24 },
318   - ifShow: ({ values }) => values['requestContentType'] !== '1',
319   - },
320   - {
321   - field: 'testSlot',
322   - label: '',
323   - component: 'Input',
324   - slot: 'testSql',
325   - colProps: { span: 24 },
326   - ifShow: ({ values }) => values['requestContentType'] === '1',
327   - },
328   -];
329   -
330   -//表格表头配置
331   -export const editCellTableTHeadConfig = ['序号', '内置参数', '参数名', '是否必须', '操作'];
332   -export const editTestCellTableTHeadConfig = ['内置参数', '参数名', '参数值'];
333   -export const editTestCellTableTHeaderConfig = ['序号', '参数名', '参数值', '是否必须', '操作'];
  1 +import { BasicColumn, FormSchema } from '/@/components/Table';
  2 +import { h } from 'vue';
  3 +import { Tag } from 'ant-design-vue';
  4 +import { findDictItemByCode } from '/@/api/system/dict';
  5 +import { USER_INFO_KEY } from '/@/enums/cacheEnum';
  6 +import { getAuthCache } from '/@/utils/auth';
  7 +import { isAdmin } from '/@/enums/roleEnum';
  8 +
  9 +// 表格配置
  10 +export const columns: BasicColumn[] = [
  11 + {
  12 + title: '接口名称',
  13 + dataIndex: 'interfaceName',
  14 + width: 150,
  15 + },
  16 + {
  17 + title: '接口类型',
  18 + dataIndex: 'interfaceType',
  19 + width: 80,
  20 + format(text) {
  21 + return text === 'SYSTEM' ? '系统默认' : '自定义';
  22 + },
  23 + },
  24 + {
  25 + title: '请求方式',
  26 + dataIndex: 'requestContentType',
  27 + width: 90,
  28 + format(text) {
  29 + return Number(text) === 0 ? '普通请求' : Number(text) === 1 ? 'SQL请求' : 'websocket请求';
  30 + },
  31 + },
  32 + {
  33 + title: '接口内容',
  34 + dataIndex: 'content',
  35 + width: 80,
  36 + slots: { customRender: 'content' },
  37 + },
  38 + {
  39 + title: '状态',
  40 + dataIndex: 'state',
  41 + width: 80,
  42 + customRender: ({ record }) => {
  43 + const color = record.state == 1 ? 'green' : 'red';
  44 + const text = record.state == 1 ? '发布' : '未发布';
  45 + return h(Tag, { color: color }, () => text);
  46 + },
  47 + },
  48 +];
  49 +
  50 +// 查询配置
  51 +export const searchFormSchema: FormSchema[] = [
  52 + {
  53 + field: 'name',
  54 + label: '接口名称',
  55 + component: 'Input',
  56 + componentProps: {
  57 + maxLength: 36,
  58 + placeholder: '请输入接口名称',
  59 + },
  60 + },
  61 + {
  62 + field: 'state',
  63 + label: '发布状态',
  64 + component: 'Select',
  65 + componentProps: {
  66 + options: [
  67 + {
  68 + label: '发布',
  69 + value: 1,
  70 + },
  71 + {
  72 + label: '未发布',
  73 + value: 0,
  74 + },
  75 + ],
  76 + placeholder: '请选择发布状态',
  77 + },
  78 + },
  79 + {
  80 + field: 'interfaceType',
  81 + label: '接口类型',
  82 + component: 'Select',
  83 + colProps: { span: 7 },
  84 + componentProps: {
  85 + options: [
  86 + {
  87 + label: '系统默认',
  88 + value: 'SYSTEM',
  89 + },
  90 + {
  91 + label: '自定义',
  92 + value: 'CUSTOM',
  93 + },
  94 + ],
  95 + placeholder: '请选择接口类型',
  96 + },
  97 + ifShow: ({}) => {
  98 + const userInfo: any = getAuthCache(USER_INFO_KEY);
  99 + const role: string = userInfo?.roles[0];
  100 + if (isAdmin(role)) return true;
  101 + else return false;
  102 + },
  103 + },
  104 +];
  105 +
  106 +//表单配置
  107 +export const schemas: FormSchema[] = [
  108 + {
  109 + field: 'interfaceName',
  110 + label: '接口名称',
  111 + colProps: { span: 24 },
  112 + required: true,
  113 + component: 'Input',
  114 + componentProps: {
  115 + maxLength: 255,
  116 + placeholder: '请输入接口名称',
  117 + },
  118 + },
  119 + // {
  120 + // field: 'interfaceType',
  121 + // component: 'ApiRadioGroup',
  122 + // label: '接口类型',
  123 + // required: true,
  124 + // colProps: {
  125 + // span: 8,
  126 + // },
  127 + // defaultValue: 'SYSTEM',
  128 + // componentProps: {
  129 + // api: findDictItemByCode,
  130 + // params: {
  131 + // dictCode: 'interface_Type',
  132 + // },
  133 + // labelField: 'itemText',
  134 + // valueField: 'itemValue',
  135 + // },
  136 + // },
  137 + {
  138 + field: 'interfaceType',
  139 + component: 'ApiRadioGroup',
  140 + label: '接口类型',
  141 + required: true,
  142 + colProps: {
  143 + span: 8,
  144 + },
  145 + defaultValue: 'CUSTOM',
  146 + componentProps: {
  147 + options: [
  148 + {
  149 + label: '系统默认',
  150 + value: 'SYSTEM',
  151 + },
  152 + {
  153 + label: '自定义',
  154 + value: 'CUSTOM',
  155 + },
  156 + ],
  157 + },
  158 + ifShow: ({}) => {
  159 + const userInfo: any = getAuthCache(USER_INFO_KEY);
  160 + const role: string = userInfo?.roles[0];
  161 + if (isAdmin(role)) return true;
  162 + else return false;
  163 + },
  164 + },
  165 + {
  166 + field: 'requestContentType',
  167 + label: '请求方式',
  168 + component: 'ApiSelect',
  169 + required: true,
  170 + colProps: { span: 24 },
  171 + defaultValue: '0',
  172 + componentProps: ({ formActionType }) => {
  173 + const { updateSchema, setFieldsValue } = formActionType;
  174 + return {
  175 + api: findDictItemByCode,
  176 + params: {
  177 + dictCode: 'dataview_select_methods',
  178 + },
  179 + placeholder: '请选择请求方式',
  180 + labelField: 'itemText',
  181 + valueField: 'itemValue',
  182 + getPopupContainer: () => document.body,
  183 + async onChange(e) {
  184 + setFieldsValue({
  185 + requestOriginUrl: '',
  186 + requestHttpTypeAndUrl: {
  187 + requestHttpType: undefined,
  188 + requestUrl: '',
  189 + },
  190 + });
  191 + updateSchema({
  192 + field: 'requestHttpTypeAndUrl',
  193 + componentProps: {
  194 + type: e,
  195 + },
  196 + });
  197 + updateSchema({
  198 + field: 'requestOriginUrl',
  199 + componentProps: {
  200 + placeholder: `${
  201 + e === '0' ? '示例:http://127.0.0.1' : e === '2' ? '示例:ws://127.0.0.1' : ''
  202 + }`,
  203 + },
  204 + });
  205 + },
  206 + };
  207 + },
  208 + },
  209 + {
  210 + field: 'originUrlType',
  211 + label: '地址类型',
  212 + component: 'ApiSelect',
  213 + required: true,
  214 + colProps: { span: 24 },
  215 + defaultValue: 'server_url',
  216 + componentProps: ({ formActionType }) => {
  217 + const { setFieldsValue } = formActionType;
  218 + return {
  219 + placeholder: '请选择地址类型',
  220 + api: findDictItemByCode,
  221 + params: {
  222 + dictCode: 'dataview_select_origin_type',
  223 + },
  224 + labelField: 'itemText',
  225 + valueField: 'itemValue',
  226 + onChange: (e) => {
  227 + if (e) {
  228 + setFieldsValue({
  229 + requestOriginUrl: '',
  230 + });
  231 + }
  232 + },
  233 + };
  234 + },
  235 + },
  236 + {
  237 + field: 'requestOriginUrl',
  238 + label: '源地址',
  239 + colProps: { span: 24 },
  240 + required: true,
  241 + component: 'Input',
  242 + componentProps: ({ formActionType }) => {
  243 + const { getFieldsValue } = formActionType;
  244 + const type = getFieldsValue()?.requestContentType;
  245 + return {
  246 + placeholder: `${
  247 + type === '0' ? '示例:http://127.0.0.1' : type === '2' ? '示例:ws://127.0.0.1' : ''
  248 + }`,
  249 + };
  250 + },
  251 + ifShow: ({ values }) => values['originUrlType'] === 'custom_url',
  252 + },
  253 + {
  254 + field: 'requestHttpTypeAndUrl',
  255 + label: '请求类型&地址',
  256 + component: 'InputGroup',
  257 + required: true,
  258 + colProps: { span: 24 },
  259 + componentProps: ({ formActionType }) => {
  260 + const { getFieldsValue } = formActionType;
  261 + return {
  262 + type: getFieldsValue().requestContentType,
  263 + };
  264 + },
  265 + },
  266 + {
  267 + field: 'fillAddress',
  268 + label: '完整地址',
  269 + component: 'Input',
  270 + slot: 'slotFillAddress',
  271 + colProps: { span: 24 },
  272 + ifShow: ({ values }) => {
  273 + return values['originUrlType'] === 'custom_url' && values['requestOriginUrl'];
  274 + },
  275 + },
  276 + {
  277 + field: 'slotServerAddress',
  278 + label: '完整地址',
  279 + component: 'Input',
  280 + slot: 'slotServerAddress',
  281 + colProps: { span: 24 },
  282 + ifShow: ({ values }) => {
  283 + return values['originUrlType'] === 'server_url';
  284 + },
  285 + },
  286 + {
  287 + field: 'requestSQLKey',
  288 + label: '键名',
  289 + colProps: { span: 6 },
  290 + component: 'Input',
  291 + defaultValue: 'sql',
  292 + componentProps: {
  293 + disabled: true,
  294 + },
  295 + ifShow: ({ values }) => values['requestContentType'] === '1',
  296 + },
  297 + {
  298 + field: 'requestSQLContent',
  299 + label: '键值',
  300 + colProps: { span: 24 },
  301 + component: 'InputTextArea',
  302 + defaultValue: 'select * from where',
  303 + componentProps: {
  304 + maxLength: 255,
  305 + placeholder: '请输入键值',
  306 + rows: 6,
  307 + },
  308 + ifShow: ({ values }) => values['requestContentType'] === '1',
  309 + },
  310 + {
  311 + field: 'slot',
  312 + label: '参数设置',
  313 + component: 'Input',
  314 + slot: 'selectMethods',
  315 + colProps: { span: 24 },
  316 + ifShow: ({ values }) => values['requestContentType'] !== '1',
  317 + },
  318 + {
  319 + field: 'testSlot',
  320 + label: '',
  321 + component: 'Input',
  322 + slot: 'testSql',
  323 + colProps: { span: 24 },
  324 + ifShow: ({ values }) => values['requestContentType'] === '1',
  325 + },
  326 +];
  327 +
  328 +//表格表头配置
  329 +export const editCellTableTHeadConfig = ['序号', '内置参数', '参数名', '是否必须', '操作'];
  330 +export const editTestCellTableTHeadConfig = ['内置参数', '参数名', '参数值'];
  331 +export const editTestCellTableTHeaderConfig = ['序号', '参数名', '参数值', '是否必须', '操作'];
... ...
1 1 <template>
2 2 <div>
3   - <BasicTable @register="registerTable" :row-selection="rowSelection">
  3 + <BasicTable
  4 + @register="registerTable"
  5 + :row-selection="rowSelection"
  6 + class="bg-neutral-100 dark:bg-dark-700"
  7 + >
4 8 <template #content="{ record }">
5 9 <a-button type="link" class="ml-2" @click="handleRecordContent(record)"> 查看 </a-button>
6 10 </template>
... ... @@ -108,8 +112,10 @@
108 112 showTableSetting: true,
109 113 bordered: true,
110 114 formConfig: {
111   - labelWidth: 120,
  115 + labelWidth: 80,
112 116 schemas: searchFormSchema,
  117 + baseColProps: { span: 9 },
  118 + actionColOptions: { span: 6 },
113 119 },
114 120 useSearchForm: true,
115 121 actionColumn: {
... ...
... ... @@ -63,12 +63,12 @@
63 63 </div>
64 64 </template>
65 65 <template #deviceProfile="{ record }">
66   - <Tag.CheckableTag
  66 + <Button
67 67 @click="!isCustomer ? goDeviceProfile(record.deviceProfile.name) : null"
68   - style="white-space: normal; height: auto; cursor: pointer"
  68 + type="link"
69 69 >
70   - <span style="color: #377dff">{{ record.deviceProfile.name }}</span>
71   - </Tag.CheckableTag>
  70 + {{ record.deviceProfile.name }}
  71 + </Button>
72 72 </template>
73 73
74 74 <template #deviceType="{ record }">
... ... @@ -385,10 +385,10 @@
385 385 openGatewayDetailDrawer(true, data);
386 386 };
387 387
388   - const handleUpAndDownRecord = (record: Record<'name', string>) => {
  388 + const handleUpAndDownRecord = (record: Record<'name' | 'alias', string>) => {
389 389 ROUTER.push({
390 390 path: '/operation/onlinerecord',
391   - query: { deviceName: record.name },
  391 + query: { deviceName: record.alias || record.name },
392 392 });
393 393 };
394 394
... ...
... ... @@ -82,7 +82,7 @@ export const columns: BasicColumn[] = [
82 82 dataIndex: 'name',
83 83 width: 120,
84 84 format: (_text: string, record: Recordable) => {
85   - return record?.alias ? record?.alias : record?.name;
  85 + return record?.alias || record?.name;
86 86 },
87 87 },
88 88 {
... ...
... ... @@ -150,6 +150,7 @@
150 150 deviceProfile: { default: boolean; enabled: boolean; name: string; transportType: string };
151 151 deviceInfo: { longitude: string; latitude: string; address: string };
152 152 deviceType?: string;
  153 + alias?: string;
153 154 deviceProfileId: string;
154 155 }
155 156 type MarkerList = DeviceInfo & { marker: any; label: any };
... ... @@ -376,7 +377,7 @@
376 377 width: 330, // 信息窗口宽度
377 378 height: 0, // 信息窗口高度
378 379 };
379   - const { name, organizationDTO, deviceState, deviceProfile, deviceType } = record;
  380 + const { name, alias, organizationDTO, deviceState, deviceProfile, deviceType } = record;
380 381 const { address, longitude, latitude } = record.deviceInfo;
381 382
382 383 // 创建信息窗口对象
... ... @@ -387,7 +388,7 @@
387 388 let infoWindow = new BMap.InfoWindow(
388 389 `
389 390 <div style="display:flex;justify-content:space-between; margin:20px 0px;">
390   - <div style="font-size:16px;font-weight:bold">${name}</div>
  391 + <div style="font-size:16px;font-weight:bold">${alias || name}</div>
391 392 ${
392 393 deviceState === 'INACTIVE'
393 394 ? `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${djh}" class="mr-1">待激活</div>`
... ...
1   -import { ref } from 'vue';
2   -import { BasicColumn, FormSchema } from '/@/components/Table';
3   -import type { FormSchema as QFormSchema } from '/@/components/Form/index';
4   -import { getOrganizationList } from '/@/api/system/system';
5   -import { copyTransFun } from '/@/utils/fnUtils';
6   -import { findDictItemByCode } from '/@/api/system/dict';
7   -import { isTiming, isWeek, isMonth, isFixedTime } from './timeConfig';
8   -import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config';
9   -import {
10   - getPacketIntervalByRange,
11   - getPacketIntervalByValue,
12   - intervalOption,
13   -} from '../../device/localtion/cpns/TimePeriodForm/helper';
14   -import moment, { Moment } from 'moment';
15   -
16   -export enum QueryWay {
17   - LATEST = 'latest',
18   - TIME_PERIOD = 'timePeriod',
19   -}
20   -export enum SchemaFiled {
21   - WAY = 'queryMode',
22   - TIME_PERIOD = 'timePeriod',
23   - KEYS = 'keys',
24   - DATE_RANGE = 'dataRange',
25   - START_TS = 'startTs',
26   - END_TS = 'endTs',
27   - INTERVAL = 'interval',
28   - LIMIT = 'limit',
29   - AGG = 'agg',
30   - ORDER_BY = 'orderBy',
31   -}
32   -export const organizationId = ref('');
33   -
34   -// 表格配置
35   -export const columns: BasicColumn[] = [
36   - {
37   - title: '配置名称',
38   - dataIndex: 'name',
39   - width: 120,
40   - },
41   - {
42   - title: '所属组织',
43   - dataIndex: 'organizationDTO.name',
44   - width: 120,
45   - },
46   - {
47   - title: '数据类型',
48   - dataIndex: 'dataType',
49   - width: 120,
50   - format: (_text: string, record: Recordable) => {
51   - return record.dataType === 0 ? '原始数据' : '聚合数据';
52   - },
53   - },
54   - {
55   - title: '配置状态',
56   - dataIndex: 'status',
57   - width: 120,
58   - slots: { customRender: 'configStatus' },
59   - },
60   - {
61   - title: '执行方式',
62   - dataIndex: 'executeWay',
63   - width: 160,
64   - format: (_text: string, record: Recordable) => {
65   - return record.executeWay === 0 ? '立即执行' : '定时执行';
66   - },
67   - },
68   - {
69   - title: '执行设备',
70   - dataIndex: 'devices',
71   - width: 160,
72   - slots: { customRender: 'doDeviceSlot' },
73   - },
74   - {
75   - title: '创建人',
76   - dataIndex: 'createUserName',
77   - width: 180,
78   - },
79   - {
80   - title: '创建时间',
81   - dataIndex: 'createTime',
82   - width: 180,
83   - },
84   -];
85   -export const viewDeviceColumn: BasicColumn[] = [
86   - {
87   - title: '设备',
88   - dataIndex: 'device',
89   - width: 80,
90   - },
91   - {
92   - title: '属性',
93   - dataIndex: 'attribute',
94   - width: 120,
95   - },
96   -];
97   -
98   -// 查询配置
99   -export const searchFormSchema: FormSchema[] = [
100   - {
101   - field: 'name',
102   - label: '配置名称',
103   - component: 'Input',
104   - colProps: { span: 6 },
105   - componentProps: {
106   - maxLength: 36,
107   - placeholder: '请输入配置名称',
108   - },
109   - },
110   - {
111   - field: 'status',
112   - label: '配置状态',
113   - component: 'Select',
114   - colProps: { span: 6 },
115   - componentProps: {
116   - options: [
117   - {
118   - label: '启用',
119   - value: 1,
120   - },
121   - {
122   - label: '禁用',
123   - value: 0,
124   - },
125   - ],
126   - placeholder: '请选择配置状态',
127   - },
128   - },
129   - {
130   - field: 'sendTime',
131   - label: '创建时间',
132   - component: 'RangePicker',
133   - componentProps: {
134   - showTime: {
135   - defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
136   - },
137   - },
138   - colProps: { span: 6 },
139   - },
140   -];
141   -
142   -// 新增编辑配置
143   -export const formSchema: QFormSchema[] = [
144   - {
145   - field: 'name',
146   - label: '报表名称',
147   - colProps: { span: 24 },
148   - required: true,
149   - component: 'Input',
150   - componentProps: {
151   - maxLength: 64,
152   - placeholder: '请输入报表名称',
153   - },
154   - },
155   - {
156   - field: 'organizationId',
157   - label: '所属组织',
158   - colProps: { span: 24 },
159   - component: 'ApiTreeSelect',
160   - required: true,
161   - componentProps: () => {
162   - return {
163   - maxLength: 250,
164   - placeholder: '请选择所属组织',
165   - api: async () => {
166   - const data = await getOrganizationList();
167   - copyTransFun(data as any as any[]);
168   - return data;
169   - },
170   - async onChange(e) {
171   - organizationId.value = e;
172   - },
173   - };
174   - },
175   - },
176   - {
177   - field: 'remark',
178   - label: '描述',
179   - colProps: { span: 24 },
180   - component: 'InputTextArea',
181   - componentProps: {
182   - maxLength: 255,
183   - placeholder: '请输入描述',
184   - },
185   - },
186   - {
187   - field: 'executeWay',
188   - component: 'RadioGroup',
189   - helpMessage: [
190   - `立即执行,在创建完报表配置后,启用配置即执行。
191   - 定时执行,用户定义执行时间,启用后,
192   - 在满足执行时间条件后,自动执行。`,
193   - ],
194   - label: '执行方式',
195   - colProps: {
196   - span: 24,
197   - },
198   - defaultValue: 0,
199   - componentProps: ({ formActionType }) => {
200   - const { updateSchema, setFieldsValue } = formActionType;
201   - const options = [
202   - {
203   - label: '立即执行',
204   - value: 0,
205   - },
206   - {
207   - label: '定时执行',
208   - value: 1,
209   - },
210   - ];
211   - return {
212   - options,
213   - placeholder: '请选择执行方式',
214   - onChange(e) {
215   - let dataCompareOpions: any = [];
216   - setFieldsValue({
217   - startTs: 1000,
218   - interval: 1000,
219   - });
220   - if (e.target.value == 0) {
221   - setFieldsValue({ queryMode: QueryWay.LATEST });
222   - dataCompareOpions = [
223   - { label: '固定周期', value: QueryWay.LATEST },
224   - { label: '自定义周期', value: QueryWay.TIME_PERIOD },
225   - ];
226   - updateSchema({
227   - field: SchemaFiled.WAY,
228   - componentProps: {
229   - options: dataCompareOpions,
230   - },
231   - });
232   - } else {
233   - setFieldsValue({ queryMode: QueryWay.LATEST });
234   - setFieldsValue({ startTs: 5000 });
235   - setFieldsValue({ interval: 1000 });
236   - dataCompareOpions = [{ label: '固定周期', value: QueryWay.LATEST }];
237   - updateSchema({
238   - defaultValue: QueryWay.LATEST,
239   - field: SchemaFiled.WAY,
240   - componentProps: {
241   - options: dataCompareOpions,
242   - },
243   - });
244   - }
245   - },
246   - maxLength: 250,
247   - };
248   - },
249   - },
250   - {
251   - field: 'cycleType',
252   - component: 'Select',
253   - label: '周期',
254   - required: true,
255   - colProps: { span: 24 },
256   - defaultValue: 0,
257   - componentProps: {
258   - placeholder: '请选择周期',
259   - options: [
260   - { label: '每日', value: 0 },
261   - { label: '每周', value: 1 },
262   - { label: '每月', value: 2 },
263   - ],
264   - },
265   - ifShow: ({ values }) => isTiming(values.executeWay),
266   - },
267   - {
268   - field: 'currentCycle',
269   - component: 'ApiSelect',
270   - label: '每周',
271   - required: true,
272   - colProps: { span: 24 },
273   - defaultValue: '0 0 0 ? * MON',
274   - componentProps: {
275   - placeholder: '请选择周期',
276   - api: findDictItemByCode,
277   - params: {
278   - dictCode: 'every_week',
279   - },
280   - labelField: 'itemText',
281   - valueField: 'itemValue',
282   - },
283   - ifShow: ({ values }) => isWeek(values.cycleType),
284   - },
285   - {
286   - field: 'cycleTime',
287   - component: 'ApiSelect',
288   - label: '每月',
289   - required: true,
290   - colProps: { span: 24 },
291   - defaultValue: '0 0 0 1 * ? *',
292   - componentProps: {
293   - placeholder: '请选择月份',
294   - api: findDictItemByCode,
295   - params: {
296   - dictCode: 'every_month',
297   - },
298   - labelField: 'itemText',
299   - valueField: 'itemValue',
300   - },
301   - ifShow: ({ values }) => isMonth(values.cycleType),
302   - },
303   - {
304   - field: 'cronTime',
305   - component: 'ApiSelect',
306   - label: '时间',
307   - required: true,
308   - colProps: { span: 24 },
309   - defaultValue: '0 0 0 * * ?',
310   - componentProps: {
311   - placeholder: '请选择时间',
312   - api: findDictItemByCode,
313   - params: {
314   - dictCode: 'every_day',
315   - },
316   - labelField: 'itemText',
317   - valueField: 'itemValue',
318   - },
319   - ifShow: ({ values }) => isTiming(values.executeWay),
320   - },
321   - {
322   - field: 'devices',
323   - label: '设备',
324   - component: 'Select',
325   - slot: 'devices',
326   - colProps: { span: 24 },
327   - },
328   - {
329   - field: 'dataType',
330   - label: '数据类型',
331   - required: true,
332   - component: 'Select',
333   - componentProps: ({ formActionType }) => {
334   - const { updateSchema, setFieldsValue } = formActionType;
335   - const options = [
336   - { label: '原始数据', value: 0 },
337   - { label: '聚合数据', value: 1 },
338   - ];
339   - return {
340   - options,
341   - onSelect(e) {
342   - let dataCompareOpions: any = [];
343   - if (e == 0) {
344   - setFieldsValue({ agg: 'NONE' });
345   - dataCompareOpions = [{ label: '空', value: AggregateDataEnum.NONE }];
346   - updateSchema({
347   - field: SchemaFiled.AGG,
348   - componentProps: {
349   - options: dataCompareOpions,
350   - },
351   - });
352   - } else {
353   - setFieldsValue({ agg: '' });
354   - dataCompareOpions = [
355   - { label: '最小值', value: AggregateDataEnum.MIN },
356   - { label: '最大值', value: AggregateDataEnum.MAX },
357   - { label: '平均值', value: AggregateDataEnum.AVG },
358   - { label: '求和', value: AggregateDataEnum.SUM },
359   - { label: '计数', value: AggregateDataEnum.COUNT },
360   - ];
361   - updateSchema({
362   - field: SchemaFiled.AGG,
363   - componentProps: {
364   - options: dataCompareOpions,
365   - },
366   - });
367   - }
368   - },
369   - maxLength: 250,
370   - placeholder: '请选择属性性质',
371   - };
372   - },
373   - colProps: { span: 24 },
374   - },
375   - {
376   - field: SchemaFiled.AGG,
377   - label: '聚合条件',
378   - component: 'Select',
379   - required: true,
380   - componentProps: {
381   - placeholder: '请选择聚合条件',
382   - getPopupContainer: () => document.body,
383   - },
384   - },
385   - {
386   - field: 'limit',
387   - required: true,
388   - label: '最大条数',
389   - component: 'InputNumber',
390   - defaultValue: 100,
391   - ifShow({ values }) {
392   - return values[SchemaFiled.AGG] === AggregateDataEnum.NONE;
393   - },
394   - colProps: { span: 12 },
395   - componentProps: {
396   - placeholder: '请输入最大条数',
397   - min: 7,
398   - max: 50000,
399   - },
400   - },
401   - {
402   - field: SchemaFiled.WAY,
403   - label: '查询周期',
404   - component: 'RadioGroup',
405   - defaultValue: QueryWay.LATEST,
406   - required: true,
407   - componentProps({ formActionType }) {
408   - const { setFieldsValue } = formActionType;
409   - return {
410   - placeholder: '请选择查询周期',
411   - options: [
412   - { label: '固定周期', value: QueryWay.LATEST },
413   - { label: '自定义周期', value: QueryWay.TIME_PERIOD },
414   - ],
415   - onChange(value) {
416   - console.log(value);
417   - value === QueryWay.LATEST
418   - ? setFieldsValue({
419   - [SchemaFiled.DATE_RANGE]: [],
420   - [SchemaFiled.START_TS]: null,
421   - [SchemaFiled.END_TS]: null,
422   - })
423   - : setFieldsValue({ [SchemaFiled.START_TS]: null });
424   - },
425   - };
426   - },
427   - },
428   - {
429   - field: SchemaFiled.DATE_RANGE,
430   - label: '时间段',
431   - component: 'RangePicker',
432   - required: true,
433   - ifShow({ values }) {
434   - return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && !isFixedTime(values.executeWay);
435   - },
436   - // componentProps: {
437   - // showTime: {
438   - // defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
439   - // },
440   - // },
441   - componentProps({ formActionType }) {
442   - const { setFieldsValue } = formActionType;
443   - let dates: Moment[] = [];
444   - return {
445   - showTime: {
446   - defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
447   - },
448   - onCalendarChange(value: Moment[]) {
449   - dates = value;
450   - },
451   - disabledDate(current: Moment) {
452   - if (!dates || dates.length === 0 || !current) {
453   - return false;
454   - }
455   - const diffDate = current.diff(dates[0], 'years', true);
456   - return Math.abs(diffDate) > 1;
457   - },
458   - onChange() {
459   - dates = [];
460   - setFieldsValue({ dateGroupGap: null });
461   - },
462   - getPopupContainer: () => document.body,
463   - };
464   - },
465   - colProps: {
466   - span: 10,
467   - },
468   - },
469   - {
470   - field: 'dateGroupGap',
471   - label: '分组间隔',
472   - component: 'Select',
473   - dynamicRules: ({ model }) => {
474   - return [
475   - {
476   - required: model[SchemaFiled.AGG] !== AggregateDataEnum.NONE,
477   - message: '分组间隔为必填项',
478   - type: 'number',
479   - },
480   - ];
481   - },
482   - ifShow({ values }) {
483   - return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && !isFixedTime(values.executeWay);
484   - },
485   - componentProps({ formModel, formActionType }) {
486   - const options =
487   - formModel[SchemaFiled.WAY] === QueryWay.LATEST
488   - ? getPacketIntervalByValue(formModel[SchemaFiled.START_TS])
489   - : getPacketIntervalByRange(formModel[SchemaFiled.DATE_RANGE]);
490   - if (formModel[SchemaFiled.AGG] !== AggregateDataEnum.NONE) {
491   - formActionType.setFieldsValue({ [SchemaFiled.LIMIT]: null });
492   - }
493   - return {
494   - options,
495   - getPopupContainer: () => document.body,
496   - };
497   - },
498   - },
499   - {
500   - field: SchemaFiled.START_TS,
501   - label: '最近时间',
502   - component: 'Select',
503   - required: true,
504   - ifShow({ values }) {
505   - return values[SchemaFiled.WAY] == QueryWay.LATEST;
506   - },
507   - componentProps({ formActionType }) {
508   - const { setFieldsValue } = formActionType;
509   - return {
510   - defaultValue: 1000,
511   - placeholder: '请选择近期时间',
512   - options: intervalOption,
513   - onChange() {
514   - setFieldsValue({ [SchemaFiled.INTERVAL]: null });
515   - },
516   - };
517   - },
518   - },
519   - {
520   - field: SchemaFiled.INTERVAL,
521   - label: '间隔时间',
522   - component: 'Select',
523   - required: true,
524   - ifShow({ values }) {
525   - return values[SchemaFiled.WAY] == QueryWay.LATEST;
526   - },
527   - componentProps({ formModel, formActionType }) {
528   - const options =
529   - formModel[SchemaFiled.WAY] === QueryWay.LATEST
530   - ? getPacketIntervalByValue(formModel[SchemaFiled.START_TS])
531   - : getPacketIntervalByRange(formModel[SchemaFiled.DATE_RANGE]);
532   - if (formModel[SchemaFiled.AGG] !== AggregateDataEnum.NONE) {
533   - formActionType.setFieldsValue({ [SchemaFiled.LIMIT]: null });
534   - }
535   - return {
536   - placeholder: '请选择间隔时间',
537   - options,
538   - };
539   - },
540   - },
541   -];
  1 +import { ref } from 'vue';
  2 +import { BasicColumn, FormSchema } from '/@/components/Table';
  3 +import { FormSchema as QFormSchema, useComponentRegister } from '/@/components/Form/index';
  4 +import { findDictItemByCode } from '/@/api/system/dict';
  5 +import { isTiming, isWeek, isMonth, isFixedTime } from './timeConfig';
  6 +import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config';
  7 +import {
  8 + getPacketIntervalByRange,
  9 + getPacketIntervalByValue,
  10 + intervalOption,
  11 +} from '../../device/localtion/cpns/TimePeriodForm/helper';
  12 +import moment, { Moment } from 'moment';
  13 +import { OrgTreeSelect } from '../../common/OrgTreeSelect';
  14 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
  15 +export enum QueryWay {
  16 + LATEST = 'latest',
  17 + TIME_PERIOD = 'timePeriod',
  18 +}
  19 +export enum SchemaFiled {
  20 + WAY = 'queryMode',
  21 + TIME_PERIOD = 'timePeriod',
  22 + KEYS = 'keys',
  23 + DATE_RANGE = 'dataRange',
  24 + START_TS = 'startTs',
  25 + END_TS = 'endTs',
  26 + INTERVAL = 'interval',
  27 + LIMIT = 'limit',
  28 + AGG = 'agg',
  29 + ORDER_BY = 'orderBy',
  30 +}
  31 +export const organizationId = ref('');
  32 +
  33 +// 表格配置
  34 +export const columns: BasicColumn[] = [
  35 + {
  36 + title: '配置名称',
  37 + dataIndex: 'name',
  38 + width: 120,
  39 + },
  40 + {
  41 + title: '所属组织',
  42 + dataIndex: 'organizationDTO.name',
  43 + width: 120,
  44 + },
  45 + {
  46 + title: '数据类型',
  47 + dataIndex: 'dataType',
  48 + width: 120,
  49 + format: (_text: string, record: Recordable) => {
  50 + return record.dataType === 0 ? '原始数据' : '聚合数据';
  51 + },
  52 + },
  53 + {
  54 + title: '配置状态',
  55 + dataIndex: 'status',
  56 + width: 120,
  57 + slots: { customRender: 'configStatus' },
  58 + },
  59 + {
  60 + title: '执行方式',
  61 + dataIndex: 'executeWay',
  62 + width: 160,
  63 + format: (_text: string, record: Recordable) => {
  64 + return record.executeWay === 0 ? '立即执行' : '定时执行';
  65 + },
  66 + },
  67 + {
  68 + title: '执行设备',
  69 + dataIndex: 'devices',
  70 + width: 160,
  71 + slots: { customRender: 'doDeviceSlot' },
  72 + },
  73 + {
  74 + title: '创建人',
  75 + dataIndex: 'createUserName',
  76 + width: 180,
  77 + },
  78 + {
  79 + title: '创建时间',
  80 + dataIndex: 'createTime',
  81 + width: 180,
  82 + },
  83 +];
  84 +export const viewDeviceColumn: BasicColumn[] = [
  85 + {
  86 + title: '设备',
  87 + dataIndex: 'device',
  88 + width: 80,
  89 + },
  90 + {
  91 + title: '属性',
  92 + dataIndex: 'attribute',
  93 + width: 120,
  94 + },
  95 +];
  96 +
  97 +// 查询配置
  98 +export const searchFormSchema: FormSchema[] = [
  99 + {
  100 + field: 'name',
  101 + label: '配置名称',
  102 + component: 'Input',
  103 + colProps: { span: 6 },
  104 + componentProps: {
  105 + maxLength: 36,
  106 + placeholder: '请输入配置名称',
  107 + },
  108 + },
  109 + {
  110 + field: 'status',
  111 + label: '配置状态',
  112 + component: 'Select',
  113 + colProps: { span: 6 },
  114 + componentProps: {
  115 + options: [
  116 + {
  117 + label: '启用',
  118 + value: 1,
  119 + },
  120 + {
  121 + label: '禁用',
  122 + value: 0,
  123 + },
  124 + ],
  125 + placeholder: '请选择配置状态',
  126 + },
  127 + },
  128 + {
  129 + field: 'sendTime',
  130 + label: '创建时间',
  131 + component: 'RangePicker',
  132 + componentProps: {
  133 + showTime: {
  134 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  135 + },
  136 + },
  137 + colProps: { span: 6 },
  138 + },
  139 +];
  140 +
  141 +// 新增编辑配置
  142 +export const formSchema: QFormSchema[] = [
  143 + {
  144 + field: 'name',
  145 + label: '报表名称',
  146 + colProps: { span: 24 },
  147 + required: true,
  148 + component: 'Input',
  149 + componentProps: {
  150 + maxLength: 64,
  151 + placeholder: '请输入报表名称',
  152 + },
  153 + },
  154 + {
  155 + field: 'organizationId',
  156 + label: '所属组织',
  157 + colProps: { span: 24 },
  158 + component: 'OrgTreeSelect',
  159 + required: true,
  160 + componentProps: () => {
  161 + return {
  162 + async onChange(e) {
  163 + organizationId.value = e;
  164 + },
  165 + };
  166 + },
  167 + },
  168 + {
  169 + field: 'remark',
  170 + label: '描述',
  171 + colProps: { span: 24 },
  172 + component: 'InputTextArea',
  173 + componentProps: {
  174 + maxLength: 255,
  175 + placeholder: '请输入描述',
  176 + },
  177 + },
  178 + {
  179 + field: 'executeWay',
  180 + component: 'RadioGroup',
  181 + helpMessage: [
  182 + `立即执行,在创建完报表配置后,启用配置即执行。
  183 + 定时执行,用户定义执行时间,启用后,
  184 + 在满足执行时间条件后,自动执行。`,
  185 + ],
  186 + label: '执行方式',
  187 + colProps: {
  188 + span: 24,
  189 + },
  190 + defaultValue: 0,
  191 + componentProps: ({ formActionType }) => {
  192 + const { updateSchema, setFieldsValue } = formActionType;
  193 + const options = [
  194 + {
  195 + label: '立即执行',
  196 + value: 0,
  197 + },
  198 + {
  199 + label: '定时执行',
  200 + value: 1,
  201 + },
  202 + ];
  203 + return {
  204 + options,
  205 + placeholder: '请选择执行方式',
  206 + onChange(e) {
  207 + let dataCompareOpions: any = [];
  208 + setFieldsValue({
  209 + startTs: 1000,
  210 + interval: 1000,
  211 + });
  212 + if (e.target.value == 0) {
  213 + setFieldsValue({ queryMode: QueryWay.LATEST });
  214 + dataCompareOpions = [
  215 + { label: '固定周期', value: QueryWay.LATEST },
  216 + { label: '自定义周期', value: QueryWay.TIME_PERIOD },
  217 + ];
  218 + updateSchema({
  219 + field: SchemaFiled.WAY,
  220 + componentProps: {
  221 + options: dataCompareOpions,
  222 + },
  223 + });
  224 + } else {
  225 + setFieldsValue({ queryMode: QueryWay.LATEST });
  226 + setFieldsValue({ startTs: 5000 });
  227 + setFieldsValue({ interval: 1000 });
  228 + dataCompareOpions = [{ label: '固定周期', value: QueryWay.LATEST }];
  229 + updateSchema({
  230 + defaultValue: QueryWay.LATEST,
  231 + field: SchemaFiled.WAY,
  232 + componentProps: {
  233 + options: dataCompareOpions,
  234 + },
  235 + });
  236 + }
  237 + },
  238 + maxLength: 250,
  239 + };
  240 + },
  241 + },
  242 + {
  243 + field: 'cycleType',
  244 + component: 'Select',
  245 + label: '周期',
  246 + required: true,
  247 + colProps: { span: 24 },
  248 + defaultValue: 0,
  249 + componentProps: {
  250 + placeholder: '请选择周期',
  251 + options: [
  252 + { label: '每日', value: 0 },
  253 + { label: '每周', value: 1 },
  254 + { label: '每月', value: 2 },
  255 + ],
  256 + },
  257 + ifShow: ({ values }) => isTiming(values.executeWay),
  258 + },
  259 + {
  260 + field: 'currentCycle',
  261 + component: 'ApiSelect',
  262 + label: '每周',
  263 + required: true,
  264 + colProps: { span: 24 },
  265 + defaultValue: '0 0 0 ? * MON',
  266 + componentProps: {
  267 + placeholder: '请选择周期',
  268 + api: findDictItemByCode,
  269 + params: {
  270 + dictCode: 'every_week',
  271 + },
  272 + labelField: 'itemText',
  273 + valueField: 'itemValue',
  274 + },
  275 + ifShow: ({ values }) => isWeek(values.cycleType),
  276 + },
  277 + {
  278 + field: 'cycleTime',
  279 + component: 'ApiSelect',
  280 + label: '每月',
  281 + required: true,
  282 + colProps: { span: 24 },
  283 + defaultValue: '0 0 0 1 * ? *',
  284 + componentProps: {
  285 + placeholder: '请选择月份',
  286 + api: findDictItemByCode,
  287 + params: {
  288 + dictCode: 'every_month',
  289 + },
  290 + labelField: 'itemText',
  291 + valueField: 'itemValue',
  292 + },
  293 + ifShow: ({ values }) => isMonth(values.cycleType),
  294 + },
  295 + {
  296 + field: 'cronTime',
  297 + component: 'ApiSelect',
  298 + label: '时间',
  299 + required: true,
  300 + colProps: { span: 24 },
  301 + defaultValue: '0 0 0 * * ?',
  302 + componentProps: {
  303 + placeholder: '请选择时间',
  304 + api: findDictItemByCode,
  305 + params: {
  306 + dictCode: 'every_day',
  307 + },
  308 + labelField: 'itemText',
  309 + valueField: 'itemValue',
  310 + },
  311 + ifShow: ({ values }) => isTiming(values.executeWay),
  312 + },
  313 + {
  314 + field: 'devices',
  315 + label: '设备',
  316 + component: 'Select',
  317 + slot: 'devices',
  318 + colProps: { span: 24 },
  319 + },
  320 + {
  321 + field: 'dataType',
  322 + label: '数据类型',
  323 + required: true,
  324 + component: 'Select',
  325 + componentProps: ({ formActionType }) => {
  326 + const { updateSchema, setFieldsValue } = formActionType;
  327 + const options = [
  328 + { label: '原始数据', value: 0 },
  329 + { label: '聚合数据', value: 1 },
  330 + ];
  331 + return {
  332 + options,
  333 + onSelect(e) {
  334 + let dataCompareOpions: any = [];
  335 + if (e == 0) {
  336 + setFieldsValue({ agg: 'NONE' });
  337 + dataCompareOpions = [{ label: '空', value: AggregateDataEnum.NONE }];
  338 + updateSchema({
  339 + field: SchemaFiled.AGG,
  340 + componentProps: {
  341 + options: dataCompareOpions,
  342 + },
  343 + });
  344 + } else {
  345 + setFieldsValue({ agg: '' });
  346 + dataCompareOpions = [
  347 + { label: '最小值', value: AggregateDataEnum.MIN },
  348 + { label: '最大值', value: AggregateDataEnum.MAX },
  349 + { label: '平均值', value: AggregateDataEnum.AVG },
  350 + { label: '求和', value: AggregateDataEnum.SUM },
  351 + { label: '计数', value: AggregateDataEnum.COUNT },
  352 + ];
  353 + updateSchema({
  354 + field: SchemaFiled.AGG,
  355 + componentProps: {
  356 + options: dataCompareOpions,
  357 + },
  358 + });
  359 + }
  360 + },
  361 + maxLength: 250,
  362 + placeholder: '请选择属性性质',
  363 + };
  364 + },
  365 + colProps: { span: 24 },
  366 + },
  367 + {
  368 + field: SchemaFiled.AGG,
  369 + label: '聚合条件',
  370 + component: 'Select',
  371 + required: true,
  372 + componentProps: {
  373 + placeholder: '请选择聚合条件',
  374 + getPopupContainer: () => document.body,
  375 + },
  376 + },
  377 + {
  378 + field: 'limit',
  379 + required: true,
  380 + label: '最大条数',
  381 + component: 'InputNumber',
  382 + defaultValue: 100,
  383 + ifShow({ values }) {
  384 + return values[SchemaFiled.AGG] === AggregateDataEnum.NONE;
  385 + },
  386 + colProps: { span: 12 },
  387 + componentProps: {
  388 + placeholder: '请输入最大条数',
  389 + min: 7,
  390 + max: 50000,
  391 + },
  392 + },
  393 + {
  394 + field: SchemaFiled.WAY,
  395 + label: '查询周期',
  396 + component: 'RadioGroup',
  397 + defaultValue: QueryWay.LATEST,
  398 + required: true,
  399 + componentProps({ formActionType }) {
  400 + const { setFieldsValue } = formActionType;
  401 + return {
  402 + placeholder: '请选择查询周期',
  403 + options: [
  404 + { label: '固定周期', value: QueryWay.LATEST },
  405 + { label: '自定义周期', value: QueryWay.TIME_PERIOD },
  406 + ],
  407 + onChange(value) {
  408 + console.log(value);
  409 + value === QueryWay.LATEST
  410 + ? setFieldsValue({
  411 + [SchemaFiled.DATE_RANGE]: [],
  412 + [SchemaFiled.START_TS]: null,
  413 + [SchemaFiled.END_TS]: null,
  414 + })
  415 + : setFieldsValue({ [SchemaFiled.START_TS]: null });
  416 + },
  417 + };
  418 + },
  419 + },
  420 + {
  421 + field: SchemaFiled.DATE_RANGE,
  422 + label: '时间段',
  423 + component: 'RangePicker',
  424 + required: true,
  425 + ifShow({ values }) {
  426 + return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && !isFixedTime(values.executeWay);
  427 + },
  428 + // componentProps: {
  429 + // showTime: {
  430 + // defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  431 + // },
  432 + // },
  433 + componentProps({ formActionType }) {
  434 + const { setFieldsValue } = formActionType;
  435 + let dates: Moment[] = [];
  436 + return {
  437 + showTime: {
  438 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  439 + },
  440 + onCalendarChange(value: Moment[]) {
  441 + dates = value;
  442 + },
  443 + disabledDate(current: Moment) {
  444 + if (!dates || dates.length === 0 || !current) {
  445 + return false;
  446 + }
  447 + const diffDate = current.diff(dates[0], 'years', true);
  448 + return Math.abs(diffDate) > 1;
  449 + },
  450 + onChange() {
  451 + dates = [];
  452 + setFieldsValue({ dateGroupGap: null });
  453 + },
  454 + getPopupContainer: () => document.body,
  455 + };
  456 + },
  457 + colProps: {
  458 + span: 10,
  459 + },
  460 + },
  461 + {
  462 + field: 'dateGroupGap',
  463 + label: '分组间隔',
  464 + component: 'Select',
  465 + dynamicRules: ({ model }) => {
  466 + return [
  467 + {
  468 + required: model[SchemaFiled.AGG] !== AggregateDataEnum.NONE,
  469 + message: '分组间隔为必填项',
  470 + type: 'number',
  471 + },
  472 + ];
  473 + },
  474 + ifShow({ values }) {
  475 + return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && !isFixedTime(values.executeWay);
  476 + },
  477 + componentProps({ formModel, formActionType }) {
  478 + const options =
  479 + formModel[SchemaFiled.WAY] === QueryWay.LATEST
  480 + ? getPacketIntervalByValue(formModel[SchemaFiled.START_TS])
  481 + : getPacketIntervalByRange(formModel[SchemaFiled.DATE_RANGE]);
  482 + if (formModel[SchemaFiled.AGG] !== AggregateDataEnum.NONE) {
  483 + formActionType.setFieldsValue({ [SchemaFiled.LIMIT]: null });
  484 + }
  485 + return {
  486 + options,
  487 + getPopupContainer: () => document.body,
  488 + };
  489 + },
  490 + },
  491 + {
  492 + field: SchemaFiled.START_TS,
  493 + label: '最近时间',
  494 + component: 'Select',
  495 + required: true,
  496 + ifShow({ values }) {
  497 + return values[SchemaFiled.WAY] == QueryWay.LATEST;
  498 + },
  499 + componentProps({ formActionType }) {
  500 + const { setFieldsValue } = formActionType;
  501 + return {
  502 + defaultValue: 1000,
  503 + placeholder: '请选择近期时间',
  504 + options: intervalOption,
  505 + onChange() {
  506 + setFieldsValue({ [SchemaFiled.INTERVAL]: null });
  507 + },
  508 + };
  509 + },
  510 + },
  511 + {
  512 + field: SchemaFiled.INTERVAL,
  513 + label: '间隔时间',
  514 + component: 'Select',
  515 + required: true,
  516 + ifShow({ values }) {
  517 + return values[SchemaFiled.WAY] == QueryWay.LATEST;
  518 + },
  519 + componentProps({ formModel, formActionType }) {
  520 + const options =
  521 + formModel[SchemaFiled.WAY] === QueryWay.LATEST
  522 + ? getPacketIntervalByValue(formModel[SchemaFiled.START_TS])
  523 + : getPacketIntervalByRange(formModel[SchemaFiled.DATE_RANGE]);
  524 + if (formModel[SchemaFiled.AGG] !== AggregateDataEnum.NONE) {
  525 + formActionType.setFieldsValue({ [SchemaFiled.LIMIT]: null });
  526 + }
  527 + return {
  528 + placeholder: '请选择间隔时间',
  529 + options,
  530 + };
  531 + },
  532 + },
  533 +];
... ...
1 1 import { FormSchema } from '/@/components/Form';
2 2 import { findDictItemByCode } from '/@/api/system/dict';
3   -import { h, ref } from 'vue';
  3 +import { h, ref, unref } from 'vue';
4 4 import { isExistDataManagerNameApi } from '/@/api/datamanager/dataManagerApi';
5 5 import { getDeviceProfile } from '/@/api/alarm/position';
6 6 import { BasicColumn, BasicTableProps } from '/@/components/Table';
... ... @@ -8,6 +8,8 @@ import { devicePage } from '/@/api/device/deviceManager';
8 8 import { Tag } from 'ant-design-vue';
9 9 import { DeviceRecord } from '/@/api/device/model/deviceModel';
10 10 import { FETCH_SETTING } from '/@/components/Table/src/const';
  11 +import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
  12 +import { useMessage } from '/@/hooks/web/useMessage';
11 13
12 14 const typeValue = ref('');
13 15 export enum CredentialsEnum {
... ... @@ -100,7 +102,8 @@ const deviceTableFormSchema: FormSchema[] = [
100 102 },
101 103 },
102 104 ];
103   -
  105 +const { clipboardRef, isSuccessRef } = useCopyToClipboard();
  106 +const { createMessage } = useMessage();
104 107 const deviceTableColumn: BasicColumn[] = [
105 108 {
106 109 title: '状态',
... ... @@ -125,8 +128,20 @@ const deviceTableColumn: BasicColumn[] = [
125 128 dataIndex: 'name',
126 129 customRender: ({ record }) => {
127 130 return h('div', [
128   - h('div', `${record.alias}/${record.name}`),
129   - // h('div', { class: 'text-blue-400 truncate', title: record.sn }, record.sn),
  131 + h(
  132 + 'div',
  133 + {
  134 + class: 'cursor-pointer',
  135 + onClick: () => {
  136 + clipboardRef.value = record.name;
  137 + if (unref(isSuccessRef)) createMessage.success('复制成功~');
  138 + },
  139 + },
  140 + [
  141 + h('div', { class: 'text-blue-400 truncate' }, record.alias),
  142 + h('div', { class: 'text-blue-400 truncate' }, record.name),
  143 + ]
  144 + ),
130 145 ]);
131 146 },
132 147 },
... ...
... ... @@ -15,6 +15,10 @@ import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
15 15 import useCommonFun from '../hooks/useCommonFun';
16 16 import { DeviceProfileModel } from '/@/api/device/model/deviceModel';
17 17 import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const';
  18 +import { useComponentRegister } from '/@/components/Form';
  19 +import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect';
  20 +
  21 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
18 22
19 23 const { useByProductGetAttribute } = useCommonFun();
20 24 export type TOption = {
... ... @@ -109,13 +113,8 @@ export const formSchema: FormSchema[] = [
109 113 field: 'organizationId',
110 114 label: '所属组织',
111 115 colProps: { span: 24 },
112   - component: 'ApiTreeSelect',
  116 + component: 'OrgTreeSelect',
113 117 componentProps: {
114   - api: async () => {
115   - const data = await screenLinkOrganizationGetApi();
116   - copyTransFun(data as any as any[]);
117   - return data;
118   - },
119 118 onChange(value) {
120 119 organizationId.value = value;
121 120 },
... ...
1 1 import { TaskTargetEnum, TaskTargetNameEnum, TaskTypeEnum, TaskTypeNameEnum } from '../../config';
2 2 import { findDictItemByCode } from '/@/api/system/dict';
3   -import { FormSchema, useComponentRegister } from '/@/components/Form';
  3 +import { FormSchema, Rule, useComponentRegister } from '/@/components/Form';
4 4 import {
5 5 DevicePicker,
6 6 validateDevicePicker,
... ... @@ -211,14 +211,18 @@ export const formSchemas: FormSchema[] = [
211 211 field: FormFieldsEnum.RPC_COMMAND,
212 212 component: 'PollCommandInput',
213 213 label: '自定义数据流',
214   - rules: [{ required: true, message: '请输入自定义数据流' }],
215   - dynamicRules: ({ model }) =>
216   - model[FormFieldsEnum.PUSH_WAY] === PushWayEnum.MQTT ? JSONEditorValidator() : [],
  214 + dynamicRules: ({ model }) => {
  215 + const rules: Rule[] = [{ required: true, message: '请输入自定义数据流' }];
  216 + return model[FormFieldsEnum.PUSH_WAY] === PushWayEnum.MQTT
  217 + ? [...rules, ...JSONEditorValidator()]
  218 + : rules;
  219 + },
217 220 ifShow: ({ model }) => model[FormFieldsEnum.EXECUTE_CONTENT_TYPE] === TaskTypeEnum.CUSTOM,
218 221 valueField: 'value',
219 222 changeEvent: 'update:value',
220   - componentProps: ({ formModel }) => {
  223 + componentProps: ({ formModel, formActionType }) => {
221 224 const pushMode = Reflect.get(formModel, FormFieldsEnum.PUSH_WAY);
  225 + formActionType?.clearValidate(FormFieldsEnum.RPC_COMMAND);
222 226 return {
223 227 inputProps: {
224 228 placeholder: '请输入自定义数据流',
... ... @@ -232,7 +236,9 @@ export const formSchemas: FormSchema[] = [
232 236 component: 'PollCommandInput',
233 237 label: 'ModbusRTU轮询',
234 238 rules: [{ required: true, message: '请输入Modbus RTU 轮询指令' }],
235   - ifShow: ({ model }) => model[FormFieldsEnum.EXECUTE_CONTENT_TYPE] === TaskTypeEnum.MODBUS_RTU,
  239 + ifShow: ({ model }) =>
  240 + model[FormFieldsEnum.EXECUTE_CONTENT_TYPE] === TaskTypeEnum.MODBUS_RTU &&
  241 + model[FormFieldsEnum.PUSH_WAY] === PushWayEnum.TCP,
236 242 valueField: 'value',
237 243 changeEvent: 'update:value',
238 244 componentProps: () => {
... ... @@ -345,6 +351,7 @@ export const formSchemas: FormSchema[] = [
345 351 field: FormFieldsEnum.EXECUTE_TIME_INTERVAL,
346 352 label: '间隔时间',
347 353 component: 'InputNumber',
  354 + rules: [{ required: true, message: '请输入间隔时间', type: 'number' }],
348 355 ifShow: ({ model }) => model[FormFieldsEnum.EXECUTE_TIME_TYPE] === ExecuteTimeTypeEnum.POLL,
349 356 componentProps: ({ formModel }) => {
350 357 const unit = formModel[FormFieldsEnum.POLL_UNIT];
... ...
... ... @@ -78,7 +78,7 @@ export const formSchemas: FormSchema[] = [
78 78 const result = await getDevicesByDeviceIds(data!);
79 79 return result.data.map((item) => ({
80 80 label: item.alias || item.name,
81   - value: 'tbDeviceId',
  81 + value: item.tbDeviceId,
82 82 }));
83 83 } else {
84 84 const result = await getMeetTheConditionsDevice({
... ... @@ -87,7 +87,7 @@ export const formSchemas: FormSchema[] = [
87 87 });
88 88 return result.map((item) => ({
89 89 label: item.alias || item.name,
90   - value: 'tbDeviceId',
  90 + value: item.tbDeviceId,
91 91 }));
92 92 }
93 93 } catch (error) {
... ...
1   -import { getOrganizationList } from '/@/api/system/system';
2   -import { FormSchema } from '/@/components/Form';
3   -import { copyTransFun } from '/@/utils/fnUtils';
  1 +import { FormSchema, useComponentRegister } from '/@/components/Form';
  2 +import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect';
4 3 export enum ViewType {
5 4 PRIVATE_VIEW = 'PRIVATE_VIEW',
6 5 PUBLIC_VIEW = 'PUBLIC_VIEW',
7 6 }
  7 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
8 8
9 9 export const formSchema: FormSchema[] = [
10 10 {
... ... @@ -19,20 +19,9 @@ export const formSchema: FormSchema[] = [
19 19 },
20 20 {
21 21 field: 'organizationId',
22   - component: 'ApiTreeSelect',
  22 + component: 'OrgTreeSelect',
23 23 label: '组织',
24 24 rules: [{ required: true, message: '组织为必填项' }],
25   - componentProps() {
26   - return {
27   - placeholder: '请选择组织',
28   - api: async () => {
29   - const data = await getOrganizationList();
30   - copyTransFun(data as any as any[]);
31   - return data;
32   - },
33   - getPopupContainer: () => document.body,
34   - };
35   - },
36 25 },
37 26 {
38 27 field: 'remark',
... ...