Commit 70490d49f4e36d2bea1ff85dc9b5f407401c6555

Authored by xp.Huang
2 parents 765a7235 5fafe334

Merge branch 'ft' into 'main_dev'

fix: 修改消息配置表格里的查看配置权限标识和详情一样

See merge request yunteng/thingskit-front!928
@@ -8,24 +8,6 @@ @@ -8,24 +8,6 @@
8 @ok="handleSubmit" 8 @ok="handleSubmit"
9 > 9 >
10 <BasicForm @register="registerForm"> 10 <BasicForm @register="registerForm">
11 - <template #iconSelect>  
12 - <Upload  
13 - name="avatar"  
14 - accept=".png,.jpg,.jpeg,.gif"  
15 - list-type="picture-card"  
16 - class="avatar-uploader"  
17 - :show-upload-list="false"  
18 - :customRequest="customUpload"  
19 - :before-upload="beforeUpload"  
20 - >  
21 - <img v-if="tenantLogo" :src="tenantLogo" alt="avatar" />  
22 - <div v-else>  
23 - <LoadingOutlined v-if="loading" />  
24 - <plus-outlined v-else />  
25 - <div class="ant-upload-text">上传</div>  
26 - </div>  
27 - </Upload>  
28 - </template>  
29 <template #videoPlatformIdSlot="{ model, field }"> 11 <template #videoPlatformIdSlot="{ model, field }">
30 <a-select 12 <a-select
31 placeholder="请选择流媒体配置" 13 placeholder="请选择流媒体配置"
@@ -52,23 +34,20 @@ @@ -52,23 +34,20 @@
52 import { formSchema } from './config.data'; 34 import { formSchema } from './config.data';
53 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 35 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
54 import { createOrEditCameraManage } from '/@/api/camera/cameraManager'; 36 import { createOrEditCameraManage } from '/@/api/camera/cameraManager';
55 - import { message, Upload } from 'ant-design-vue';  
56 import { useMessage } from '/@/hooks/web/useMessage'; 37 import { useMessage } from '/@/hooks/web/useMessage';
57 - import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue';  
58 - import { upload } from '/@/api/oss/ossFileUploader';  
59 - import { FileItem } from '/@/components/Upload/src/typing'; 38 + import { PlusOutlined } from '@ant-design/icons-vue';
60 import { getStreamingMediaList } from '/@/api/camera/cameraManager'; 39 import { getStreamingMediaList } from '/@/api/camera/cameraManager';
61 import SteramingDrawer from '../streaming/SteramingDrawer.vue'; 40 import SteramingDrawer from '../streaming/SteramingDrawer.vue';
62 import { useDrawer } from '/@/components/Drawer'; 41 import { useDrawer } from '/@/components/Drawer';
  42 + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  43 + import { buildUUID } from '/@/utils/uuid';
63 44
64 export default defineComponent({ 45 export default defineComponent({
65 name: 'ContactDrawer', 46 name: 'ContactDrawer',
66 components: { 47 components: {
67 BasicDrawer, 48 BasicDrawer,
68 BasicForm, 49 BasicForm,
69 - Upload,  
70 PlusOutlined, 50 PlusOutlined,
71 - LoadingOutlined,  
72 SteramingDrawer, 51 SteramingDrawer,
73 VNodes: (_, { attrs }) => { 52 VNodes: (_, { attrs }) => {
74 return attrs.vnodes; 53 return attrs.vnodes;
@@ -118,42 +97,19 @@ @@ -118,42 +97,19 @@
118 if (unref(isUpdate)) { 97 if (unref(isUpdate)) {
119 await nextTick(); 98 await nextTick();
120 editId.value = data.record.id; 99 editId.value = data.record.id;
121 - tenantLogo.value = data.record?.avatar;  
122 - await setFieldsValue(data.record); 100 + if (data.record.avatar) {
  101 + setFieldsValue({
  102 + avatar: [{ uid: buildUUID(), name: 'name', url: data.record.avatar } as FileItem],
  103 + });
  104 + }
  105 + const { avatar, ...params } = data.record;
  106 + console.log(avatar);
  107 + await setFieldsValue({ ...params });
123 } else { 108 } else {
124 - tenantLogo.value = '';  
125 editId.value = ''; 109 editId.value = '';
126 } 110 }
127 }); 111 });
128 112
129 - const tenantLogo = ref('');  
130 -  
131 - async function customUpload({ file }) {  
132 - if (beforeUpload(file)) {  
133 - tenantLogo.value = '';  
134 - loading.value = true;  
135 - const formData = new FormData();  
136 - formData.append('file', file);  
137 - const response = await upload(formData);  
138 - if (response.fileStaticUri) {  
139 - tenantLogo.value = response.fileStaticUri;  
140 - loading.value = false;  
141 - }  
142 - }  
143 - }  
144 -  
145 - const beforeUpload = (file: FileItem) => {  
146 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
147 - if (!isJpgOrPng) {  
148 - message.error('只能上传图片文件!');  
149 - }  
150 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
151 - if (!isLt2M) {  
152 - message.error('图片大小不能超过5MB!');  
153 - }  
154 - return isJpgOrPng && isLt2M;  
155 - };  
156 -  
157 const getTitle = computed(() => (!unref(isUpdate) ? '新增视频配置' : '编辑视频配置')); 113 const getTitle = computed(() => (!unref(isUpdate) ? '新增视频配置' : '编辑视频配置'));
158 114
159 async function handleSubmit() { 115 async function handleSubmit() {
@@ -162,8 +118,9 @@ @@ -162,8 +118,9 @@
162 const { createMessage } = useMessage(); 118 const { createMessage } = useMessage();
163 const values = await validate(); 119 const values = await validate();
164 if (!values) return; 120 if (!values) return;
165 - if (tenantLogo.value !== '') {  
166 - values.avatar = tenantLogo.value; 121 + if (Reflect.has(values, 'avatar')) {
  122 + const file = (values.avatar || []).at(0) || {};
  123 + values.avatar = file.url || null;
167 } 124 }
168 if (editId.value !== '') { 125 if (editId.value !== '') {
169 values.id = editId.value; 126 values.id = editId.value;
@@ -188,9 +145,6 @@ @@ -188,9 +145,6 @@
188 registerDrawer, 145 registerDrawer,
189 registerForm, 146 registerForm,
190 handleSubmit, 147 handleSubmit,
191 - customUpload,  
192 - beforeUpload,  
193 - tenantLogo,  
194 loading, 148 loading,
195 streamConfigOptions, 149 streamConfigOptions,
196 registerSteramingDrawer, 150 registerSteramingDrawer,
@@ -5,6 +5,9 @@ import { CameraVideoUrl, CameraMaxLength } from '/@/utils/rules'; @@ -5,6 +5,9 @@ import { CameraVideoUrl, CameraMaxLength } from '/@/utils/rules';
5 import { h } from 'vue'; 5 import { h } from 'vue';
6 import SnHelpMessage from './SnHelpMessage.vue'; 6 import SnHelpMessage from './SnHelpMessage.vue';
7 import { OrgTreeSelect } from '../../common/OrgTreeSelect'; 7 import { OrgTreeSelect } from '../../common/OrgTreeSelect';
  8 +import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  9 +import { createImgPreview } from '/@/components/Preview';
  10 +import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter';
8 11
9 useComponentRegister('OrgTreeSelect', OrgTreeSelect); 12 useComponentRegister('OrgTreeSelect', OrgTreeSelect);
10 13
@@ -102,8 +105,33 @@ export const formSchema: QFormSchema[] = [ @@ -102,8 +105,33 @@ export const formSchema: QFormSchema[] = [
102 { 105 {
103 field: 'avatar', 106 field: 'avatar',
104 label: '视频封面', 107 label: '视频封面',
105 - slot: 'iconSelect',  
106 - component: 'Input', 108 + component: 'ApiUpload',
  109 + changeEvent: 'update:fileList',
  110 + valueField: 'fileList',
  111 + componentProps: () => {
  112 + return {
  113 + listType: 'picture-card',
  114 + maxFileLimit: 1,
  115 + accept: '.png,.jpg,.jpeg,.gif',
  116 + api: async (file: File) => {
  117 + try {
  118 + const formData = new FormData();
  119 + formData.set('file', file);
  120 + const { fileStaticUri, fileName } = await uploadThumbnail(formData);
  121 + return {
  122 + uid: fileStaticUri,
  123 + name: fileName,
  124 + url: fileStaticUri,
  125 + } as FileItem;
  126 + } catch (error) {
  127 + return {};
  128 + }
  129 + },
  130 + onPreview: (fileList: FileItem) => {
  131 + createImgPreview({ imageList: [fileList.url!] });
  132 + },
  133 + };
  134 + },
107 }, 135 },
108 { 136 {
109 field: 'name', 137 field: 'name',
@@ -12,6 +12,9 @@ import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/compo @@ -12,6 +12,9 @@ import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/compo
12 import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum'; 12 import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum';
13 import { TaskTypeEnum } from '/@/views/task/center/config'; 13 import { TaskTypeEnum } from '/@/views/task/center/config';
14 import { AddressTypeEnum } from '/@/views/task/center/components/PollCommandInput'; 14 import { AddressTypeEnum } from '/@/views/task/center/components/PollCommandInput';
  15 +import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  16 +import { createImgPreview } from '/@/components/Preview';
  17 +import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter';
15 18
16 useComponentRegister('JSONEditor', JSONEditor); 19 useComponentRegister('JSONEditor', JSONEditor);
17 useComponentRegister('ObjectModelValidateForm', ObjectModelValidateForm); 20 useComponentRegister('ObjectModelValidateForm', ObjectModelValidateForm);
@@ -29,8 +32,33 @@ export const step1Schemas: FormSchema[] = [ @@ -29,8 +32,33 @@ export const step1Schemas: FormSchema[] = [
29 { 32 {
30 field: 'icon', 33 field: 'icon',
31 label: '设备图片', 34 label: '设备图片',
32 - slot: 'iconSelect',  
33 - component: 'Input', 35 + component: 'ApiUpload',
  36 + changeEvent: 'update:fileList',
  37 + valueField: 'fileList',
  38 + componentProps: () => {
  39 + return {
  40 + listType: 'picture-card',
  41 + maxFileLimit: 1,
  42 + accept: '.png,.jpg,.jpeg,.gif',
  43 + api: async (file: File) => {
  44 + try {
  45 + const formData = new FormData();
  46 + formData.set('file', file);
  47 + const { fileStaticUri, fileName } = await uploadThumbnail(formData);
  48 + return {
  49 + uid: fileStaticUri,
  50 + name: fileName,
  51 + url: fileStaticUri,
  52 + } as FileItem;
  53 + } catch (error) {
  54 + return {};
  55 + }
  56 + },
  57 + onPreview: (fileList: FileItem) => {
  58 + createImgPreview({ imageList: [fileList.url!] });
  59 + },
  60 + };
  61 + },
34 }, 62 },
35 { 63 {
36 field: 'alias', 64 field: 'alias',
@@ -32,14 +32,14 @@ export const columns: BasicColumn[] = [ @@ -32,14 +32,14 @@ export const columns: BasicColumn[] = [
32 h( 32 h(
33 'div', 33 'div',
34 { 34 {
35 - class: 'cursor-pointer', 35 + class: 'cursor-pointer truncate',
36 }, 36 },
37 `${record.alias}` 37 `${record.alias}`
38 ), 38 ),
39 h( 39 h(
40 'div', 40 'div',
41 { 41 {
42 - class: 'cursor-pointer text-blue-500', 42 + class: 'cursor-pointer text-blue-500 truncate',
43 onClick: () => { 43 onClick: () => {
44 handeleCopy(`${record.name}`); 44 handeleCopy(`${record.name}`);
45 }, 45 },
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 @register="register" 5 @register="register"
6 destroyOnClose 6 destroyOnClose
7 @close="closeDrawer" 7 @close="closeDrawer"
8 - :title="deviceDetail.alias || deviceDetail.name" 8 + :title="drawerTitle"
9 width="80%" 9 width="80%"
10 > 10 >
11 <Tabs v-model:activeKey="activeKey" :size="size"> 11 <Tabs v-model:activeKey="activeKey" :size="size">
@@ -58,7 +58,7 @@ @@ -58,7 +58,7 @@
58 </BasicDrawer> 58 </BasicDrawer>
59 </template> 59 </template>
60 <script lang="ts"> 60 <script lang="ts">
61 - import { defineComponent, ref } from 'vue'; 61 + import { defineComponent, ref, computed } from 'vue';
62 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 62 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
63 63
64 import { Tabs } from 'ant-design-vue'; 64 import { Tabs } from 'ant-design-vue';
@@ -122,6 +122,13 @@ @@ -122,6 +122,13 @@
122 emit('openGatewayDeviceDetail', { id: data.gatewayId }); 122 emit('openGatewayDeviceDetail', { id: data.gatewayId });
123 }; 123 };
124 124
  125 + const drawerTitle = computed(() => {
  126 + return (
  127 + deviceDetail.value?.alias?.slice(0, 40) + '...' ||
  128 + deviceDetail.value?.name?.slice(0, 40) + '...'
  129 + );
  130 + });
  131 +
125 return { 132 return {
126 size, 133 size,
127 activeKey, 134 activeKey,
@@ -132,6 +139,7 @@ @@ -132,6 +139,7 @@
132 tbDeviceId, 139 tbDeviceId,
133 handleOpenTbDeviceDetail, 140 handleOpenTbDeviceDetail,
134 handleOpenGatewayDevice, 141 handleOpenGatewayDevice,
  142 + drawerTitle,
135 }; 143 };
136 }, 144 },
137 }); 145 });
@@ -157,7 +157,7 @@ @@ -157,7 +157,7 @@
157 sn: stepRecord.name, 157 sn: stepRecord.name,
158 customerId: currentDeviceData.customerId, 158 customerId: currentDeviceData.customerId,
159 deviceInfo: { 159 deviceInfo: {
160 - avatar: DeviceStep1Ref.value?.devicePic, 160 + avatar: stepRecord?.icon,
161 ...DeviceStep1Ref.value?.devicePositionState, 161 ...DeviceStep1Ref.value?.devicePositionState,
162 }, 162 },
163 }; 163 };
@@ -169,7 +169,7 @@ @@ -169,7 +169,7 @@
169 ...stepRecord, 169 ...stepRecord,
170 sn: stepRecord.name, 170 sn: stepRecord.name,
171 deviceInfo: { 171 deviceInfo: {
172 - avatar: DeviceStep1Ref.value?.devicePic, 172 + avatar: stepRecord?.icon,
173 ...DeviceStep1Ref.value?.devicePositionState, 173 ...DeviceStep1Ref.value?.devicePositionState,
174 }, 174 },
175 deviceToken: 175 deviceToken:
@@ -22,24 +22,6 @@ @@ -22,24 +22,6 @@
22 </div> 22 </div>
23 </div> 23 </div>
24 </template> 24 </template>
25 - <template #iconSelect>  
26 - <Upload  
27 - name="avatar"  
28 - accept=".png,.jpg,.jpeg,.gif"  
29 - :show-upload-list="false"  
30 - list-type="picture-card"  
31 - class="avatar-uploader"  
32 - :customRequest="customUpload"  
33 - :before-upload="beforeUpload"  
34 - >  
35 - <img v-if="devicePic" :src="devicePic" alt="avatar" />  
36 - <div v-else>  
37 - <LoadingOutlined v-if="loading" />  
38 - <PlusOutlined v-else />  
39 - <div class="ant-upload-text">图片上传</div>  
40 - </div>  
41 - </Upload>  
42 - </template>  
43 <template #snCode="{ model, field }"> 25 <template #snCode="{ model, field }">
44 <div class="flex"> 26 <div class="flex">
45 <Input v-model:value="model[field]" placeholder="请输入设备名称" /> 27 <Input v-model:value="model[field]" placeholder="请输入设备名称" />
@@ -115,10 +97,9 @@ @@ -115,10 +97,9 @@
115 import { BasicForm, useForm } from '/@/components/Form'; 97 import { BasicForm, useForm } from '/@/components/Form';
116 import { step1Schemas } from '../../config/data'; 98 import { step1Schemas } from '../../config/data';
117 import { useScript } from '/@/hooks/web/useScript'; 99 import { useScript } from '/@/hooks/web/useScript';
118 - import { Input, Upload, message, Modal, Form, Row, Col, AutoComplete } from 'ant-design-vue';  
119 - import { EnvironmentTwoTone, PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue'; 100 + import { Input, message, Modal, Form, Row, Col, AutoComplete } from 'ant-design-vue';
  101 + import { EnvironmentTwoTone } from '@ant-design/icons-vue';
120 import { upload } from '/@/api/oss/ossFileUploader'; 102 import { upload } from '/@/api/oss/ossFileUploader';
121 - import { FileItem } from '/@/components/Upload/src/typing';  
122 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; 103 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
123 import { generateSNCode } from '/@/api/device/deviceManager'; 104 import { generateSNCode } from '/@/api/device/deviceManager';
124 import icon from '/@/assets/images/wz.png'; 105 import icon from '/@/assets/images/wz.png';
@@ -130,21 +111,20 @@ @@ -130,21 +111,20 @@
130 import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue'; 111 import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue';
131 import { TaskTypeEnum } from '/@/views/task/center/config'; 112 import { TaskTypeEnum } from '/@/views/task/center/config';
132 import { toRaw } from 'vue'; 113 import { toRaw } from 'vue';
  114 + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  115 + import { buildUUID } from '/@/utils/uuid';
133 116
134 export default defineComponent({ 117 export default defineComponent({
135 components: { 118 components: {
136 BasicForm, 119 BasicForm,
137 Input, 120 Input,
138 AutoComplete, 121 AutoComplete,
139 - Upload,  
140 EnvironmentTwoTone, 122 EnvironmentTwoTone,
141 - PlusOutlined,  
142 Modal, 123 Modal,
143 Form, 124 Form,
144 FormItem: Form.Item, 125 FormItem: Form.Item,
145 Row, 126 Row,
146 Col, 127 Col,
147 - LoadingOutlined,  
148 DeptDrawer, 128 DeptDrawer,
149 }, 129 },
150 props: { 130 props: {
@@ -202,8 +182,11 @@ @@ -202,8 +182,11 @@
202 async function nextStep() { 182 async function nextStep() {
203 try { 183 try {
204 let values = await validate(); 184 let values = await validate();
205 - values = { devicePic: devicePic.value, ...positionState, ...values };  
206 - delete values.icon; 185 + if (Reflect.has(values, 'icon')) {
  186 + const file = (unref(values.icon) || []).at(0) || {};
  187 + values.icon = file.url || null;
  188 + }
  189 + values = { ...positionState, ...values };
207 delete values.deviceAddress; 190 delete values.deviceAddress;
208 emit('next', values); 191 emit('next', values);
209 // 获取输入的数据 192 // 获取输入的数据
@@ -405,6 +388,11 @@ @@ -405,6 +388,11 @@
405 positionState.address = deviceInfo.address; 388 positionState.address = deviceInfo.address;
406 devicePositionState.value = { ...toRaw(positionState) }; 389 devicePositionState.value = { ...toRaw(positionState) };
407 devicePic.value = deviceInfo.avatar; 390 devicePic.value = deviceInfo.avatar;
  391 + if (deviceInfo.avatar) {
  392 + setFieldsValue({
  393 + icon: [{ uid: buildUUID(), name: 'name', url: deviceInfo.avatar } as FileItem],
  394 + });
  395 + }
408 setFieldsValue({ 396 setFieldsValue({
409 ...data, 397 ...data,
410 code: data?.code, 398 code: data?.code,
@@ -414,6 +402,10 @@ @@ -414,6 +402,10 @@
414 // 父组件调用获取字段值的方法 402 // 父组件调用获取字段值的方法
415 function parentGetFieldsValue() { 403 function parentGetFieldsValue() {
416 const value = getFieldsValue(); 404 const value = getFieldsValue();
  405 + if (Reflect.has(value, 'icon')) {
  406 + const file = (value.icon || []).at(0) || {};
  407 + value.icon = file.url || null;
  408 + }
417 return { 409 return {
418 ...value, 410 ...value,
419 ...(value?.code || value?.addressCode 411 ...(value?.code || value?.addressCode
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 </div> 47 </div>
48 </BasicModal> 48 </BasicModal>
49 </div> 49 </div>
50 - <Description @register="register" class="mt-4" :data="deviceDetail" /> 50 + <Description @register="register" class="mt-4" :data="deviceDetail" :contentStyle="CS" />
51 </div> 51 </div>
52 <div class="mt-4" v-if="!isCustomer"> 52 <div class="mt-4" v-if="!isCustomer">
53 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button> 53 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button>
@@ -116,6 +116,15 @@ @@ -116,6 +116,15 @@
116 column: 2, 116 column: 2,
117 }); 117 });
118 118
  119 + const CS = {
  120 + 'max-width': '600px',
  121 + 'word-break': 'break-all',
  122 + overflow: 'hidden',
  123 + display: '-webkit-box',
  124 + '-webkit-line-clamp': 2,
  125 + '-webkit-box-orient': 'vertical',
  126 + };
  127 +
119 // 地图 128 // 地图
120 const mapWrapRef = ref<HTMLDivElement>(); 129 const mapWrapRef = ref<HTMLDivElement>();
121 130
@@ -217,6 +226,7 @@ @@ -217,6 +226,7 @@
217 remoteConnectiondGateway, 226 remoteConnectiondGateway,
218 locationImage, 227 locationImage,
219 isCustomer, 228 isCustomer,
  229 + CS,
220 }; 230 };
221 }, 231 },
222 }); 232 });
@@ -12,6 +12,9 @@ import { EventType, EventTypeColor, EventTypeName } from '../list/cpns/tabs/Even @@ -12,6 +12,9 @@ import { EventType, EventTypeColor, EventTypeName } from '../list/cpns/tabs/Even
12 12
13 import { useClipboard } from '@vueuse/core'; 13 import { useClipboard } from '@vueuse/core';
14 import { useMessage } from '/@/hooks/web/useMessage'; 14 import { useMessage } from '/@/hooks/web/useMessage';
  15 +import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  16 +import { createImgPreview } from '/@/components/Preview';
  17 +import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter';
15 18
16 export enum Mode { 19 export enum Mode {
17 CARD = 'card', 20 CARD = 'card',
@@ -162,8 +165,33 @@ export const step1Schemas: FormSchema[] = [ @@ -162,8 +165,33 @@ export const step1Schemas: FormSchema[] = [
162 { 165 {
163 field: 'image', 166 field: 'image',
164 label: '上传图片', 167 label: '上传图片',
165 - component: 'Input',  
166 - slot: 'imageSelect', 168 + component: 'ApiUpload',
  169 + changeEvent: 'update:fileList',
  170 + valueField: 'fileList',
  171 + componentProps: () => {
  172 + return {
  173 + listType: 'picture-card',
  174 + maxFileLimit: 1,
  175 + accept: '.png,.jpg,.jpeg,.gif',
  176 + api: async (file: File) => {
  177 + try {
  178 + const formData = new FormData();
  179 + formData.set('file', file);
  180 + const { fileStaticUri, fileName } = await uploadThumbnail(formData);
  181 + return {
  182 + uid: fileStaticUri,
  183 + name: fileName,
  184 + url: fileStaticUri,
  185 + } as FileItem;
  186 + } catch (error) {
  187 + return {};
  188 + }
  189 + },
  190 + onPreview: (fileList: FileItem) => {
  191 + createImgPreview({ imageList: [fileList.url!] });
  192 + },
  193 + };
  194 + },
167 }, 195 },
168 { 196 {
169 field: 'deviceType', 197 field: 'deviceType',
1 <template> 1 <template>
2 <div class="step1"> 2 <div class="step1">
3 - <BasicForm @register="register">  
4 - <template #imageSelect>  
5 - <Upload  
6 - style="width: 20vw"  
7 - name="avatar"  
8 - accept=".png,.jpg,.jpeg,.gif"  
9 - list-type="picture-card"  
10 - class="avatar-uploader"  
11 - :show-upload-list="false"  
12 - :customRequest="customUploadqrcodePic"  
13 - :before-upload="beforeUploadqrcodePic"  
14 - >  
15 - <img  
16 - v-if="deviceConfigPic"  
17 - :src="deviceConfigPic"  
18 - alt=""  
19 - style="width: 6.25rem; height: 6.25rem"  
20 - />  
21 - <div v-else>  
22 - <LoadingOutlined v-if="loading" />  
23 - <PlusOutlined v-else />  
24 - <div class="ant-upload-text">图片上传</div>  
25 - </div>  
26 - </Upload>  
27 - </template>  
28 - </BasicForm> 3 + <BasicForm @register="register" />
29 </div> 4 </div>
30 </template> 5 </template>
31 <script lang="ts" setup> 6 <script lang="ts" setup>
32 - import { ref, nextTick } from 'vue'; 7 + import { nextTick } from 'vue';
33 import { BasicForm, useForm } from '/@/components/Form'; 8 import { BasicForm, useForm } from '/@/components/Form';
34 import { step1Schemas } from '../device.profile.data'; 9 import { step1Schemas } from '../device.profile.data';
35 - import { uploadApi } from '/@/api/personal/index';  
36 - import { Upload } from 'ant-design-vue';  
37 - import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue';  
38 - import { useMessage } from '/@/hooks/web/useMessage';  
39 - import type { FileItem } from '/@/components/Upload/src/typing'; 10 + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  11 + import { buildUUID } from '/@/utils/uuid';
40 12
41 const emits = defineEmits(['next', 'emitDeviceType']); 13 const emits = defineEmits(['next', 'emitDeviceType']);
42 - const loading = ref(false);  
43 - const { createMessage } = useMessage();  
44 - const deviceConfigPic = ref('');  
45 const props = defineProps({ 14 const props = defineProps({
46 ifShowBtn: { type: Boolean, default: true }, 15 ifShowBtn: { type: Boolean, default: true },
47 }); 16 });
@@ -66,32 +35,6 @@ @@ -66,32 +35,6 @@
66 disabled: nameStatus, 35 disabled: nameStatus,
67 }, 36 },
68 }); 37 });
69 - const customUploadqrcodePic = async ({ file }) => {  
70 - if (beforeUploadqrcodePic(file)) {  
71 - deviceConfigPic.value = '';  
72 - loading.value = true;  
73 - const formData = new FormData();  
74 - formData.append('file', file);  
75 - const response = await uploadApi(formData);  
76 - if (response.fileStaticUri) {  
77 - deviceConfigPic.value = response.fileStaticUri;  
78 - loading.value = false;  
79 - }  
80 - }  
81 - };  
82 - const beforeUploadqrcodePic = (file: FileItem) => {  
83 - const isJpgOrPng =  
84 - file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg';  
85 - if (!isJpgOrPng) {  
86 - createMessage.error('只能上传图片文件!');  
87 - }  
88 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
89 - if (!isLt2M) {  
90 - createMessage.error('图片大小不能超过5MB!');  
91 - }  
92 - return isJpgOrPng && isLt2M;  
93 - };  
94 -  
95 const setFieldsdefaultRuleChainId = async (id) => { 38 const setFieldsdefaultRuleChainId = async (id) => {
96 await nextTick(); 39 await nextTick();
97 setFieldsValue({ defaultRuleChainId: id }); 40 setFieldsValue({ defaultRuleChainId: id });
@@ -105,20 +48,28 @@ @@ -105,20 +48,28 @@
105 } 48 }
106 //回显数据 49 //回显数据
107 const setFormData = (v) => { 50 const setFormData = (v) => {
108 - setFieldsValue(v);  
109 - deviceConfigPic.value = v.image; 51 + if (v.image) {
  52 + setFieldsValue({
  53 + image: [{ uid: buildUUID(), name: 'name', url: v.image } as FileItem],
  54 + });
  55 + }
  56 + const { image, ...params } = v;
  57 + console.log(image);
  58 + setFieldsValue({ ...params });
110 }; 59 };
111 //获取数据 60 //获取数据
112 async function getFormData() { 61 async function getFormData() {
113 const values = await validate(); 62 const values = await validate();
114 if (!values) return; 63 if (!values) return;
115 - Reflect.set(values, 'image', deviceConfigPic.value); 64 + if (Reflect.has(values, 'image')) {
  65 + const file = (values.image || []).at(0) || {};
  66 + values.image = file.url || null;
  67 + }
116 return values; 68 return values;
117 } 69 }
118 //清空数据 70 //清空数据
119 const resetFormData = () => { 71 const resetFormData = () => {
120 resetFields(); 72 resetFields();
121 - deviceConfigPic.value = '';  
122 }; 73 };
123 74
124 const editOrAddDeviceTypeStatus = (status: boolean) => { 75 const editOrAddDeviceTypeStatus = (status: boolean) => {
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 </Authority> 17 </Authority>
18 </template> 18 </template>
19 <template #config="{ record }"> 19 <template #config="{ record }">
20 - <Authority value="api:yt:message:get:config"> 20 + <Authority value="api:yt:template:get">
21 <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button> 21 <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button>
22 </Authority> 22 </Authority>
23 </template> 23 </template>