完善 MCS 桌面代理与开炼机动作同步,修复原料相关菜单权限,桌面端新增上辅机 MES 菜单。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-27 15:56:05 +08:00
parent 7a9c19e4f3
commit 442a4c8ae2
113 changed files with 10169 additions and 91 deletions

View File

@@ -34,7 +34,7 @@
"@traptitech/markdown-it-katex": "^3.6.0",
"@vant/area-data": "^1.5.2",
"@vue/shared": "^3.5.22",
"@vueuse/core": "^10.11.1",
"@vueuse/core": "^10.11.1",
"@zxcvbn-ts/core": "^3.0.4",
"ant-design-vue": "^4.2.6",
"axios": "^1.12.2",

View File

@@ -3,12 +3,35 @@ import { FormSchema } from '/@/components/Form';
export const mcsDbConfigFormSchema: FormSchema[] = [
{ label: 'id', field: 'id', component: 'Input', show: false },
{ label: 'tenantId', field: 'tenantId', component: 'InputNumber', show: false },
{
label: '访问模式',
field: 'accessMode',
component: 'Select',
defaultValue: 'DESKTOP_AGENT',
required: true,
helpMessage: '桌面代理由厂区桌面端直连设备库直连MES 服务器 JDBC仅调试',
componentProps: {
options: [
{ label: '桌面代理(推荐)', value: 'DESKTOP_AGENT' },
{ label: '服务端直连', value: 'DIRECT' },
],
},
},
{
label: '绑定桌面代理 ID',
field: 'agentDeviceId',
component: 'Input',
helpMessage: '与桌面端「设备 ID」一致留空则自动选用当前在线代理',
componentProps: { placeholder: '例如工控机计算机名' },
ifShow: ({ values }) => values.accessMode !== 'DIRECT',
},
{
label: '服务器地址',
field: 'serverHost',
component: 'Input',
required: true,
componentProps: { placeholder: 'IP 或域名,例如 192.168.1.10 或 xxx.vicp.fun' },
ifShow: ({ values }) => values.accessMode === 'DIRECT',
},
{
label: '端口',
@@ -17,6 +40,7 @@ export const mcsDbConfigFormSchema: FormSchema[] = [
defaultValue: 1433,
required: true,
componentProps: { min: 1, max: 65535, style: { width: '100%' } },
ifShow: ({ values }) => values.accessMode === 'DIRECT',
},
{
label: '数据库名',
@@ -24,6 +48,7 @@ export const mcsDbConfigFormSchema: FormSchema[] = [
component: 'Input',
defaultValue: 'MES_ShareDB',
required: true,
ifShow: ({ values }) => values.accessMode === 'DIRECT',
},
{
label: '用户名',
@@ -31,12 +56,14 @@ export const mcsDbConfigFormSchema: FormSchema[] = [
component: 'Input',
required: true,
componentProps: { placeholder: '例如 sa' },
ifShow: ({ values }) => values.accessMode === 'DIRECT',
},
{
label: '密码',
field: 'dbPassword',
component: 'InputPassword',
componentProps: { placeholder: '编辑时留空表示不修改密码' },
ifShow: ({ values }) => values.accessMode === 'DIRECT',
},
{
label: '读取开关',
@@ -68,7 +95,7 @@ export const mcsDbConfigFormSchema: FormSchema[] = [
label: '启用连接',
field: 'status',
component: 'Switch',
helpMessage: '开启后立即连接中间库并热刷新数据源,无需重启后端',
helpMessage: '开启后立即生效(桌面代理模式无需 MES 直连 SQL Server',
componentProps: {
checkedChildren: '启用',
checkedValue: 1,
@@ -83,6 +110,7 @@ export const mcsDbConfigFormSchema: FormSchema[] = [
component: 'InputNumber',
defaultValue: 120,
componentProps: { min: 10, max: 600, style: { width: '100%' } },
ifShow: ({ values }) => values.accessMode === 'DIRECT',
},
{
label: '连接超时(毫秒)',
@@ -90,6 +118,7 @@ export const mcsDbConfigFormSchema: FormSchema[] = [
component: 'InputNumber',
defaultValue: 120000,
componentProps: { min: 5000, max: 600000, style: { width: '100%' } },
ifShow: ({ values }) => values.accessMode === 'DIRECT',
},
{
label: '备注',

View File

@@ -33,15 +33,15 @@
const values = await getMcsDbConfig({ tenantId });
setModalProps({ confirmLoading: false });
if (values) {
await setFieldsValue({ ...values, dbPassword: '' });
await setFieldsValue({ ...values, dbPassword: '', accessMode: values.accessMode || 'DESKTOP_AGENT' });
} else {
await setFieldsValue({ tenantId, readEnabled: 1, writeEnabled: 1, status: 0, serverPort: 1433, dbName: 'MES_ShareDB' });
await setFieldsValue({ tenantId, readEnabled: 1, writeEnabled: 1, status: 0, serverPort: 1433, dbName: 'MES_ShareDB', accessMode: 'DESKTOP_AGENT' });
}
});
async function handleSubmit() {
const values = await validate();
if (!values.id && !values.dbPassword) {
if (!values.id && values.accessMode === 'DIRECT' && !values.dbPassword) {
createMessage.warning('请输入数据库密码');
return;
}

View File

@@ -7,8 +7,8 @@
<div style="font-size: 16px"> 1.配置说明</div>
</template>
<div class="base-desc">
在此配置 SQL Server 中间库MES_ShareDB连接信息<strong>保存后立即生效无需重启后端</strong>也无需修改 application.yml
读取开关控制 MCSMES 方向数据查询写入开关控制 MESMCS 方向数据写入
推荐使用<strong>桌面代理</strong>模式厂区桌面端直连设备 SQL ServerMES 通过 STOMP 命令读写
也可切换为服务端直连仅调试读取/写入开关控制 MCSMES 方向
</div>
</a-collapse-panel>
</a-collapse>
@@ -22,18 +22,32 @@
</template>
<a-alert v-if="connStatus" type="info" show-icon style="margin-bottom: 12px" message="当前运行状态" :description="connStatus" />
<div class="flex-flow">
<div class="base-title">访问模式</div>
<div class="base-message" style="display: flex; align-items: center; height: 50px">
<a-tag :color="runtimeStatus.agentMode ? 'blue' : 'default'">{{ runtimeStatus.agentMode ? '桌面代理' : '服务端直连' }}</a-tag>
</div>
</div>
<div class="flex-flow">
<div class="base-title">桌面代理</div>
<div class="base-message" style="display: flex; align-items: center; height: 50px; gap: 8px">
<a-tag :color="runtimeStatus.agentOnline ? 'green' : 'orange'">{{ runtimeStatus.agentOnline ? '在线' : '离线' }}</a-tag>
<a-tag :color="runtimeStatus.agentDbConnected ? 'green' : 'default'">{{ runtimeStatus.agentDbConnected ? '库已连通' : '库未连通' }}</a-tag>
<span v-if="runtimeStatus.agentHostName || configData.agentDeviceId">{{ runtimeStatus.agentHostName || configData.agentDeviceId }}</span>
</div>
</div>
<div class="flex-flow" v-if="!runtimeStatus.agentMode">
<div class="base-title">服务器</div>
<div class="base-message">
<a-input :value="displayHost" readonly />
</div>
</div>
<div class="flex-flow">
<div class="flex-flow" v-if="!runtimeStatus.agentMode">
<div class="base-title">数据库</div>
<div class="base-message">
<a-input :value="configData.dbName || '-'" readonly />
</div>
</div>
<div class="flex-flow">
<div class="flex-flow" v-if="!runtimeStatus.agentMode">
<div class="base-title">用户名</div>
<div class="base-message">
<a-input :value="configData.dbUsername || '-'" readonly />
@@ -52,14 +66,14 @@
</div>
</div>
<div class="flex-flow">
<div class="base-title">连接状态</div>
<div class="base-title">配置状态</div>
<div class="base-message" style="display: flex; align-items: center; height: 50px">
<a-tag :color="runtimeStatus.dbConfigActive ? 'green' : 'orange'">{{ runtimeStatus.dbConfigActive ? '已启用数据库配置' : '使用 yml 默认配置' }}</a-tag>
<a-tag :color="runtimeStatus.dbConfigActive ? 'green' : 'orange'">{{ runtimeStatus.dbConfigActive ? '已启用' : '未启用/回退 yml' }}</a-tag>
</div>
</div>
<div style="margin-top: 20px; width: 100%; text-align: right">
<a-button type="primary" @click="editClick">编辑配置</a-button>
<a-button @click="testClick" style="margin-left: 10px">连接测试</a-button>
<a-button @click="testClick" style="margin-left: 10px">{{ runtimeStatus.agentMode ? '请求桌面探测' : '连接测试' }}</a-button>
<a-button v-if="configData.id" @click="deleteClick" danger style="margin-left: 10px">删除配置</a-button>
</div>
</a-collapse-panel>
@@ -97,9 +111,12 @@
const connStatus = computed(() => {
const s = runtimeStatus.value;
if (!configData.value.id) {
return '尚未保存数据库配置,当前使用 application.yml 中的 sqlserver_mcs 默认连接。';
return '尚未保存配置。推荐使用桌面代理模式桌面端连接设备库后MES 即可读写。';
}
return `读取:${s.readEnabled ? '开' : '关'} | 写入:${s.writeEnabled ? '开' : '关'} | 连接:${s.dbConfigActive ? '已启用数据库配置' : '使用 yml 默认配置'}`;
const mode = s.agentMode ? '桌面代理' : '服务端直连';
const agent = s.agentOnline ? '代理在线' : '代理离线';
const db = s.agentDbConnected ? '库连通' : '库未连通';
return `模式:${mode} | ${agent} | ${db} | 读取:${s.readEnabled ? '开' : '关'} | 写入:${s.writeEnabled ? '开' : '关'}${s.agentDbMessage ? ' | ' + s.agentDbMessage : ''}`;
});
async function reload() {

View File

@@ -1,13 +1,18 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
export const baseColumns: BasicColumn[] = [
{ title: '日期', align: 'center', dataIndex: 'statDate', width: 140 },
{ title: '原材料名称', align: 'center', dataIndex: 'rawMaterialName', width: 260, ellipsis: true },
{ title: '需求重量(KG)', align: 'center', dataIndex: 'demandWeight', width: 180 },
];
export const machineColumns: BasicColumn[] = [{ title: '机台', align: 'center', dataIndex: 'machineName', width: 180 }, ...baseColumns];
export const machineColumns: BasicColumn[] = [
baseColumns[0],
{ title: '机台', align: 'center', dataIndex: 'machineName', width: 180 },
...baseColumns.slice(1),
];
export const searchFormSchema: FormSchema[] = [
export const baseSearchFormSchema: FormSchema[] = [
{
label: '日期',
field: 'statDate',
@@ -18,6 +23,12 @@ export const searchFormSchema: FormSchema[] = [
{ label: '原材料名称', field: 'rawMaterialName', component: 'JInput', colProps: { span: 6 } },
];
export const machineSearchFormSchema: FormSchema[] = [
baseSearchFormSchema[0],
{ label: '机台', field: 'machineName', component: 'JInput', colProps: { span: 6 } },
...baseSearchFormSchema.slice(1),
];
export const superQuerySchema = {
machineName: { title: '机台', order: 0, view: 'text' },
statDate: { title: '日期', order: 1, view: 'date' },

View File

@@ -25,7 +25,8 @@
import {
baseColumns,
machineColumns,
searchFormSchema,
baseSearchFormSchema,
machineSearchFormSchema,
superQuerySchema,
} from './MesXslAutoSmallMaterialDemandPlan.data';
import { list, getExportUrl } from './MesXslAutoSmallMaterialDemandPlan.api';
@@ -40,7 +41,7 @@
columns: baseColumns,
canResize: true,
formConfig: {
schemas: searchFormSchema,
schemas: baseSearchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
},
@@ -57,20 +58,33 @@
},
});
const [registerTable, { reload, setColumns }] = tableContext;
const [registerTable, { reload, setColumns, setProps }] = tableContext;
const superQueryConfig = reactive(superQuerySchema);
onMounted(() => {
applyColumns();
applySearchSchemas();
});
function applyColumns() {
setColumns(groupByMachine.value ? machineColumns : baseColumns);
}
function applySearchSchemas() {
setProps({
formConfig: {
schemas: groupByMachine.value ? machineSearchFormSchema : baseSearchFormSchema,
},
});
}
function onGroupByMachineChange() {
queryParam.groupByMachine = groupByMachine.value ? 1 : 0;
if (!groupByMachine.value) {
delete queryParam.machineName;
}
applyColumns();
applySearchSchemas();
reload();
}

View File

@@ -1,13 +1,18 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
export const baseColumns: BasicColumn[] = [
{ title: '日期', align: 'center', dataIndex: 'statDate', width: 140 },
{ title: '原材料名称', align: 'center', dataIndex: 'rawMaterialName', width: 260, ellipsis: true },
{ title: '需求重量(KG)', align: 'center', dataIndex: 'demandWeight', width: 180 },
];
export const machineColumns: BasicColumn[] = [{ title: '机台', align: 'center', dataIndex: 'machineName', width: 180 }, ...baseColumns];
export const machineColumns: BasicColumn[] = [
baseColumns[0],
{ title: '机台', align: 'center', dataIndex: 'machineName', width: 180 },
...baseColumns.slice(1),
];
export const searchFormSchema: FormSchema[] = [
export const baseSearchFormSchema: FormSchema[] = [
{
label: '日期',
field: 'statDate',
@@ -18,6 +23,12 @@ export const searchFormSchema: FormSchema[] = [
{ label: '原材料名称', field: 'rawMaterialName', component: 'JInput', colProps: { span: 6 } },
];
export const machineSearchFormSchema: FormSchema[] = [
baseSearchFormSchema[0],
{ label: '机台', field: 'machineName', component: 'JInput', colProps: { span: 6 } },
...baseSearchFormSchema.slice(1),
];
export const superQuerySchema = {
machineName: { title: '机台', order: 0, view: 'text' },
statDate: { title: '日期', order: 1, view: 'date' },

View File

@@ -25,7 +25,8 @@
import {
baseColumns,
machineColumns,
searchFormSchema,
baseSearchFormSchema,
machineSearchFormSchema,
superQuerySchema,
} from './MesXslManualSmallMaterialDemandPlan.data';
import { list, getExportUrl } from './MesXslManualSmallMaterialDemandPlan.api';
@@ -40,7 +41,7 @@
columns: baseColumns,
canResize: true,
formConfig: {
schemas: searchFormSchema,
schemas: baseSearchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
},
@@ -57,20 +58,33 @@
},
});
const [registerTable, { reload, setColumns }] = tableContext;
const [registerTable, { reload, setColumns, setProps }] = tableContext;
const superQueryConfig = reactive(superQuerySchema);
onMounted(() => {
applyColumns();
applySearchSchemas();
});
function applyColumns() {
setColumns(groupByMachine.value ? machineColumns : baseColumns);
}
function applySearchSchemas() {
setProps({
formConfig: {
schemas: groupByMachine.value ? machineSearchFormSchema : baseSearchFormSchema,
},
});
}
function onGroupByMachineChange() {
queryParam.groupByMachine = groupByMachine.value ? 1 : 0;
if (!groupByMachine.value) {
delete queryParam.machineName;
}
applyColumns();
applySearchSchemas();
reload();
}

View File

@@ -0,0 +1,13 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/xslmes/mesXslMillAction/list',
queryById = '/xslmes/mesXslMillAction/queryById',
exportXls = '/xslmes/mesXslMillAction/exportXls',
}
export const getExportUrl = Api.exportXls;
export const list = (params) => defHttp.get({ url: Api.list, params });
export const queryById = (params) => defHttp.get({ url: Api.queryById, params });

View File

@@ -0,0 +1,33 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
export const columns: BasicColumn[] = [
{ title: 'GUID', align: 'center', dataIndex: 'guid', width: 280 },
{ title: '动作地址', align: 'center', dataIndex: 'actAddr', width: 100 },
{ title: '动作名称', align: 'center', dataIndex: 'actName', width: 140 },
{ title: '动作名称(英)', align: 'center', dataIndex: 'actNameEn', width: 140 },
{ title: '动作备注', align: 'center', dataIndex: 'actMemo', width: 120 },
{ title: '关联地址', align: 'center', dataIndex: 'actRepaddr', width: 100 },
{ title: '写入时间', align: 'center', dataIndex: 'writeTime', width: 170 },
{ title: '读写标识', align: 'center', dataIndex: 'rwFlag', width: 90 },
{ title: '更新时间', align: 'center', dataIndex: 'updateTime', width: 170 },
];
export const searchFormSchema: FormSchema[] = [
{ label: '动作名称', field: 'actName', component: 'Input', colProps: { span: 6 } },
{ label: '动作地址', field: 'actAddr', component: 'InputNumber', colProps: { span: 6 } },
{ label: 'GUID', field: 'guid', component: 'Input', colProps: { span: 6 } },
];
export const formSchema: FormSchema[] = [
{ label: '', field: 'id', component: 'Input', show: false },
{ label: 'GUID', field: 'guid', component: 'Input', componentProps: { disabled: true }, colProps: { span: 24 } },
{ label: '动作地址', field: 'actAddr', component: 'InputNumber', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '关联地址', field: 'actRepaddr', component: 'InputNumber', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '动作名称', field: 'actName', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '动作名称(英)', field: 'actNameEn', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '动作备注', field: 'actMemo', component: 'Input', componentProps: { disabled: true }, colProps: { span: 24 } },
{ label: '写入时间', field: 'writeTime', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '读取时间', field: 'readTime', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '读写标识', field: 'rwFlag', component: 'InputNumber', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '更新时间', field: 'updateTime', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
];

View File

@@ -0,0 +1,81 @@
<template>
<div class="mes-xsl-mill-action-page">
<BasicTable @register="registerTable">
<template #tableTitle>
<a-button type="primary" v-auth="'xslmes:mcsSyncConfig:setting'" preIcon="ant-design:sync-outlined" @click="openCollect"> 采集操作 </a-button>
<a-button type="link" v-auth="'xslmes:mes_xsl_mill_action:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
</template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
<MesXslMillActionModal @register="registerModal" />
<CollectModal @register="registerCollectModal" @success="reload" />
</div>
</template>
<script lang="ts" name="xslmes-mesXslMillAction" setup>
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage';
import MesXslMillActionModal from './components/MesXslMillActionModal.vue';
import CollectModal from '/@/views/xslmesMcs/mcsSyncConfig/components/CollectModal.vue';
import { columns, searchFormSchema } from './MesXslMillAction.data';
import { list, getExportUrl } from './MesXslMillAction.api';
const [registerModal, { openModal }] = useModal();
const [registerCollectModal, { openModal: openCollectModal }] = useModal();
const { tableContext, onExportXls } = useListPage({
tableProps: {
title: '开炼机动作接收',
api: list,
columns,
canResize: true,
formConfig: { labelWidth: 100, schemas: searchFormSchema, autoSubmitOnEnter: true },
actionColumn: { width: 80, fixed: 'right' },
},
exportConfig: { name: '开炼机动作接收', url: getExportUrl },
});
const [registerTable, { reload }] = tableContext;
function openCollect() {
openCollectModal(true, { bizType: 'MILL_ACT' });
}
function handleDetail(record: Recordable) {
openModal(true, { record, isUpdate: true, showFooter: false });
}
function getTableAction(record) {
return [{ label: '详情', onClick: handleDetail.bind(null, record) }];
}
</script>
<style lang="less" scoped>
/* 空数据时 BasicTable canResize 不计算高度,用视口高度把表格区域铺满 */
.mes-xsl-mill-action-page {
min-height: calc(100vh - 120px);
:deep(.jeecg-basic-table-form-container) {
min-height: inherit;
}
:deep(.ant-table-wrapper),
:deep(.ant-spin-nested-loading),
:deep(.ant-spin-container),
:deep(.ant-table),
:deep(.ant-table-container) {
min-height: calc(100vh - 280px);
}
:deep(.ant-table-body) {
min-height: calc(100vh - 360px) !important;
}
:deep(.ant-table-tbody > tr.ant-table-placeholder > td) {
height: calc(100vh - 360px);
}
}
</style>

View File

@@ -0,0 +1,30 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose title="开炼机动作接收" :width="900">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../MesXslMillAction.data';
defineEmits(['register']);
const [registerForm, { resetFields, setFieldsValue, setProps }] = useForm({
labelWidth: 120,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 12 },
disabled: true,
});
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
await resetFields();
setModalProps({ confirmLoading: false, showOkBtn: false, showCancelBtn: true, cancelText: '关闭' });
if (data?.record) {
await setFieldsValue({ ...data.record });
}
setProps({ disabled: true });
});
</script>

View File

@@ -10,16 +10,23 @@ export const baseColumns: BasicColumn[] = [
];
export const machineColumns: BasicColumn[] = [
baseColumns[0],
{ title: '机台', align: 'center', dataIndex: 'machineName', width: 160 },
...baseColumns,
...baseColumns.slice(1),
];
export const searchFormSchema: FormSchema[] = [
export const baseSearchFormSchema: FormSchema[] = [
{ label: '计划日期', field: 'planDate', component: 'DatePicker', colProps: { span: 6 } },
{ label: 'ERP编号', field: 'erpCode', component: 'JInput', colProps: { span: 6 } },
{ label: '原材料名称', field: 'rawMaterialName', component: 'JInput', colProps: { span: 6 } },
];
export const machineSearchFormSchema: FormSchema[] = [
baseSearchFormSchema[0],
{ label: '机台', field: 'machineName', component: 'JInput', colProps: { span: 6 } },
...baseSearchFormSchema.slice(1),
];
export const superQuerySchema = {
planDate: { title: '计划日期', order: 0, view: 'date' },
machineName: { title: '机台', order: 1, view: 'text' },

View File

@@ -25,7 +25,8 @@
import {
baseColumns,
machineColumns,
searchFormSchema,
baseSearchFormSchema,
machineSearchFormSchema,
superQuerySchema,
} from './MesXslRawMaterialDemandPlan.data';
import { list, getExportUrl } from './MesXslRawMaterialDemandPlan.api';
@@ -40,7 +41,7 @@
columns: baseColumns,
canResize: true,
formConfig: {
schemas: searchFormSchema,
schemas: baseSearchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
},
@@ -57,20 +58,33 @@
},
});
const [registerTable, { reload, setColumns }] = tableContext;
const [registerTable, { reload, setColumns, setProps }] = tableContext;
const superQueryConfig = reactive(superQuerySchema);
onMounted(() => {
applyColumns();
applySearchSchemas();
});
function applyColumns() {
setColumns(groupByMachine.value ? machineColumns : baseColumns);
}
function applySearchSchemas() {
setProps({
formConfig: {
schemas: groupByMachine.value ? machineSearchFormSchema : baseSearchFormSchema,
},
});
}
function onGroupByMachineChange() {
queryParam.groupByMachine = groupByMachine.value ? 1 : 0;
if (!groupByMachine.value) {
delete queryParam.machineName;
}
applyColumns();
applySearchSchemas();
reload();
}

View File

@@ -0,0 +1,13 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/xslmes/mcs/mcsToMesActMill/list',
queryById = '/xslmes/mcs/mcsToMesActMill/queryById',
exportXls = '/xslmes/mcs/mcsToMesActMill/exportXls',
}
export const getExportUrl = Api.exportXls;
export const list = (params) => defHttp.get({ url: Api.list, params });
export const queryById = (params) => defHttp.get({ url: Api.queryById, params });

View File

@@ -0,0 +1,29 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
export const columns: BasicColumn[] = [
{ title: 'GUID', align: 'center', dataIndex: 'guid', width: 280 },
{ title: '动作地址', align: 'center', dataIndex: 'actAddr', width: 100 },
{ title: '动作名称', align: 'center', dataIndex: 'actName', width: 140 },
{ title: '动作名称(英)', align: 'center', dataIndex: 'actNameEn', width: 140 },
{ title: '动作备注', align: 'center', dataIndex: 'actMemo', width: 120 },
{ title: '关联地址', align: 'center', dataIndex: 'actRepaddr', width: 100 },
{ title: '写入时间', align: 'center', dataIndex: 'writeTime', width: 170 },
{ title: '读写标识', align: 'center', dataIndex: 'rwFlag', width: 90 },
];
export const searchFormSchema: FormSchema[] = [
{ label: '动作名称', field: 'actName', component: 'JInput', colProps: { span: 6 } },
{ label: '动作地址', field: 'actAddr', component: 'InputNumber', colProps: { span: 6 } },
];
export const formSchema: FormSchema[] = [
{ label: 'GUID', field: 'guid', component: 'Input', componentProps: { disabled: true }, colProps: { span: 24 } },
{ label: '动作地址', field: 'actAddr', component: 'InputNumber', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '关联地址', field: 'actRepaddr', component: 'InputNumber', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '动作名称', field: 'actName', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '动作名称(英)', field: 'actNameEn', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '动作备注', field: 'actMemo', component: 'Input', componentProps: { disabled: true }, colProps: { span: 24 } },
{ label: '写入时间', field: 'writeTime', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '读取时间', field: 'readTime', component: 'Input', componentProps: { disabled: true }, colProps: { span: 12 } },
{ label: '读写标识', field: 'rwFlag', component: 'InputNumber', componentProps: { disabled: true }, colProps: { span: 12 } },
];

View File

@@ -0,0 +1,30 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose title="开炼机动作(中间库)" :width="900">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../McsToMesActMill.data';
defineEmits(['register']);
const [registerForm, { resetFields, setFieldsValue, setProps }] = useForm({
labelWidth: 120,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 12 },
disabled: true,
});
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
await resetFields();
setModalProps({ confirmLoading: false, showOkBtn: false, showCancelBtn: true, cancelText: '关闭' });
if (data?.record) {
await setFieldsValue({ ...data.record });
}
setProps({ disabled: true });
});
</script>

View File

@@ -0,0 +1,71 @@
<template>
<div>
<BasicTable @register="registerTable">
<template #tableTitle>
<a-button type="primary" v-auth="'xslmes:mcsSyncConfig:setting'" preIcon="ant-design:sync-outlined" @click="openCollect"> 采集操作 </a-button>
<a-button type="link" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
</template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
<McsToMesActMillModal @register="registerModal" />
<CollectModal @register="registerCollectModal" @success="reload" />
</div>
</template>
<script lang="ts" name="xslmes-mcs-mcsToMesActMill" setup>
import { reactive } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage';
import McsToMesActMillModal from './components/McsToMesActMillModal.vue';
import CollectModal from '../mcsSyncConfig/components/CollectModal.vue';
import { columns, searchFormSchema } from './McsToMesActMill.data';
import { list, getExportUrl } from './McsToMesActMill.api';
const queryParam = reactive<any>({});
const [registerModal, { openModal }] = useModal();
const [registerCollectModal, { openModal: openCollectModal }] = useModal();
const { tableContext, onExportXls } = useListPage({
tableProps: {
title: '开炼机动作(中间库)',
api: list,
columns,
canResize: true,
formConfig: {
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
fieldMapToTime: [['writeTime', ['writeTime_begin', 'writeTime_end'], 'YYYY-MM-DD HH:mm:ss']],
},
actionColumn: { width: 80, fixed: 'right' },
beforeFetch: (params) => Object.assign(params, queryParam),
},
exportConfig: { name: '开炼机动作(中间库)', url: getExportUrl, params: queryParam },
});
const [registerTable, { reload }] = tableContext;
const superQueryConfig = reactive({});
function openCollect() {
openCollectModal(true, { bizType: 'MILL_ACT' });
}
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
reload();
}
function handleDetail(record: Recordable) {
openModal(true, { record, isUpdate: true, showFooter: false });
}
function getTableAction(record) {
return [{ label: '详情', onClick: handleDetail.bind(null, record) }];
}
</script>