Commit 6d5dafbd7b5d256743b615ede074380361c11d8a
Merge branch 'ww' into 'main'
fix: BUG in teambition See merge request huang/yun-teng-iot-front!381
Showing
14 changed files
with
212 additions
and
167 deletions
@@ -6,8 +6,10 @@ import type { | @@ -6,8 +6,10 @@ import type { | ||
6 | ConfigurationCenterItemsModal, | 6 | ConfigurationCenterItemsModal, |
7 | } from './model/configurationCenterModal'; | 7 | } from './model/configurationCenterModal'; |
8 | import { getPageData } from '../../base'; | 8 | import { getPageData } from '../../base'; |
9 | +import { FileUploadResponse } from '../../oem/model'; | ||
9 | enum API { | 10 | enum API { |
10 | basicUrl = '/configuration/center', | 11 | basicUrl = '/configuration/center', |
12 | + UPLOAD = '/oss/upload', | ||
11 | } | 13 | } |
12 | 14 | ||
13 | export const getPage = (params: queryPageParams) => { | 15 | export const getPage = (params: queryPageParams) => { |
@@ -43,3 +45,7 @@ export const saveOrUpdateConfigurationCenter = ( | @@ -43,3 +45,7 @@ export const saveOrUpdateConfigurationCenter = ( | ||
43 | ) => { | 45 | ) => { |
44 | return isUpdate ? updateConfigurationCenter(params) : saveConfigurationCenter(params); | 46 | return isUpdate ? updateConfigurationCenter(params) : saveConfigurationCenter(params); |
45 | }; | 47 | }; |
48 | + | ||
49 | +export const uploadThumbnail = (file: FormData) => { | ||
50 | + return defHttp.post<FileUploadResponse>({ url: API.UPLOAD, params: file }); | ||
51 | +}; |
@@ -186,7 +186,7 @@ export const getGATEWAYdevice = async (params: { organization: string }) => { | @@ -186,7 +186,7 @@ export const getGATEWAYdevice = async (params: { organization: string }) => { | ||
186 | params, | 186 | params, |
187 | }); | 187 | }); |
188 | return Promise.resolve<{ label: string; value: string }[]>( | 188 | return Promise.resolve<{ label: string; value: string }[]>( |
189 | - res.map((item) => ({ label: item.name, value: item.id })) | 189 | + res.map((item) => ({ label: item.name, value: item.tbDeviceId })) |
190 | ); | 190 | ); |
191 | }; | 191 | }; |
192 | 192 |
src/assets/icons/configuration.svg
0 → 100644
1 | +<svg t="1667959039355" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2798" width="32" height="32"><path d="M860.068571 666.422857L726.857143 731.245714c-8.685714 4.205714-18.742857 4.205714-27.428572 0l-133.211428-64.822857A31.296 31.296 0 0 1 548.571429 638.262857V477.165714c0-11.977143 6.857143-22.948571 17.645714-28.16l133.211428-64.822857c8.685714-4.205714 18.742857-4.205714 27.428572 0l133.211428 64.822857c10.788571 5.211429 17.645714 16.182857 17.645715 28.16v161.097143c0 11.977143-6.857143 22.948571-17.645715 28.16z" fill="#B4D7FE" p-id="2799"></path><path d="M713.142857 701.988571V543.542857l-139.337143-68.571428M852.48 474.971429L713.142857 543.542857" fill="#B4D7FE" p-id="2800"></path><path d="M950.857143 146.285714H73.142857c-10.057143 0-18.285714 8.228571-18.285714 18.285715v621.714285c0 10.057143 8.228571 18.285714 18.285714 18.285715h205.714286v54.857142c0 10.057143 8.228571 18.285714 18.285714 18.285715h429.714286c10.057143 0 18.285714-8.228571 18.285714-18.285715v-54.857142H950.857143c10.057143 0 18.285714-8.228571 18.285714-18.285715V164.571429c0-10.057143-8.228571-18.285714-18.285714-18.285715zM708.571429 841.142857h-393.142858v-36.571428h393.142858v36.571428z m224-73.142857H91.428571V182.857143h841.142858v585.142857z" fill="#248BFF" p-id="2801"></path><path d="M182.857143 274.285714h201.142857v36.571429H182.857143z" fill="#B4D7FE" p-id="2802"></path><path d="M411.428571 237.714286H155.428571c-5.028571 0-9.142857 4.114286-9.142857 9.142857v457.142857c0 5.028571 4.114286 9.142857 9.142857 9.142857h256c5.028571 0 9.142857-4.114286 9.142858-9.142857V246.857143c0-5.028571-4.114286-9.142857-9.142858-9.142857z m-228.571428 36.571428h201.142857v36.571429H182.857143v-36.571429z m0 402.285715V347.428571h201.142857v329.142858H182.857143zM867.474286 452.571429l-146.285715-71.222858c-2.56-1.188571-5.302857-1.828571-8.045714-1.828571s-5.485714 0.64-8.045714 1.828571l-146.285714 71.222858c-6.217143 3.108571-10.24 9.417143-10.24 16.457142v177.371429c0 7.04 4.022857 13.348571 10.24 16.457143l146.285714 71.222857c2.56 1.188571 5.302857 1.828571 8.045714 1.828571s5.485714-0.64 8.045714-1.828571l146.285715-71.222857c6.308571-3.017143 10.24-9.417143 10.24-16.457143V469.028571c0-7.04-4.022857-13.348571-10.24-16.457142zM713.142857 418.102857l107.245714 52.205714-107.428571 52.937143c-0.64-0.365714-1.28-0.822857-1.92-1.097143l-105.142857-51.748571L713.142857 418.102857z m-128 82.834286l109.714286 54.034286v133.394285l-109.714286-53.394285V500.937143z m146.285714 187.428571V554.971429l109.714286-54.034286v134.034286l-109.714286 53.394285z" fill="#248BFF" p-id="2803"></path><path d="M347.428571 411.428571H219.428571c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h128c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285714zM859.428571 292.571429H484.571429c-10.057143 0-18.285714-8.228571-18.285715-18.285715s8.228571-18.285714 18.285715-18.285714h374.857142c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285715zM667.428571 356.571429H484.571429c-10.057143 0-18.285714-8.228571-18.285715-18.285715s8.228571-18.285714 18.285715-18.285714h182.857142c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285715zM548.571429 420.571429h-64c-10.057143 0-18.285714-8.228571-18.285715-18.285715s8.228571-18.285714 18.285715-18.285714h64c10.057143 0 18.285714 8.228571 18.285714 18.285714s-8.228571 18.285714-18.285714 18.285715zM237.714286 475.428571h-18.285715c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h18.285715c10.057143 0 18.285714 8.228571 18.285714 18.285714s-8.228571 18.285714-18.285714 18.285714z" fill="#248BFF" p-id="2804"></path><path d="M301.714286 539.428571h-82.285715c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h82.285715c10.057143 0 18.285714 8.228571 18.285714 18.285714s-8.228571 18.285714-18.285714 18.285714z" fill="#248BFF" p-id="2805"></path><path d="M274.285714 603.428571h-54.857143c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h54.857143c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285714z" fill="#248BFF" p-id="2806"></path></svg> |
src/assets/images/configuration.png
0 → 100644
871 Bytes
@@ -4,10 +4,10 @@ | @@ -4,10 +4,10 @@ | ||
4 | }; | 4 | }; |
5 | </script> | 5 | </script> |
6 | <script lang="ts" setup> | 6 | <script lang="ts" setup> |
7 | - import { Upload, Spin } from 'ant-design-vue'; | 7 | + import { Upload, Spin, Tooltip } from 'ant-design-vue'; |
8 | import { InboxOutlined } from '@ant-design/icons-vue'; | 8 | import { InboxOutlined } from '@ant-design/icons-vue'; |
9 | import { useMessage } from '/@/hooks/web/useMessage'; | 9 | import { useMessage } from '/@/hooks/web/useMessage'; |
10 | - import { computed, ref, unref, useAttrs } from 'vue'; | 10 | + import { computed, ref, unref } from 'vue'; |
11 | import { cloneDeep } from 'lodash-es'; | 11 | import { cloneDeep } from 'lodash-es'; |
12 | import { isFunction, isNumber, isObject } from '/@/utils/is'; | 12 | import { isFunction, isNumber, isObject } from '/@/utils/is'; |
13 | import { useDesign } from '/@/hooks/web/useDesign'; | 13 | import { useDesign } from '/@/hooks/web/useDesign'; |
@@ -23,8 +23,6 @@ | @@ -23,8 +23,6 @@ | ||
23 | const { prefixCls } = useDesign('api-upload'); | 23 | const { prefixCls } = useDesign('api-upload'); |
24 | const emit = defineEmits(['update:fileList', 'preview', 'download']); | 24 | const emit = defineEmits(['update:fileList', 'preview', 'download']); |
25 | 25 | ||
26 | - const attrs = useAttrs(); | ||
27 | - | ||
28 | const { createMessage } = useMessage(); | 26 | const { createMessage } = useMessage(); |
29 | 27 | ||
30 | const loading = ref(false); | 28 | const loading = ref(false); |
@@ -70,6 +68,16 @@ | @@ -70,6 +68,16 @@ | ||
70 | return disabled ? disabled : unref(componentDisabled); | 68 | return disabled ? disabled : unref(componentDisabled); |
71 | }); | 69 | }); |
72 | 70 | ||
71 | + const isPictureCard = computed(() => { | ||
72 | + const { listType } = props; | ||
73 | + return listType === 'picture-card'; | ||
74 | + }); | ||
75 | + | ||
76 | + const getMaxFileLimit = computed(() => { | ||
77 | + const { maxFileLimit } = props; | ||
78 | + return isPictureCard.value ? 1 : maxFileLimit; | ||
79 | + }); | ||
80 | + | ||
73 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { | 81 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { |
74 | try { | 82 | try { |
75 | setUploadStatus(true); | 83 | setUploadStatus(true); |
@@ -78,10 +86,10 @@ | @@ -78,10 +86,10 @@ | ||
78 | if (api && isFunction(api)) { | 86 | if (api && isFunction(api)) { |
79 | const data = await api(file); | 87 | const data = await api(file); |
80 | if (isObject(data) && Reflect.has(data, 'uid') && Reflect.has(data, 'name')) { | 88 | if (isObject(data) && Reflect.has(data, 'uid') && Reflect.has(data, 'name')) { |
81 | - const { fileList, maxFileLimit } = props; | 89 | + const { fileList } = props; |
82 | let _fileList = cloneDeep(fileList); | 90 | let _fileList = cloneDeep(fileList); |
83 | 91 | ||
84 | - if (isNumber(maxFileLimit) && _fileList.length === maxFileLimit) { | 92 | + if (isNumber(unref(getMaxFileLimit)) && _fileList.length === unref(getMaxFileLimit)) { |
85 | _fileList.splice(0, 1); | 93 | _fileList.splice(0, 1); |
86 | } | 94 | } |
87 | 95 | ||
@@ -106,49 +114,36 @@ | @@ -106,49 +114,36 @@ | ||
106 | emit('update:fileList', _fileList); | 114 | emit('update:fileList', _fileList); |
107 | }; | 115 | }; |
108 | 116 | ||
109 | - const defaultPreview = (file: FileItem) => { | ||
110 | - console.log('default preview', file); | ||
111 | - }; | ||
112 | - | ||
113 | - const defaultDownload = (file: FileItem) => { | ||
114 | - console.log('default download', file); | ||
115 | - }; | ||
116 | - | ||
117 | const handlePreview = (file: FileItem) => { | 117 | const handlePreview = (file: FileItem) => { |
118 | - if (Reflect.has(attrs, 'preview')) { | ||
119 | - emit('preview', file); | ||
120 | - return; | ||
121 | - } | ||
122 | - defaultPreview(file); | 118 | + emit('preview', file); |
123 | }; | 119 | }; |
124 | 120 | ||
125 | const handleDownload = (file: FileItem) => { | 121 | const handleDownload = (file: FileItem) => { |
126 | - if (Reflect.has(attrs, 'download')) { | ||
127 | - emit('download', file); | ||
128 | - return; | ||
129 | - } | ||
130 | - defaultDownload(file); | 122 | + emit('download', file); |
131 | }; | 123 | }; |
132 | </script> | 124 | </script> |
133 | 125 | ||
134 | <template> | 126 | <template> |
135 | - <Upload.Dragger | 127 | + <Upload |
136 | class="block" | 128 | class="block" |
137 | :class="prefixCls" | 129 | :class="prefixCls" |
138 | :file-list="props.fileList" | 130 | :file-list="props.fileList" |
131 | + :list-type="props.listType" | ||
139 | :disabled="getDisabled" | 132 | :disabled="getDisabled" |
140 | :before-upload="handleBeforeUpload" | 133 | :before-upload="handleBeforeUpload" |
141 | @preview="handlePreview" | 134 | @preview="handlePreview" |
142 | @download="handleDownload" | 135 | @download="handleDownload" |
143 | :remove="handleRemove" | 136 | :remove="handleRemove" |
144 | > | 137 | > |
145 | - <Spin :spinning="loading"> | 138 | + <Spin v-if="!fileList.length" :spinning="loading"> |
146 | <div class="w-full h-full flex flex-col justify-center content-center"> | 139 | <div class="w-full h-full flex flex-col justify-center content-center"> |
147 | - <InboxOutlined class="text-[3rem] !text-blue-500" /> | ||
148 | - <div class="m-2 text-gray-400">点击上传或拖拽上传</div> | 140 | + <Tooltip title="点击上传或拖拽上传"> |
141 | + <InboxOutlined class="text-[3rem] !text-blue-500" /> | ||
142 | + </Tooltip> | ||
143 | + <div v-if="!isPictureCard" class="m-2 text-gray-400 text-sm">点击上传或拖拽上传</div> | ||
149 | </div> | 144 | </div> |
150 | </Spin> | 145 | </Spin> |
151 | - </Upload.Dragger> | 146 | + </Upload> |
152 | </template> | 147 | </template> |
153 | 148 | ||
154 | <style lang="less"> | 149 | <style lang="less"> |
@@ -164,6 +159,12 @@ | @@ -164,6 +159,12 @@ | ||
164 | .ant-upload-list-item-name { | 159 | .ant-upload-list-item-name { |
165 | width: calc(100% - 22px); | 160 | width: calc(100% - 22px); |
166 | } | 161 | } |
162 | + | ||
163 | + .ant-upload-select-text { | ||
164 | + width: 100%; | ||
165 | + text-align: center; | ||
166 | + border: 1px dashed #d9d9d9; | ||
167 | + } | ||
167 | } | 168 | } |
168 | } | 169 | } |
169 | </style> | 170 | </style> |
@@ -245,69 +245,25 @@ | @@ -245,69 +245,25 @@ | ||
245 | </Space> | 245 | </Space> |
246 | </div> | 246 | </div> |
247 | </div> | 247 | </div> |
248 | - <List | ||
249 | - :loading="loading" | ||
250 | - :data-source="cameraList" | ||
251 | - class="bg-light-50 flex-auto dark:bg-dark-900 split-mode-list" | ||
252 | - :grid="gridLayout" | ||
253 | - :style="{ '--height': `${100 / pagination.colNumber}%` }" | ||
254 | - > | ||
255 | - <template #renderItem="{ item }"> | ||
256 | - <List.Item> | ||
257 | - <div class="box-border w-full h-full p-1px"> | ||
258 | - <div | ||
259 | - v-if="item.placeholder" | ||
260 | - class="bg-black w-full h-full overflow-hidden relative" | ||
261 | - ></div> | ||
262 | - <div | ||
263 | - v-if="!item.placeholder" | ||
264 | - class="bg-black w-full h-full overflow-hidden relative video-container" | ||
265 | - > | ||
266 | - <Spin v-show="!item.isTransform" :spinning="!item.isTransform"> | ||
267 | - <div class="bg-black text-light-50"> </div> | ||
268 | - </Spin> | ||
269 | - <VideoPlay | ||
270 | - v-show="item.isTransform" | ||
271 | - @loadstart="handleLoadStart(item)" | ||
272 | - @loadeddata="handleLoadData(item)" | ||
273 | - v-bind="options" | ||
274 | - :src="item.videoUrl" | ||
275 | - :title="item.name" | ||
276 | - :type="item.type" | ||
277 | - /> | 248 | + <section ref="videoContainer" class="flex-auto"> |
249 | + <List | ||
250 | + :loading="loading" | ||
251 | + :data-source="cameraList" | ||
252 | + class="bg-light-50 w-full h-full dark:bg-dark-900 split-mode-list" | ||
253 | + :grid="gridLayout" | ||
254 | + :style="{ '--height': `${100 / pagination.colNumber}%` }" | ||
255 | + > | ||
256 | + <template #renderItem="{ item }"> | ||
257 | + <List.Item> | ||
258 | + <div class="box-border w-full h-full p-1px"> | ||
278 | <div | 259 | <div |
279 | - v-if="item.isTransform && isDef(item.canPlay) && !item.canPlay" | ||
280 | - class="video-container-error-msk absolute top-0 left-0 text-lg w-full h-full text-light-50 flex justify-center items-center z-50 bg-black" | ||
281 | - > | ||
282 | - 视频加载出错了! | ||
283 | - </div> | 260 | + v-if="item.placeholder" |
261 | + class="bg-black w-full h-full overflow-hidden relative" | ||
262 | + ></div> | ||
284 | <div | 263 | <div |
285 | - class="video-container-mask absolute top-0 left-0 z-50 text-lg w-full text-light-50 flex justify-center items-center" | ||
286 | - style="height: 100%; background-color: rgba(0, 0, 0, 0.5)" | 264 | + v-if="!item.placeholder" |
265 | + class="bg-black w-full h-full overflow-hidden relative video-container" | ||
287 | > | 266 | > |
288 | - <span>{{ item.name }}</span> | ||
289 | - </div> | ||
290 | - </div> | ||
291 | - </div> | ||
292 | - </List.Item> | ||
293 | - </template> | ||
294 | - </List> | ||
295 | - <!-- <section ref="videoContainer" class="bg-light-50 flex-auto dark:bg-dark-900"> | ||
296 | - <Spin :spinning="loading" class="h-full"> | ||
297 | - <Empty | ||
298 | - class="h-full flex flex-col justify-center items-center" | ||
299 | - v-if="!cameraList.length" | ||
300 | - /> | ||
301 | - <Row :gutter="8" class="h-full mx-0 content-start"> | ||
302 | - <Col | ||
303 | - v-for="item in cameraList" | ||
304 | - :key="item.id" | ||
305 | - :style="{ height: `${100 / pagination.colNumber}%` }" | ||
306 | - class="h-1/2 !px-0 !flex justify-center items-center" | ||
307 | - :span="getColLayout" | ||
308 | - > | ||
309 | - <div class="box-border w-full h-full p-1px"> | ||
310 | - <div class="bg-black w-full h-full overflow-hidden relative video-container"> | ||
311 | <Spin v-show="!item.isTransform" :spinning="!item.isTransform"> | 267 | <Spin v-show="!item.isTransform" :spinning="!item.isTransform"> |
312 | <div class="bg-black text-light-50"> </div> | 268 | <div class="bg-black text-light-50"> </div> |
313 | </Spin> | 269 | </Spin> |
@@ -334,10 +290,10 @@ | @@ -334,10 +290,10 @@ | ||
334 | </div> | 290 | </div> |
335 | </div> | 291 | </div> |
336 | </div> | 292 | </div> |
337 | - </Col> | ||
338 | - </Row> | ||
339 | - </Spin> | ||
340 | - </section> --> | 293 | + </List.Item> |
294 | + </template> | ||
295 | + </List> | ||
296 | + </section> | ||
341 | </section> | 297 | </section> |
342 | </PageWrapper> | 298 | </PageWrapper> |
343 | <CameraDrawer @register="registerDrawer" @success="getCameraList" /> | 299 | <CameraDrawer @register="registerDrawer" @success="getCameraList" /> |
@@ -17,6 +17,8 @@ | @@ -17,6 +17,8 @@ | ||
17 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | 17 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
18 | import { useMessage } from '/@/hooks/web/useMessage'; | 18 | import { useMessage } from '/@/hooks/web/useMessage'; |
19 | import { saveOrUpdateConfigurationCenter } from '/@/api/configuration/center/configurationCenter'; | 19 | import { saveOrUpdateConfigurationCenter } from '/@/api/configuration/center/configurationCenter'; |
20 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
21 | + import { buildUUID } from '/@/utils/uuid'; | ||
20 | 22 | ||
21 | export default defineComponent({ | 23 | export default defineComponent({ |
22 | name: 'ConfigurationDrawer', | 24 | name: 'ConfigurationDrawer', |
@@ -36,6 +38,11 @@ | @@ -36,6 +38,11 @@ | ||
36 | setDrawerProps({ confirmLoading: false }); | 38 | setDrawerProps({ confirmLoading: false }); |
37 | isUpdate.value = !!data?.isUpdate; | 39 | isUpdate.value = !!data?.isUpdate; |
38 | if (unref(isUpdate)) { | 40 | if (unref(isUpdate)) { |
41 | + if (data.record.thumbnail) { | ||
42 | + data.record.thumbnail = [ | ||
43 | + { uid: buildUUID(), name: 'name', url: data.record.thumbnail } as FileItem, | ||
44 | + ]; | ||
45 | + } | ||
39 | if (data.record.organizationDTO) { | 46 | if (data.record.organizationDTO) { |
40 | await setFieldsValue(data.record); | 47 | await setFieldsValue(data.record); |
41 | } else { | 48 | } else { |
@@ -51,9 +58,14 @@ | @@ -51,9 +58,14 @@ | ||
51 | try { | 58 | try { |
52 | const { createMessage } = useMessage(); | 59 | const { createMessage } = useMessage(); |
53 | const values = await validate(); | 60 | const values = await validate(); |
61 | + if (Reflect.has(values, 'thumbnail')) { | ||
62 | + const file = (values.thumbnail || []).at(0) || {}; | ||
63 | + values.thumbnail = file.url || null; | ||
64 | + } | ||
54 | setDrawerProps({ confirmLoading: true }); | 65 | setDrawerProps({ confirmLoading: true }); |
55 | let saveMessage = '添加成功'; | 66 | let saveMessage = '添加成功'; |
56 | let updateMessage = '修改成功'; | 67 | let updateMessage = '修改成功'; |
68 | + console.log(values); | ||
57 | await saveOrUpdateConfigurationCenter(values, unref(isUpdate)); | 69 | await saveOrUpdateConfigurationCenter(values, unref(isUpdate)); |
58 | closeDrawer(); | 70 | closeDrawer(); |
59 | emit('success'); | 71 | emit('success'); |
1 | import { BasicColumn, FormSchema } from '/@/components/Table'; | 1 | import { BasicColumn, FormSchema } from '/@/components/Table'; |
2 | import { getOrganizationList } from '/@/api/system/system'; | 2 | import { getOrganizationList } from '/@/api/system/system'; |
3 | import { copyTransFun } from '/@/utils/fnUtils'; | 3 | import { copyTransFun } from '/@/utils/fnUtils'; |
4 | +import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
5 | +import { createImgPreview } from '/@/components/Preview'; | ||
6 | +import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter'; | ||
4 | export enum Platform { | 7 | export enum Platform { |
5 | PHONE = 'phone', | 8 | PHONE = 'phone', |
6 | PC = 'pc', | 9 | PC = 'pc', |
@@ -64,6 +67,37 @@ export const searchFormSchema: FormSchema[] = [ | @@ -64,6 +67,37 @@ export const searchFormSchema: FormSchema[] = [ | ||
64 | 67 | ||
65 | export const formSchema: FormSchema[] = [ | 68 | export const formSchema: FormSchema[] = [ |
66 | { | 69 | { |
70 | + field: 'thumbnail', | ||
71 | + label: '缩略图', | ||
72 | + component: 'ApiUpload', | ||
73 | + changeEvent: 'update:fileList', | ||
74 | + valueField: 'fileList', | ||
75 | + componentProps: () => { | ||
76 | + return { | ||
77 | + listType: 'picture-card', | ||
78 | + maxFileLimit: 1, | ||
79 | + api: async (file: File) => { | ||
80 | + try { | ||
81 | + const formData = new FormData(); | ||
82 | + formData.set('file', file); | ||
83 | + const { fileStaticUri, fileName } = await uploadThumbnail(formData); | ||
84 | + return { | ||
85 | + uid: fileStaticUri, | ||
86 | + name: fileName, | ||
87 | + url: fileStaticUri, | ||
88 | + } as FileItem; | ||
89 | + } catch (error) { | ||
90 | + return {}; | ||
91 | + } | ||
92 | + }, | ||
93 | + onPreview: (fileList: FileItem) => { | ||
94 | + createImgPreview({ imageList: [fileList.url!] }); | ||
95 | + }, | ||
96 | + }; | ||
97 | + }, | ||
98 | + }, | ||
99 | + | ||
100 | + { | ||
67 | field: 'name', | 101 | field: 'name', |
68 | label: '组态名称', | 102 | label: '组态名称', |
69 | required: true, | 103 | required: true, |
@@ -25,6 +25,8 @@ | @@ -25,6 +25,8 @@ | ||
25 | import { useDrawer } from '/@/components/Drawer'; | 25 | import { useDrawer } from '/@/components/Drawer'; |
26 | import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; | 26 | import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; |
27 | import { getBoundingClientRect } from '/@/utils/domUtils'; | 27 | import { getBoundingClientRect } from '/@/utils/domUtils'; |
28 | + import configurationSrc from '/@/assets/icons/configuration.svg'; | ||
29 | + import { cloneDeep } from 'lodash'; | ||
28 | 30 | ||
29 | const listColumn = ref(4); | 31 | const listColumn = ref(4); |
30 | 32 | ||
@@ -98,7 +100,7 @@ | @@ -98,7 +100,7 @@ | ||
98 | if (record) { | 100 | if (record) { |
99 | openDrawer(true, { | 101 | openDrawer(true, { |
100 | isUpdate: true, | 102 | isUpdate: true, |
101 | - record, | 103 | + record: cloneDeep(record), |
102 | }); | 104 | }); |
103 | } else { | 105 | } else { |
104 | openDrawer(true, { | 106 | openDrawer(true, { |
@@ -204,8 +206,9 @@ | @@ -204,8 +206,9 @@ | ||
204 | <Card hoverable> | 206 | <Card hoverable> |
205 | <template #cover> | 207 | <template #cover> |
206 | <img | 208 | <img |
209 | + class="w-36 h-36 flex justify-center items-center" | ||
207 | alt="example" | 210 | alt="example" |
208 | - src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png" | 211 | + :src="item.thumbnail || configurationSrc" |
209 | /> | 212 | /> |
210 | </template> | 213 | </template> |
211 | <template class="ant-card-actions" #actions> | 214 | <template class="ant-card-actions" #actions> |
@@ -242,8 +245,10 @@ | @@ -242,8 +245,10 @@ | ||
242 | </template> | 245 | </template> |
243 | <Card.Meta :title="item.name"> | 246 | <Card.Meta :title="item.name"> |
244 | <template #description> | 247 | <template #description> |
245 | - <div class="truncate">{{ item.organizationDTO.name }}</div> | ||
246 | - <div class="truncate">{{ item.remark }} </div> | 248 | + <div class="truncate h-11"> |
249 | + <div class="truncate">{{ item.organizationDTO.name }}</div> | ||
250 | + <div class="truncate">{{ item.remark || '' }} </div> | ||
251 | + </div> | ||
247 | </template> | 252 | </template> |
248 | </Card.Meta> | 253 | </Card.Meta> |
249 | </Card> | 254 | </Card> |
@@ -34,6 +34,12 @@ export const step1Schemas: FormSchema[] = [ | @@ -34,6 +34,12 @@ export const step1Schemas: FormSchema[] = [ | ||
34 | slot: 'snCode', | 34 | slot: 'snCode', |
35 | }, | 35 | }, |
36 | { | 36 | { |
37 | + field: 'transportType', | ||
38 | + label: '类型', | ||
39 | + component: 'Input', | ||
40 | + show: false, | ||
41 | + }, | ||
42 | + { | ||
37 | field: 'profileId', | 43 | field: 'profileId', |
38 | label: '所属产品', | 44 | label: '所属产品', |
39 | required: true, | 45 | required: true, |
@@ -44,9 +50,9 @@ export const step1Schemas: FormSchema[] = [ | @@ -44,9 +50,9 @@ export const step1Schemas: FormSchema[] = [ | ||
44 | api: deviceProfile, | 50 | api: deviceProfile, |
45 | labelField: 'name', | 51 | labelField: 'name', |
46 | valueField: 'tbProfileId', | 52 | valueField: 'tbProfileId', |
47 | - onChange(_value: string, option: { deviceType: string }) { | ||
48 | - const { deviceType } = option; | ||
49 | - setFieldsValue({ deviceType: deviceType }); | 53 | + onChange(_value: string, option: { deviceType: string; transportType: string }) { |
54 | + const { deviceType, transportType } = option; | ||
55 | + setFieldsValue({ deviceType: deviceType, transportType }); | ||
50 | }, | 56 | }, |
51 | }; | 57 | }; |
52 | }, | 58 | }, |
@@ -69,6 +75,17 @@ export const step1Schemas: FormSchema[] = [ | @@ -69,6 +75,17 @@ export const step1Schemas: FormSchema[] = [ | ||
69 | }, | 75 | }, |
70 | }, | 76 | }, |
71 | { | 77 | { |
78 | + field: 'code', | ||
79 | + label: '地址码', | ||
80 | + component: 'Input', | ||
81 | + ifShow: ({ model }) => { | ||
82 | + return model['transportType'] === 'TCP'; | ||
83 | + }, | ||
84 | + dynamicRules: ({ model }) => { | ||
85 | + return [{ required: model['transportType'] === 'TCP', message: '地址码为必填项' }]; | ||
86 | + }, | ||
87 | + }, | ||
88 | + { | ||
72 | field: 'brand', | 89 | field: 'brand', |
73 | component: 'ApiRadioGroup', | 90 | component: 'ApiRadioGroup', |
74 | label: '选择厂家', | 91 | label: '选择厂家', |
@@ -110,72 +110,79 @@ | @@ -110,72 +110,79 @@ | ||
110 | // 提交 | 110 | // 提交 |
111 | const msg = computed(() => (unref(isUpdate) ? '更新设备成功' : '新增设备成功')); | 111 | const msg = computed(() => (unref(isUpdate) ? '更新设备成功' : '新增设备成功')); |
112 | async function handleOk() { | 112 | async function handleOk() { |
113 | - if (current.value === 0) { | ||
114 | - // 验证 | ||
115 | - const valid = await unref(DeviceStep1Ref)?.parentValidate(); | ||
116 | - if (!valid) return; | ||
117 | - stepState.value = unref(DeviceStep1Ref)?.parentGetFieldsValue(); | ||
118 | - } else { | ||
119 | - // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded | ||
120 | - Reflect.deleteProperty(stepState.value, 'map'); | ||
121 | - Reflect.deleteProperty(stepState.value, 'marker'); | ||
122 | - if (unref(DeviceStep2Ref)?.getFieldsValue().addAgree) { | ||
123 | - const valid = await unref(DeviceStep2Ref)?.validate(); | 113 | + try { |
114 | + if (current.value === 0) { | ||
115 | + // 验证 | ||
116 | + const valid = await unref(DeviceStep1Ref)?.parentValidate(); | ||
124 | if (!valid) return; | 117 | if (!valid) return; |
125 | - // 第二页验证通过情况 | ||
126 | - stepState.value = { | 118 | + stepState.value = unref(DeviceStep1Ref)?.parentGetFieldsValue(); |
119 | + } else { | ||
120 | + // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded | ||
121 | + Reflect.deleteProperty(stepState.value, 'map'); | ||
122 | + Reflect.deleteProperty(stepState.value, 'marker'); | ||
123 | + if (unref(DeviceStep2Ref)?.getFieldsValue().addAgree) { | ||
124 | + const valid = await unref(DeviceStep2Ref)?.validate(); | ||
125 | + if (!valid) return; | ||
126 | + // 第二页验证通过情况 | ||
127 | + stepState.value = { | ||
128 | + ...unref(stepState), | ||
129 | + ...unref(DeviceStep2Ref)?.getFieldsValue(), | ||
130 | + }; | ||
131 | + } | ||
132 | + } | ||
133 | + // 验证成功 --调-- 新增或者编辑接口 | ||
134 | + // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded | ||
135 | + Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'map'); | ||
136 | + Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'marker'); | ||
137 | + setModalProps({ | ||
138 | + confirmLoading: true, | ||
139 | + }); | ||
140 | + if (unref(isUpdate)) { | ||
141 | + const editData = { | ||
127 | ...unref(stepState), | 142 | ...unref(stepState), |
128 | - ...unref(DeviceStep2Ref)?.getFieldsValue(), | 143 | + deviceInfo: { |
144 | + avatar: DeviceStep1Ref.value?.devicePic, | ||
145 | + ...DeviceStep1Ref.value?.positionState, | ||
146 | + }, | ||
129 | }; | 147 | }; |
148 | + await createOrEditDevice(editData); | ||
149 | + } else { | ||
150 | + const createData = { | ||
151 | + ...unref(stepState), | ||
152 | + deviceInfo: { | ||
153 | + avatar: DeviceStep1Ref.value?.devicePic, | ||
154 | + ...DeviceStep1Ref.value?.positionState, | ||
155 | + }, | ||
156 | + deviceToken: | ||
157 | + unref(current) === 0 || !unref(stepState).addAgree | ||
158 | + ? null | ||
159 | + : { | ||
160 | + credentialsType: unref(stepState).credentialType, | ||
161 | + credentialsId: unref(stepState).credentialsId, | ||
162 | + credentialsValue: | ||
163 | + unref(stepState).credentialType === credentialTypeEnum.MQTT_BASIC | ||
164 | + ? JSON.stringify({ | ||
165 | + userName: unref(stepState).username, | ||
166 | + password: unref(stepState).password, | ||
167 | + clientId: unref(stepState).clientId, | ||
168 | + }) | ||
169 | + : unref(stepState).credentialType === credentialTypeEnum.X_509 | ||
170 | + ? unref(stepState).publicKey | ||
171 | + : null, | ||
172 | + }, | ||
173 | + }; | ||
174 | + await createOrEditDevice(createData); | ||
130 | } | 175 | } |
176 | + createMessage.success(unref(msg)); | ||
177 | + handleCancel(); | ||
178 | + closeModal(); | ||
179 | + emit('reload'); | ||
180 | + } catch (error) { | ||
181 | + } finally { | ||
182 | + setModalProps({ | ||
183 | + confirmLoading: false, | ||
184 | + }); | ||
131 | } | 185 | } |
132 | - // 验证成功 --调-- 新增或者编辑接口 | ||
133 | - // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded | ||
134 | - Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'map'); | ||
135 | - Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'marker'); | ||
136 | - setModalProps({ | ||
137 | - confirmLoading: true, | ||
138 | - }); | ||
139 | - if (unref(isUpdate)) { | ||
140 | - const editData = { | ||
141 | - ...unref(stepState), | ||
142 | - deviceInfo: { | ||
143 | - avatar: DeviceStep1Ref.value?.devicePic, | ||
144 | - ...DeviceStep1Ref.value?.positionState, | ||
145 | - }, | ||
146 | - }; | ||
147 | - await createOrEditDevice(editData); | ||
148 | - } else { | ||
149 | - const createData = { | ||
150 | - ...unref(stepState), | ||
151 | - deviceInfo: { | ||
152 | - avatar: DeviceStep1Ref.value?.devicePic, | ||
153 | - ...DeviceStep1Ref.value?.positionState, | ||
154 | - }, | ||
155 | - deviceToken: | ||
156 | - unref(current) === 0 || !unref(stepState).addAgree | ||
157 | - ? null | ||
158 | - : { | ||
159 | - credentialsType: unref(stepState).credentialType, | ||
160 | - credentialsId: unref(stepState).credentialsId, | ||
161 | - credentialsValue: | ||
162 | - unref(stepState).credentialType === credentialTypeEnum.MQTT_BASIC | ||
163 | - ? JSON.stringify({ | ||
164 | - userName: unref(stepState).username, | ||
165 | - password: unref(stepState).password, | ||
166 | - clientId: unref(stepState).clientId, | ||
167 | - }) | ||
168 | - : unref(stepState).credentialType === credentialTypeEnum.X_509 | ||
169 | - ? unref(stepState).publicKey | ||
170 | - : null, | ||
171 | - }, | ||
172 | - }; | ||
173 | - await createOrEditDevice(createData); | ||
174 | - } | ||
175 | - createMessage.success(unref(msg)); | ||
176 | - handleCancel(); | ||
177 | - closeModal(); | ||
178 | - emit('reload'); | ||
179 | } | 186 | } |
180 | return { | 187 | return { |
181 | getTitle, | 188 | getTitle, |
1 | <template> | 1 | <template> |
2 | <div class="wrapper"> | 2 | <div class="wrapper"> |
3 | <div ref="wrapRef" :style="{ height, width }"> </div> | 3 | <div ref="wrapRef" :style="{ height, width }"> </div> |
4 | - <div class="right-wrap"> | ||
5 | - <BasicTable style="cursor: pointer" @register="registerTable" @rowClick="deviceRowClick"> | 4 | + <div class="right-wrap !dark:bg-dark-900"> |
5 | + <BasicTable | ||
6 | + style="cursor: pointer" | ||
7 | + @register="registerTable" | ||
8 | + @rowClick="deviceRowClick" | ||
9 | + class="dark:bg-dark-900" | ||
10 | + > | ||
6 | <template #deviceState="{ record }"> | 11 | <template #deviceState="{ record }"> |
7 | <Tag | 12 | <Tag |
8 | :color=" | 13 | :color=" |
@@ -42,7 +42,7 @@ | @@ -42,7 +42,7 @@ | ||
42 | import ConverScriptModal from '/@/views/scriptmanage/converscript/ConverScriptModal.vue'; | 42 | import ConverScriptModal from '/@/views/scriptmanage/converscript/ConverScriptModal.vue'; |
43 | 43 | ||
44 | const { createMessage } = useMessage(); | 44 | const { createMessage } = useMessage(); |
45 | - const selectScript = reactive({ | 45 | + const selectScript = reactive<Record<'script', Nullable<string>>>({ |
46 | script: null, | 46 | script: null, |
47 | }); | 47 | }); |
48 | const selectOptions: Ref<SelectTypes['options']> = ref([]); | 48 | const selectOptions: Ref<SelectTypes['options']> = ref([]); |
@@ -55,7 +55,7 @@ | @@ -55,7 +55,7 @@ | ||
55 | }; | 55 | }; |
56 | }); | 56 | }); |
57 | }); | 57 | }); |
58 | - const handleSuccess = async () => { | 58 | + const handleSuccess = async (val: { id: string }) => { |
59 | const res = await getScriptManageMeList(); | 59 | const res = await getScriptManageMeList(); |
60 | selectOptions.value = res.map((m) => { | 60 | selectOptions.value = res.map((m) => { |
61 | return { | 61 | return { |
@@ -63,6 +63,7 @@ | @@ -63,6 +63,7 @@ | ||
63 | value: m.id, | 63 | value: m.id, |
64 | }; | 64 | }; |
65 | }); | 65 | }); |
66 | + selectScript.script = val.id; | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | const [register] = useForm({ | 69 | const [register] = useForm({ |
@@ -101,7 +101,7 @@ | @@ -101,7 +101,7 @@ | ||
101 | converScriptRef.value?.setScriptOutputData(res?.output); | 101 | converScriptRef.value?.setScriptOutputData(res?.output); |
102 | } | 102 | } |
103 | } | 103 | } |
104 | - emits('success'); | 104 | + emits('success', res); |
105 | } finally { | 105 | } finally { |
106 | setModalProps({ confirmLoading: false }); | 106 | setModalProps({ confirmLoading: false }); |
107 | } | 107 | } |