Commit 6ae019862e88ad6c972b0c8b0a463bbb4ea5a5ee
Merge branch 'cherry-pick-e6853904' into 'main'
Merge branch 'feat-import-model-of-matter' into 'main_dev' See merge request yunteng/thingskit-front!600
Showing
6 changed files
with
126 additions
and
8 deletions
| @@ -55,3 +55,9 @@ export interface GetModelTslParams { | @@ -55,3 +55,9 @@ export interface GetModelTslParams { | ||
| 55 | functionType: FunctionType; | 55 | functionType: FunctionType; |
| 56 | deviceProfileId: string; | 56 | deviceProfileId: string; |
| 57 | } | 57 | } |
| 58 | + | ||
| 59 | +export interface ImportModelOfMatterType { | ||
| 60 | + data: Recordable; | ||
| 61 | + functionType: string; | ||
| 62 | + tkDeviceProfileId: string; | ||
| 63 | +} |
| 1 | import { BasicPageParams } from '../model/baseModel'; | 1 | import { BasicPageParams } from '../model/baseModel'; |
| 2 | -import { GetModelTslParams, ModelOfMatterParams } from './model/modelOfMatterModel'; | 2 | +import { |
| 3 | + GetModelTslParams, | ||
| 4 | + ImportModelOfMatterType, | ||
| 5 | + ModelOfMatterParams, | ||
| 6 | +} from './model/modelOfMatterModel'; | ||
| 3 | import { defHttp } from '/@/utils/http/axios'; | 7 | import { defHttp } from '/@/utils/http/axios'; |
| 4 | import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 8 | import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; |
| 5 | 9 | ||
| @@ -11,6 +15,8 @@ enum ModelOfMatter { | @@ -11,6 +15,8 @@ enum ModelOfMatter { | ||
| 11 | LIST = '/things_model/page', | 15 | LIST = '/things_model/page', |
| 12 | RELEASE = '/things_model', | 16 | RELEASE = '/things_model', |
| 13 | 17 | ||
| 18 | + IMPORT = '/things_model/import', | ||
| 19 | + | ||
| 14 | GET_MODEL_SERVICE = '/things_model/get_services', | 20 | GET_MODEL_SERVICE = '/things_model/get_services', |
| 15 | } | 21 | } |
| 16 | 22 | ||
| @@ -69,3 +75,10 @@ export const getModelServices = (params: { deviceProfileId: string }) => { | @@ -69,3 +75,10 @@ export const getModelServices = (params: { deviceProfileId: string }) => { | ||
| 69 | url: `${ModelOfMatter.GET_MODEL_SERVICE}/${deviceProfileId}`, | 75 | url: `${ModelOfMatter.GET_MODEL_SERVICE}/${deviceProfileId}`, |
| 70 | }); | 76 | }); |
| 71 | }; | 77 | }; |
| 78 | + | ||
| 79 | +export const importModelOfMatter = (data: ImportModelOfMatterType) => { | ||
| 80 | + return defHttp.post({ | ||
| 81 | + url: ModelOfMatter.IMPORT, | ||
| 82 | + data, | ||
| 83 | + }); | ||
| 84 | +}; |
| @@ -281,6 +281,7 @@ export const formSchemas = (hasStructForm: boolean): FormSchema[] => { | @@ -281,6 +281,7 @@ export const formSchemas = (hasStructForm: boolean): FormSchema[] => { | ||
| 281 | colProps: { | 281 | colProps: { |
| 282 | span: 24, | 282 | span: 24, |
| 283 | }, | 283 | }, |
| 284 | + ifShow: () => !hasStructForm, | ||
| 284 | defaultValue: 'r', | 285 | defaultValue: 'r', |
| 285 | componentProps: { | 286 | componentProps: { |
| 286 | placeholder: '请选择读写类型', | 287 | placeholder: '请选择读写类型', |
| @@ -33,9 +33,9 @@ | @@ -33,9 +33,9 @@ | ||
| 33 | </Button> | 33 | </Button> |
| 34 | </Authority> | 34 | </Authority> |
| 35 | <Button type="primary" @click="handleOpenTsl"> 物模型TSL </Button> | 35 | <Button type="primary" @click="handleOpenTsl"> 物模型TSL </Button> |
| 36 | - <Button v-if="false && isShowBtn" type="primary" @click="handleImportModel" | ||
| 37 | - >导入物模型</Button | ||
| 38 | - > | 36 | + <Upload v-if="isShowBtn" :show-upload-list="false" :customRequest="handleImportModel"> |
| 37 | + <Button type="primary"> 导入物模型 </Button> | ||
| 38 | + </Upload> | ||
| 39 | </div> | 39 | </div> |
| 40 | <div class="flex gap-2"> | 40 | <div class="flex gap-2"> |
| 41 | <Authority :value="ModelOfMatterPermission.RELEASE"> | 41 | <Authority :value="ModelOfMatterPermission.RELEASE"> |
| @@ -126,13 +126,19 @@ | @@ -126,13 +126,19 @@ | ||
| 126 | import { Authority } from '/@/components/Authority'; | 126 | import { Authority } from '/@/components/Authority'; |
| 127 | import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue'; | 127 | import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue'; |
| 128 | import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue'; | 128 | import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue'; |
| 129 | - import { Popconfirm, Button, Alert } from 'ant-design-vue'; | 129 | + import { Popconfirm, Button, Alert, Upload } from 'ant-design-vue'; |
| 130 | import { useMessage } from '/@/hooks/web/useMessage'; | 130 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 131 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 131 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
| 132 | - import { deleteModel, getModelList, releaseModel } from '/@/api/device/modelOfMatter'; | 132 | + import { |
| 133 | + deleteModel, | ||
| 134 | + getModelList, | ||
| 135 | + importModelOfMatter, | ||
| 136 | + releaseModel, | ||
| 137 | + } from '/@/api/device/modelOfMatter'; | ||
| 133 | import { OpenModelOfMatterModelParams, OpenModelMode } from './cpns/physical/types'; | 138 | import { OpenModelOfMatterModelParams, OpenModelMode } from './cpns/physical/types'; |
| 134 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | 139 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; |
| 135 | import { ref } from 'vue'; | 140 | import { ref } from 'vue'; |
| 141 | + import { isObject, isString } from '/@/utils/is'; | ||
| 136 | defineEmits(['register']); | 142 | defineEmits(['register']); |
| 137 | 143 | ||
| 138 | const props = defineProps<{ | 144 | const props = defineProps<{ |
| @@ -229,7 +235,37 @@ | @@ -229,7 +235,37 @@ | ||
| 229 | } | 235 | } |
| 230 | }; | 236 | }; |
| 231 | 237 | ||
| 232 | - const handleImportModel = async () => {}; | 238 | + const paseJSON = (string: string) => { |
| 239 | + let data = null; | ||
| 240 | + let flag = false; | ||
| 241 | + try { | ||
| 242 | + if (!isString(string)) return { flag: false, data }; | ||
| 243 | + data = JSON.parse(string); | ||
| 244 | + flag = true; | ||
| 245 | + if (!isObject(data)) flag = false; | ||
| 246 | + } catch (error) {} | ||
| 247 | + return { flag, data }; | ||
| 248 | + }; | ||
| 249 | + | ||
| 250 | + const handleImportModel = async (data: { file: File }) => { | ||
| 251 | + const fileReader = new FileReader(); | ||
| 252 | + | ||
| 253 | + fileReader.onload = async () => { | ||
| 254 | + const { flag, data } = paseJSON(fileReader.result as string); | ||
| 255 | + if (!flag) return; | ||
| 256 | + const result = await importModelOfMatter({ | ||
| 257 | + tkDeviceProfileId: props.record.id, | ||
| 258 | + data: data!, | ||
| 259 | + functionType: 'all', | ||
| 260 | + }); | ||
| 261 | + | ||
| 262 | + result ? createMessage.success('导入成功~') : createMessage.error('导入失败~'); | ||
| 263 | + | ||
| 264 | + result && reload(); | ||
| 265 | + }; | ||
| 266 | + | ||
| 267 | + fileReader.readAsText(data.file, 'utf-8'); | ||
| 268 | + }; | ||
| 233 | 269 | ||
| 234 | defineExpose({}); | 270 | defineExpose({}); |
| 235 | </script> | 271 | </script> |
| @@ -85,7 +85,13 @@ | @@ -85,7 +85,13 @@ | ||
| 85 | try { | 85 | try { |
| 86 | loading.value = true; | 86 | loading.value = true; |
| 87 | const record = await getModelTsl({ deviceProfileId: props.record.id, functionType }); | 87 | const record = await getModelTsl({ deviceProfileId: props.record.id, functionType }); |
| 88 | - jsonValue.value = JSON.stringify(record, null, 2); | 88 | + jsonValue.value = JSON.stringify( |
| 89 | + { | ||
| 90 | + [functionType]: record, | ||
| 91 | + }, | ||
| 92 | + null, | ||
| 93 | + 2 | ||
| 94 | + ); | ||
| 89 | } catch (error) { | 95 | } catch (error) { |
| 90 | } finally { | 96 | } finally { |
| 91 | loading.value = false; | 97 | loading.value = false; |
| 1 | +import { ref } from 'vue'; | ||
| 2 | +import { DataSource } from '../../palette/types'; | ||
| 3 | +import { sendCommandOneway } from '/@/api/dataBoard'; | ||
| 4 | +import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 5 | +import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | ||
| 6 | + | ||
| 7 | +const { createMessage } = useMessage(); | ||
| 8 | +export function useSendCommand() { | ||
| 9 | + const loading = ref(false); | ||
| 10 | + | ||
| 11 | + const error = () => { | ||
| 12 | + createMessage.error('下发指令失败'); | ||
| 13 | + return false; | ||
| 14 | + }; | ||
| 15 | + const sendCommand = async (record: DataSource, value: any) => { | ||
| 16 | + if (!record) return error(); | ||
| 17 | + const { customCommand, attribute } = record; | ||
| 18 | + | ||
| 19 | + const { deviceId } = record; | ||
| 20 | + if (!deviceId) return error(); | ||
| 21 | + loading.value = true; | ||
| 22 | + try { | ||
| 23 | + let params: string | Recordable = { | ||
| 24 | + [attribute!]: Number(value), | ||
| 25 | + }; | ||
| 26 | + | ||
| 27 | + // 如果是TCP设备从物模型中获取下发命令(TCP网关子设备无物模型服务与事件) | ||
| 28 | + if (customCommand?.transportType === TransportTypeEnum.TCP) { | ||
| 29 | + params = customCommand.command!; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + // 控制按钮下发命令为0 或 1 | ||
| 33 | + await sendCommandOneway({ | ||
| 34 | + deviceId, | ||
| 35 | + value: { | ||
| 36 | + params: params, | ||
| 37 | + persistent: true, | ||
| 38 | + additionalInfo: { | ||
| 39 | + cmdType: 'API', | ||
| 40 | + }, | ||
| 41 | + method: 'methodThingskit', | ||
| 42 | + }, | ||
| 43 | + }); | ||
| 44 | + createMessage.success('命令下发成功'); | ||
| 45 | + return true; | ||
| 46 | + } catch (msg) { | ||
| 47 | + return error(); | ||
| 48 | + } finally { | ||
| 49 | + loading.value = false; | ||
| 50 | + } | ||
| 51 | + }; | ||
| 52 | + return { | ||
| 53 | + sendCommand, | ||
| 54 | + loading, | ||
| 55 | + }; | ||
| 56 | +} |