绑定设备端物模型

This commit is contained in:
ChenYi 2025-12-23 09:00:53 +08:00
parent e860a539fa
commit 33dd206da0
4 changed files with 186 additions and 35 deletions

View File

@ -467,10 +467,14 @@ export const BatchCreateDeviceAggregationInputSchema = {
export const BindingDeviceThingModelInputSchema = { export const BindingDeviceThingModelInputSchema = {
type: 'object', type: 'object',
properties: { properties: {
devieDataId: { devieDataIdList: {
type: 'string', type: 'array',
description: '设备数据Id', items: {
format: 'uuid' type: 'string',
format: 'uuid'
},
description: '设备数据Id集合',
nullable: true
}, },
isNeedConfigDevicMdoel: { isNeedConfigDevicMdoel: {
type: 'boolean', type: 'boolean',

View File

@ -177,9 +177,9 @@ export type BatchCreateDeviceAggregationInput = {
*/ */
export type BindingDeviceThingModelInput = { export type BindingDeviceThingModelInput = {
/** /**
* Id * Id集合
*/ */
devieDataId?: string; devieDataIdList?: Array<(string)> | null;
/** /**
* false * false
*/ */

View File

@ -165,7 +165,7 @@ const loadingTip = ref('缓存刷新中...');
const commandRow: Record<string, any> = ref({}); const commandRow: Record<string, any> = ref({});
// //
const bindRow: Record<string, any> = ref({}); const bindRows: Array<Record<string, any>> = ref([]);
// - // -
interface CommandProperty { interface CommandProperty {
@ -274,9 +274,18 @@ const [BindModal, bindModalApi] = useVbenModal({
draggable: true, draggable: true,
onConfirm: submitBindDeviceThingModel, onConfirm: submitBindDeviceThingModel,
onBeforeClose: () => { onBeforeClose: () => {
bindRow.value = {}; bindRows.value = [];
return true; return true;
}, },
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
console.log('绑定弹窗打开,选中的设备:', bindRows.value);
await nextTick();
//
const formValues = await bindFormApi.getValues();
console.log('弹窗打开时的表单值:', formValues);
}
},
}); });
const [AddForm, addFormApi] = useVbenForm({ const [AddForm, addFormApi] = useVbenForm({
@ -343,6 +352,36 @@ const [BindForm, bindFormApi] = useVbenForm({
showCollapseButton: false, showCollapseButton: false,
showDefaultActions: false, showDefaultActions: false,
wrapperClass: 'grid-cols-1', wrapperClass: 'grid-cols-1',
handleValuesChange: async (values, changedFields) => {
//
if (changedFields.includes('isNeedConfigDevicMdoel') && values.isNeedConfigDevicMdoel) {
console.log('开关打开,准备触发设备物模型下拉框重新加载');
await nextTick();
setTimeout(async () => {
try {
const productId = values._ioTPlatformProductId || values.ioTPlatformProductId;
console.log('手动触发下拉框重新加载产品ID:', productId);
if (productId) {
const fieldRef = bindFormApi.getFieldComponentRef('deviceThingModelDataId');
if (fieldRef && typeof fieldRef.updateParam === 'function') {
fieldRef.updateParam({
query: {
input: {
id: String(productId),
},
},
});
console.log('已手动触发下拉框重新加载');
} else {
console.warn('无法获取设备物模型下拉框的引用');
}
}
} catch (error) {
console.error('手动触发下拉框重新加载失败:', error);
}
}, 100);
}
},
}); });
const [BatchAddForm, batchAddFormApi] = useVbenForm({ const [BatchAddForm, batchAddFormApi] = useVbenForm({
@ -585,17 +624,58 @@ const openCommandModal = (row: Record<string, any>) => {
commandModalApi.open(); commandModalApi.open();
}; };
// //
const openBindModal = async (row: Record<string, any>) => { const openBindModal = async (rowOrRows?: Record<string, any> | Array<Record<string, any>>) => {
bindRow.value = row; //
let selectedRows: Array<Record<string, any>> = [];
if (rowOrRows) {
// 使
if (Array.isArray(rowOrRows)) {
selectedRows = rowOrRows;
} else {
//
selectedRows = [rowOrRows];
}
} else {
//
try {
const checkboxRecords = gridApi?.getCheckboxRecords?.() || [];
selectedRows = checkboxRecords;
} catch (error) {
console.warn('无法获取表格选中的设备:', error);
}
}
if (selectedRows.length === 0) {
Message.warning('请先选择要绑定的设备');
return;
}
console.log('打开绑定弹窗,选中的设备:', selectedRows);
bindRows.value = selectedRows;
// ID
const firstDevice = selectedRows[0];
const productId = firstDevice.ioTPlatformProductId;
console.log('设置表单值产品ID:', productId, '类型:', typeof productId);
if (!productId) {
console.warn('警告:设备行数据中没有 ioTPlatformProductId 字段,请检查表格数据是否包含该字段');
}
bindModalApi.open(); bindModalApi.open();
// 使ID
await nextTick(); await nextTick();
await bindFormApi.setValues({ await bindFormApi.setValues({
isNeedConfigDevicMdoel: false, isNeedConfigDevicMdoel: false,
deviceThingModelDataId: undefined, deviceThingModelDataId: undefined,
_ioTPlatformProductId: row.ioTPlatformProductId, _ioTPlatformProductId: productId ? String(productId) : undefined,
}); });
const formValues = await bindFormApi.getValues();
console.log('表单值设置完成,当前表单值:', formValues);
console.log('表单值中的 _ioTPlatformProductId:', formValues._ioTPlatformProductId);
}; };
// //
@ -687,27 +767,35 @@ async function submitBindDeviceThingModel() {
return; return;
} }
if (!bindRow.value?.id) { if (!bindRows.value || bindRows.value.length === 0) {
Message.error('设备信息缺失,无法绑定设备端物模型'); Message.error('请选择要绑定的设备');
return;
}
// ID
const deviceIds = bindRows.value
.map((row) => row.id)
.filter((id) => id); //
if (deviceIds.length === 0) {
Message.error('选中的设备中没有有效的设备ID');
return; return;
} }
try { try {
bindModalApi.setState({ loading: true, confirmLoading: true }); bindModalApi.setState({ loading: true, confirmLoading: true });
const result = await postDeviceInfoBindingDeviceThingModel({ const result = await postDeviceInfoBindingDeviceThingModel({
query: { body: {
input: { devieDataIdList: deviceIds,
devieDataId: bindRow.value.id, isNeedConfigDevicMdoel: isNeedConfig,
isNeedConfigDevicMdoel: isNeedConfig, deviceThingModelDataId: isNeedConfig ? deviceThingModelDataId : null,
deviceThingModelDataId: isNeedConfig ? deviceThingModelDataId : null,
},
}, },
}); });
if (result) { if (result.data) {
Message.success('绑定设备端物模型成功'); Message.success(`成功绑定 ${deviceIds.length} 个设备的设备端物模型`);
bindModalApi.close(); bindModalApi.close();
bindRow.value = {}; bindRows.value = [];
gridApi.reload(); gridApi.reload();
} else { } else {
Message.error('绑定设备端物模型失败'); Message.error('绑定设备端物模型失败');
@ -951,6 +1039,22 @@ const handleCacheRefresh = async () => {
} }
}; };
//
const openBatchBindModal = async () => {
//
try {
const checkboxRecords = gridApi?.getCheckboxRecords?.() || [];
if (checkboxRecords.length === 0) {
Message.warning('请先在表格中选择要绑定的设备');
return;
}
await openBindModal(checkboxRecords);
} catch (error) {
console.error('获取表格选中的设备失败:', error);
Message.error('获取表格选中的设备失败');
}
};
// //
const toolbarActions = computed(() => [ const toolbarActions = computed(() => [
{ {
@ -967,6 +1071,13 @@ const toolbarActions = computed(() => [
onClick: openBatchAddModal.bind(null), onClick: openBatchAddModal.bind(null),
auth: ['AbpIdentity.Users.Create'], auth: ['AbpIdentity.Users.Create'],
}, },
{
label: '批量绑定设备端物模型',
type: 'default',
icon: 'ant-design:link-outlined',
onClick: openBatchBindModal,
auth: ['AbpIdentity.Users.Create'],
},
{ {
label: cacheRefreshLoading.value label: cacheRefreshLoading.value
? $t('common.loading') ? $t('common.loading')
@ -1161,7 +1272,21 @@ const toolbarActions = computed(() => [
</div> </div>
</div> </div>
</CommandModal> </CommandModal>
<BindModal title="绑定设备端物模型" class="w-[600px]"> <BindModal :title="`绑定设备端物模型${bindRows.length > 0 ? ` (已选择 ${bindRows.length} 个设备)` : ''}`" class="w-[600px]">
<div v-if="bindRows.length > 0" class="mb-4 p-3 bg-blue-50 rounded border border-blue-200">
<div class="text-sm font-medium text-blue-800 mb-2">
已选择 {{ bindRows.length }} 个设备
</div>
<div class="text-xs text-blue-600 max-h-32 overflow-y-auto">
<div
v-for="(row, index) in bindRows"
:key="row.id || index"
class="mb-1"
>
{{ index + 1 }}. {{ row.deviceName || row.deviceAddress || row.id }}
</div>
</div>
</div>
<BindForm /> <BindForm />
</BindModal> </BindModal>
<BatchAddModal title="批量添加设备" class="w-[800px]"> <BatchAddModal title="批量添加设备" class="w-[800px]">

View File

@ -10,7 +10,7 @@ import {
getCommonGetSelectList, getCommonGetSelectList,
postCtWingAccountListAsync, postCtWingAccountListAsync,
postCtWingProductListAsync, postCtWingProductListAsync,
postIoTplatformThingModelInfoFindByPlatformProductIdAsync, postDeviceThingModelManagementFindByPlatformProductIdAsync,
postOneNetAccountListAsync, postOneNetAccountListAsync,
postOneNetProductListAsync, postOneNetProductListAsync,
} from '#/api-client'; } from '#/api-client';
@ -529,6 +529,14 @@ export const addDeviceFormSchema: any = computed(() => [
// 设备绑定设备端物模型表单 // 设备绑定设备端物模型表单
export const bindDeviceThingModelFormSchema: any = computed(() => [ export const bindDeviceThingModelFormSchema: any = computed(() => [
{
component: 'Input',
fieldName: '_ioTPlatformProductId',
label: '',
componentProps: {
type: 'hidden',
},
},
{ {
component: 'Switch', component: 'Switch',
fieldName: 'isNeedConfigDevicMdoel', fieldName: 'isNeedConfigDevicMdoel',
@ -545,7 +553,13 @@ export const bindDeviceThingModelFormSchema: any = computed(() => [
// 仅在需要配置设备模型时显示 // 仅在需要配置设备模型时显示
dependencies: { dependencies: {
show(values: any) { show(values: any) {
return !!values.isNeedConfigDevicMdoel; const shouldShow = !!values.isNeedConfigDevicMdoel;
console.log('设备物模型下拉框显示检查:', {
isNeedConfigDevicMdoel: values.isNeedConfigDevicMdoel,
shouldShow,
_ioTPlatformProductId: values._ioTPlatformProductId,
});
return shouldShow;
}, },
triggerFields: ['isNeedConfigDevicMdoel', '_ioTPlatformProductId'], triggerFields: ['isNeedConfigDevicMdoel', '_ioTPlatformProductId'],
}, },
@ -554,27 +568,32 @@ export const bindDeviceThingModelFormSchema: any = computed(() => [
const productId = const productId =
formValues?._ioTPlatformProductId || formValues?.ioTPlatformProductId; formValues?._ioTPlatformProductId || formValues?.ioTPlatformProductId;
return { console.log('设备物模型下拉框 componentProps 被调用:', {
formValues,
productId,
isNeedConfigDevicMdoel: formValues?.isNeedConfigDevicMdoel,
});
const config = {
api: productId api: productId
? postIoTplatformThingModelInfoFindByPlatformProductIdAsync ? postDeviceThingModelManagementFindByPlatformProductIdAsync
: null, : null,
params: productId params: productId
? { ? {
query: { query: {
input: { id: String(productId),
id: String(productId),
},
}, },
} }
: {}, : {},
// 平台物模型信息里的显示字段(优先显示标准字段显示名) // 设备端物模型信息里的显示字段
labelField: 'standardFieldDisplayName', labelField: 'deviceModelName',
valueField: 'id', valueField: 'id',
optionsPropName: 'options', optionsPropName: 'options',
immediate: !!productId, immediate: !!productId,
allowClear: true, allowClear: true,
placeholder: '请选择设备物模型', placeholder: '请选择设备物模型',
afterFetch: (res: any) => { afterFetch: (res: any) => {
console.log('设备物模型下拉框 afterFetch 被调用,响应:', res);
// 确保返回数组 // 确保返回数组
if (Array.isArray(res)) { if (Array.isArray(res)) {
return res; return res;
@ -591,6 +610,9 @@ export const bindDeviceThingModelFormSchema: any = computed(() => [
return []; return [];
}, },
}; };
console.log('设备物模型下拉框配置:', config);
return config;
}, },
// 规则在提交中按开关手动校验,这里设为可选 // 规则在提交中按开关手动校验,这里设为可选
rules: z.string().optional(), rules: z.string().optional(),