完善牧安云哨-前端

This commit is contained in:
BBIT-Kai
2025-12-29 16:30:04 +08:00
parent d78d3be5e0
commit cd7aa35960
7 changed files with 167 additions and 18 deletions
@@ -125,7 +125,7 @@ const withPreviewUpload = () => {
) => { ) => {
const previewVisible = ref<boolean>(false); const previewVisible = ref<boolean>(false);
const placeholder = attrs?.placeholder || $t(`ui.placeholder.upload`); const placeholder = attrs?.placeholder || '上传文件';
const listType = attrs?.listType || attrs?.['list-type'] || 'text'; const listType = attrs?.listType || attrs?.['list-type'] || 'text';
+142
View File
@@ -61,6 +61,148 @@ setupVbenVxeTable({
); );
}, },
}); });
/**
* 可扩展操作列渲染器
* - 支持普通操作(edit)
* - 支持确认型操作(delete / 自定义)
*/
vxeUI.renderer.add('CellOperationEx', {
renderTableDefault({ attrs, options, props }, { column, row }) {
const defaultProps = { size: 'small', type: 'link', ...props };
/** 对齐方式 */
let align = 'end';
switch (column.align) {
case 'center':
align = 'center';
break;
case 'left':
align = 'start';
break;
default:
align = 'end';
}
/** 预置操作 */
const presets: Recordable<Recordable<any>> = {
edit: {
code: 'edit',
text: $t('common.edit'),
},
delete: {
code: 'delete',
text: $t('common.delete'),
danger: true,
confirm: true,
confirmTitle: () =>
$t('ui.actionTitle.delete', [attrs?.nameTitle || '']),
confirmMessage: (row: any) =>
$t('ui.actionMessage.deleteConfirm', [
row[attrs?.nameField || 'name'],
]),
},
};
/** 生成操作配置 */
const operations = (options || ['edit', 'delete'])
.map((opt) => {
if (typeof opt === 'string') {
return presets[opt]
? { ...defaultProps, ...presets[opt] }
: {
...defaultProps,
code: opt,
text: opt,
};
}
return {
...defaultProps,
...presets[opt.code],
...opt,
};
})
.map((opt) => {
const resolved: Recordable<any> = {};
Object.keys(opt).forEach((key) => {
resolved[key] =
typeof opt[key] === 'function' ? opt[key](row) : opt[key];
});
return resolved;
})
.filter((opt) => opt.show !== false);
/** 普通按钮 */
function renderBtn(opt: Recordable<any>, listen = true) {
return h(
Button,
{
...opt,
icon: undefined,
onClick: listen
? () =>
attrs?.onClick?.({
code: opt.code,
row,
})
: undefined,
},
{ default: () => opt.text },
);
}
/** 确认型按钮 */
function renderConfirm(opt: Recordable<any>) {
let viewportWrapper: HTMLElement | null = null;
return h(
Popconfirm,
{
getPopupContainer(el) {
viewportWrapper = el.closest('.vxe-table--viewport-wrapper');
return document.body;
},
placement: 'topLeft',
title: opt.confirmTitle,
icon: undefined,
onOpenChange(open: boolean) {
if (open) {
viewportWrapper?.style.setProperty('pointer-events', 'none');
} else {
viewportWrapper?.style.removeProperty('pointer-events');
}
},
onConfirm() {
attrs?.onClick?.({
code: opt.code,
row,
});
},
},
{
default: () => renderBtn(opt, false),
description: () =>
opt.confirmMessage
? h('div', { class: 'truncate' }, opt.confirmMessage)
: null,
},
);
}
/** 根据是否需要确认选择渲染方式 */
const btns = operations.map((opt) =>
opt.confirm ? renderConfirm(opt) : renderBtn(opt),
);
return h(
'div',
{
class: 'flex table-operations',
style: { justifyContent: align },
},
btns,
);
},
});
/** /**
* 注册表格的操作按钮渲染器 * 注册表格的操作按钮渲染器
+19
View File
@@ -71,10 +71,29 @@ async function deleteDevice(id: string) {
return pyRequestClient.delete(`/iot/common/device/${id}`); return pyRequestClient.delete(`/iot/common/device/${id}`);
} }
/**
* 发送指令
* @param data 设备数据
*/
async function iotSendCommand(
id: string,
command: string,
project: string,
device_type: string,
) {
return pyRequestClient.post('/iot/common/device/command', {
id,
command,
project,
device_type,
});
}
export { export {
createDevice, createDevice,
deleteDevice, deleteDevice,
getDeviceList, getDeviceList,
iotSendCommand,
updateDevice, updateDevice,
updateDevicePatch, updateDevicePatch,
}; };
+1
View File
@@ -1 +1,2 @@
export * from './device'; export * from './device';
export * from './update';
+1 -1
View File
@@ -1 +1 @@
export * from './device'; export * from './record';
@@ -59,27 +59,16 @@ const routes: RouteRecordRaw[] = [
component: () => import('#/views/manager/dict/index.vue'), component: () => import('#/views/manager/dict/index.vue'),
}, },
{ {
name: 'M-perm', name: 'perm',
path: '/manager/perm', path: '/manager/perm',
meta: { meta: {
authority: ['manager'], authority: ['manager'],
icon: 'mdi:menu', icon: 'mdi:menu',
title: '菜单-实验室', title: '菜单管理',
keepAlive: true, keepAlive: true,
}, },
component: () => import('#/views/manager/menu/index.vue'), component: () => import('#/views/manager/menu/index.vue'),
}, },
{
name: 'M-perm2',
path: '/manager/perm2',
meta: {
authority: ['manager'],
icon: 'mdi:menu',
title: '菜单-大数据',
keepAlive: true,
},
component: () => import('#/views/manager/menu/index2.vue'),
},
], ],
}, },
]; ];
@@ -83,9 +83,7 @@ async function loadPermissions() {
} }
const getDrawerTitle = computed(() => { const getDrawerTitle = computed(() => {
return formData.value?.id return formData.value?.id ? '修改角色' : '新增角色';
? $t('common.edit', $t('system.role.name'))
: $t('common.create', $t('system.role.name'));
}); });
function getNodeClass(node: Recordable<any>) { function getNodeClass(node: Recordable<any>) {