feat:配方管理适配国际化

main
黄伟杰 1 week ago
parent fae45959ed
commit bc41f47898

@ -1583,5 +1583,198 @@ export default {
updateSuccess: 'Update successful',
updateFail: 'Update failed'
}
},
RecipeManagement: {
RecipeType: {
moduleName: 'Recipe Type',
searchNameLabel: 'Name',
searchNamePlaceholder: 'Please enter name',
searchProcessLabel: 'Process',
searchProcessPlaceholder: 'Please select process',
searchButtonText: 'Search',
resetButtonText: 'Reset',
createButtonText: 'Add',
exportButtonText: 'Export',
tableNameColumn: 'Name',
tableProcessColumn: 'Process',
tableRemarkColumn: 'Remark',
tableOperateColumn: 'Operation',
tableEditAction: 'Edit',
tableDeleteAction: 'Delete',
dialogCreateTitle: 'Create Recipe Type',
dialogEditTitle: 'Edit Recipe Type',
dialogNameLabel: 'Name',
dialogNamePlaceholder: 'Please enter name',
dialogProcessLabel: 'Process',
dialogProcessPlaceholder: 'Please select process',
dialogRemarkLabel: 'Remark',
dialogRemarkPlaceholder: 'Please enter remark',
dialogCancelButton: 'Cancel',
dialogSaveButton: 'Save',
validatorNameRequired: 'Name cannot be empty',
validatorProcessRequired: 'Process cannot be empty',
exportNoSelectionMessage: 'Please select data to export',
exportFileName: 'RecipeType.xls'
},
RecipeConfig: {
moduleName: 'Recipe Config',
searchRecipeCodeLabel: 'Recipe Code',
searchRecipeCodePlaceholder: 'Please enter recipe code',
searchNameLabel: 'Recipe Name',
searchNamePlaceholder: 'Please enter recipe name',
searchProductNameLabel: 'Product Name',
searchProductNamePlaceholder: 'Please enter product name',
searchButtonText: 'Search',
resetButtonText: 'Reset',
createButtonText: 'Add',
exportButtonText: 'Export',
tableRecipeCodeColumn: 'Recipe Code',
tableNameColumn: 'Recipe Name',
tableRecipeTypeColumn: 'Recipe Type',
tableProductNameColumn: 'Related Product',
tableMachineNameColumn: 'Related Device',
tableRecipeDescColumn: 'Recipe Description',
tableOperateColumn: 'Operation',
tableConfigAction: 'Config',
tableEditAction: 'Edit',
tableDeleteAction: 'Delete',
dialogCreateTitle: 'Create Recipe Config',
dialogEditTitle: 'Edit Recipe Config',
dialogRecipeCodeLabel: 'Recipe Code',
dialogRecipeCodePlaceholder: 'Please enter recipe code',
dialogNameLabel: 'Recipe Name',
dialogNamePlaceholder: 'Please enter recipe name',
dialogRecipeTypeLabel: 'Recipe Type',
dialogRecipeTypePlaceholder: 'Please select recipe type',
dialogProductNameLabel: 'Related Product',
dialogProductNamePlaceholder: 'Please select related product',
dialogMachineNameLabel: 'Related Device',
dialogMachineNamePlaceholder: 'Please select related device',
dialogRecipeDescLabel: 'Recipe Description',
dialogRecipeDescPlaceholder: 'Please enter recipe description',
dialogCancelButton: 'Cancel',
dialogSaveButton: 'Save',
validatorRecipeCodeRequired: 'Recipe code cannot be empty',
validatorNameRequired: 'Recipe name cannot be empty',
exportNoSelectionMessage: 'Please select data to export',
exportFileName: 'RecipeConfig.xls',
detailCollapseButton: 'Collapse',
detailTabDetailLabel: 'Detail',
detailTabManualLabel: 'Manual Parameters',
detailConfigButton: 'Config',
detailIndexColumn: 'Index',
detailPointNameColumn: 'Point Name',
detailPointTypeColumn: 'Point Type',
detailDataTypeColumn: 'Data Type',
detailDataUnitColumn: 'Unit',
manualCreateButton: 'Add',
manualTableNameColumn: 'Name',
manualTableMaxColumn: 'Upper Limit',
manualTableMinColumn: 'Lower Limit',
manualTableDataUnitColumn: 'Unit',
manualTableRemarkColumn: 'Remark',
manualTableOperateColumn: 'Operation',
manualTableEditAction: 'Edit',
manualTableDeleteAction: 'Delete',
manualDialogCreateTitle: 'Create Parameter',
manualDialogEditTitle: 'Edit Parameter',
manualDialogNameLabel: 'Name',
manualDialogNamePlaceholder: 'Please enter name',
manualDialogMaxLabel: 'Upper Limit',
manualDialogMaxPlaceholder: 'Please enter upper limit',
manualDialogMinLabel: 'Lower Limit',
manualDialogMinPlaceholder: 'Please enter lower limit',
manualDialogDataTypeLabel: 'Data Type',
manualDialogDataTypePlaceholder: 'Please select data type',
manualDialogDataUnitLabel: 'Unit',
manualDialogDataUnitPlaceholder: 'Please select unit',
manualDialogRemarkLabel: 'Remark',
manualDialogRemarkPlaceholder: 'Please enter remark',
manualDialogCancelButton: 'Cancel',
manualDialogSaveButton: 'Save',
manualValidatorNameRequired: 'Name cannot be empty',
manualValidatorMaxRequired: 'Upper limit cannot be empty',
manualValidatorMinRequired: 'Lower limit cannot be empty',
manualValidatorDataTypeRequired: 'Data type cannot be empty',
manualValidatorDataUnitRequired: 'Unit cannot be empty',
configDialogTitle: 'Config',
configSourceTitle: 'Source',
configTargetTitle: 'Target',
configFilterPlaceholder: 'Filter',
configMoveToTargetButton: 'Add to Target',
configMoveToSourceButton: 'Move to Source',
configCancelButton: 'Cancel',
configSaveButton: 'Save',
configDeviceLabelFallback: '-',
configSourceCountLabel: 'Source Count',
configTargetCountLabel: 'Target Count'
},
RecipeLibrary: {
moduleName: 'Recipe Library',
searchCodeLabel: 'Code',
searchCodePlaceholder: 'Please enter code',
searchNameLabel: 'Name',
searchNamePlaceholder: 'Please enter name',
searchRecipeLabel: 'Recipe Name',
searchRecipePlaceholder: 'Please select recipe',
searchPlanLabel: 'Related Plan',
searchPlanPlaceholder: 'Please select plan',
searchButtonText: 'Search',
resetButtonText: 'Reset',
createButtonText: 'Add',
exportButtonText: 'Export',
tableCodeColumn: 'Code',
tableNameColumn: 'Name',
tableRecipeNameColumn: 'Recipe Name',
tablePlanCodeColumn: 'Related Plan',
tableCreatorColumn: 'Creator',
tableCreateTimeColumn: 'Create Time',
tableOperateColumn: 'Operation',
tableReadAction: 'Read',
tableEditAction: 'Edit',
tableDeleteAction: 'Delete',
dialogCodeLabel: 'Code',
dialogCodePlaceholder: 'Please enter code',
dialogNameLabel: 'Name',
dialogNamePlaceholder: 'Please enter name',
dialogRecipeLabel: 'Recipe',
dialogRecipePlaceholder: 'Please select recipe',
dialogPlanLabel: 'Related Plan',
dialogPlanPlaceholder: 'Please select plan',
dialogSourceLabel: 'Source',
dialogSourcePlaceholder: 'Please select source',
dialogCancelButton: 'Cancel',
dialogSaveButton: 'Save',
validatorCodeRequired: 'Code cannot be empty',
validatorNameRequired: 'Name cannot be empty',
validatorRecipeRequired: 'Related recipe cannot be empty',
validatorPlanRequired: 'Related plan cannot be empty',
exportFileName: 'RecipeLibrary.xls',
sourceOptionNewLabel: 'New',
sourceOptionProducingLabel: 'In Production',
readDialogTitle: 'Read',
readDialogNameColumn: 'Name',
readDialogDataTypeColumn: 'Data Type',
readDialogDataUnitColumn: 'Unit',
readDialogMaxColumn: 'Upper Limit',
readDialogMinColumn: 'Lower Limit',
readDialogRemarkColumn: 'Remark',
readDialogReferColumn: 'Collected Value',
readDialogReferPlaceholder: 'Please enter collected value',
readDialogSubmitButtonText: 'Read',
readDialogCancelButton: 'Cancel',
readDeviceConfirmMessage: 'Do you want to read device data?',
detailTabDeviceDataLabel: 'Device Data',
detailTabManualLabel: 'Manual Parameters',
detailDevicePointNameColumn: 'Point Name',
detailDeviceDataTypeColumn: 'Data Type',
detailDeviceDataUnitColumn: 'Unit',
detailDeviceValueColumn: 'Collected Value',
manualTableNameColumn: 'Name',
manualTableDataTypeColumn: 'Data Type',
manualTableDataUnitColumn: 'Unit',
manualTableReferColumn: 'Reference Value',
manualTableRemarkColumn: 'Remark'
}
}
}

@ -1579,5 +1579,198 @@ export default {
updateSuccess: '更新成功',
updateFail: '更新失败'
}
},
RecipeManagement: {
RecipeType: {
moduleName: '配方类型',
searchNameLabel: '名称',
searchNamePlaceholder: '请输入名称',
searchProcessLabel: '工序',
searchProcessPlaceholder: '请选择工序',
searchButtonText: '查询',
resetButtonText: '重置',
createButtonText: '新增',
exportButtonText: '导出',
tableNameColumn: '名称',
tableProcessColumn: '工序',
tableRemarkColumn: '备注',
tableOperateColumn: '操作',
tableEditAction: '编辑',
tableDeleteAction: '删除',
dialogCreateTitle: '新增配方类型',
dialogEditTitle: '编辑配方类型',
dialogNameLabel: '名称',
dialogNamePlaceholder: '请输入名称',
dialogProcessLabel: '工序',
dialogProcessPlaceholder: '请选择工序',
dialogRemarkLabel: '备注',
dialogRemarkPlaceholder: '请输入备注',
dialogCancelButton: '取 消',
dialogSaveButton: '保 存',
validatorNameRequired: '名称不能为空',
validatorProcessRequired: '工序不能为空',
exportNoSelectionMessage: '请选择需要导出的数据',
exportFileName: '配方类型.xls'
},
RecipeConfig: {
moduleName: '配方配置',
searchRecipeCodeLabel: '配方编码',
searchRecipeCodePlaceholder: '请输入配方编码',
searchNameLabel: '配方名称',
searchNamePlaceholder: '请输入配方名称',
searchProductNameLabel: '产品名称',
searchProductNamePlaceholder: '请输入产品名称',
searchButtonText: '查询',
resetButtonText: '重置',
createButtonText: '新增',
exportButtonText: '导出',
tableRecipeCodeColumn: '配方编码',
tableNameColumn: '配方名称',
tableRecipeTypeColumn: '配方类型',
tableProductNameColumn: '关联产品',
tableMachineNameColumn: '关联设备',
tableRecipeDescColumn: '配方描述',
tableOperateColumn: '操作',
tableConfigAction: '配置',
tableEditAction: '编辑',
tableDeleteAction: '删除',
dialogCreateTitle: '新增配方配置',
dialogEditTitle: '编辑配方配置',
dialogRecipeCodeLabel: '配方编码',
dialogRecipeCodePlaceholder: '请输入配方编码',
dialogNameLabel: '配方名称',
dialogNamePlaceholder: '请输入配方名称',
dialogRecipeTypeLabel: '配方类型',
dialogRecipeTypePlaceholder: '请选择配方类型',
dialogProductNameLabel: '关联产品',
dialogProductNamePlaceholder: '请选择关联产品',
dialogMachineNameLabel: '关联设备',
dialogMachineNamePlaceholder: '请选择关联设备',
dialogRecipeDescLabel: '配方描述',
dialogRecipeDescPlaceholder: '请输入配方描述',
dialogCancelButton: '取 消',
dialogSaveButton: '保 存',
validatorRecipeCodeRequired: '配方编码不能为空',
validatorNameRequired: '配方名称不能为空',
exportNoSelectionMessage: '请选择需要导出的数据',
exportFileName: '配方配置.xls',
detailCollapseButton: '收起',
detailTabDetailLabel: '详情',
detailTabManualLabel: '手动录入参数',
detailConfigButton: '配置',
detailIndexColumn: '序号',
detailPointNameColumn: '点位名称',
detailPointTypeColumn: '点位类型',
detailDataTypeColumn: '数据类型',
detailDataUnitColumn: '单位',
manualCreateButton: '新增',
manualTableNameColumn: '名称',
manualTableMaxColumn: '上限',
manualTableMinColumn: '下限',
manualTableDataUnitColumn: '单位',
manualTableRemarkColumn: '备注',
manualTableOperateColumn: '操作',
manualTableEditAction: '编辑',
manualTableDeleteAction: '删除',
manualDialogCreateTitle: '新增参数',
manualDialogEditTitle: '编辑参数',
manualDialogNameLabel: '名称',
manualDialogNamePlaceholder: '请输入名称',
manualDialogMaxLabel: '上限',
manualDialogMaxPlaceholder: '请输入上限',
manualDialogMinLabel: '下限',
manualDialogMinPlaceholder: '请输入下限',
manualDialogDataTypeLabel: '数据类型',
manualDialogDataTypePlaceholder: '请选择数据类型',
manualDialogDataUnitLabel: '单位',
manualDialogDataUnitPlaceholder: '请选择单位',
manualDialogRemarkLabel: '备注',
manualDialogRemarkPlaceholder: '请输入备注',
manualDialogCancelButton: '取 消',
manualDialogSaveButton: '保 存',
manualValidatorNameRequired: '名称不能为空',
manualValidatorMaxRequired: '上限不能为空',
manualValidatorMinRequired: '下限不能为空',
manualValidatorDataTypeRequired: '数据类型不能为空',
manualValidatorDataUnitRequired: '单位不能为空',
configDialogTitle: '配置',
configSourceTitle: '来源',
configTargetTitle: '目标',
configFilterPlaceholder: '筛选',
configMoveToTargetButton: '添加到目标',
configMoveToSourceButton: '移回来源',
configCancelButton: '取 消',
configSaveButton: '保 存',
configDeviceLabelFallback: '-',
configSourceCountLabel: '来源数量',
configTargetCountLabel: '目标数量'
},
RecipeLibrary: {
moduleName: '配方库',
searchCodeLabel: '编码',
searchCodePlaceholder: '请输入编码',
searchNameLabel: '名称',
searchNamePlaceholder: '请输入名称',
searchRecipeLabel: '配方名称',
searchRecipePlaceholder: '请选择配方',
searchPlanLabel: '关联计划',
searchPlanPlaceholder: '请选择关联计划',
searchButtonText: '查询',
resetButtonText: '重置',
createButtonText: '新增',
exportButtonText: '导出',
tableCodeColumn: '编码',
tableNameColumn: '名称',
tableRecipeNameColumn: '配方名称',
tablePlanCodeColumn: '关联计划',
tableCreatorColumn: '创建人',
tableCreateTimeColumn: '创建时间',
tableOperateColumn: '操作',
tableReadAction: '读取',
tableEditAction: '编辑',
tableDeleteAction: '删除',
dialogCodeLabel: '编码',
dialogCodePlaceholder: '请输入编码',
dialogNameLabel: '名称',
dialogNamePlaceholder: '请输入名称',
dialogRecipeLabel: '配方',
dialogRecipePlaceholder: '请选择配方',
dialogPlanLabel: '关联计划',
dialogPlanPlaceholder: '请选择关联计划',
dialogSourceLabel: '来源',
dialogSourcePlaceholder: '请选择来源',
dialogCancelButton: '取 消',
dialogSaveButton: '保 存',
validatorCodeRequired: '编码不能为空',
validatorNameRequired: '名称不能为空',
validatorRecipeRequired: '关联配方不能为空',
validatorPlanRequired: '关联计划不能为空',
exportFileName: '配方库.xls',
sourceOptionNewLabel: '新增',
sourceOptionProducingLabel: '生产中',
readDialogTitle: '读取',
readDialogNameColumn: '名称',
readDialogDataTypeColumn: '数据类型',
readDialogDataUnitColumn: '单位',
readDialogMaxColumn: '上限',
readDialogMinColumn: '下限',
readDialogRemarkColumn: '备注',
readDialogReferColumn: '采集值',
readDialogReferPlaceholder: '请输入采集值',
readDialogSubmitButtonText: '读 取',
readDialogCancelButton: '取 消',
readDeviceConfirmMessage: '是否读取设备数据?',
detailTabDeviceDataLabel: '设备数据',
detailTabManualLabel: '手动录入参数',
detailDevicePointNameColumn: '点位名称',
detailDeviceDataTypeColumn: '数据类型',
detailDeviceDataUnitColumn: '单位',
detailDeviceValueColumn: '采集值',
manualTableNameColumn: '名称',
manualTableDataTypeColumn: '数据类型',
manualTableDataUnitColumn: '单位',
manualTableReferColumn: '参考值',
manualTableRemarkColumn: '备注'
}
}
}

@ -2,22 +2,49 @@
<ContentWrap v-if="visible">
<el-tabs v-model="activeTab" class="mb-12px">
<template #extra>
<el-button link type="info" @click="handleClose"></el-button>
<el-button link type="info" @click="handleClose">
{{ t('RecipeManagement.RecipeConfig.detailCollapseButton') }}
</el-button>
</template>
<el-tab-pane :label="`详情:${recipeCode} - ${name}`" name="detail">
<el-tab-pane
:label="`${t('RecipeManagement.RecipeConfig.detailTabDetailLabel')}${recipeCode} - ${name}`"
name="detail"
>
<div class="mb-12px text-left">
<el-button type="primary" @click="handleConfig"></el-button>
<el-button type="primary" @click="handleConfig">
{{ t('RecipeManagement.RecipeConfig.detailConfigButton') }}
</el-button>
</div>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id">
<el-table-column label="序号" align="center" width="80">
<el-table-column
:label="t('RecipeManagement.RecipeConfig.detailIndexColumn')"
align="center"
width="80"
>
<template #default="scope">
{{ (queryParams.pageNo - 1) * queryParams.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="点位名称" align="center" prop="pointName" />
<el-table-column label="点位类型" align="center" prop="pointType" />
<el-table-column label="数据类型" align="center" prop="dataType" />
<el-table-column label="单位" align="center" prop="dataUnit" />
<el-table-column
:label="t('RecipeManagement.RecipeConfig.detailPointNameColumn')"
align="center"
prop="pointName"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.detailPointTypeColumn')"
align="center"
prop="pointType"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.detailDataTypeColumn')"
align="center"
prop="dataType"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.detailDataUnitColumn')"
align="center"
prop="dataUnit"
/>
</el-table>
<Pagination
:total="total"
@ -27,9 +54,11 @@
/>
</el-tab-pane>
<el-tab-pane label="手动录入参数" name="manual">
<el-tab-pane :label="t('RecipeManagement.RecipeConfig.detailTabManualLabel')" name="manual">
<div class="mb-12px flex justify-start">
<el-button type="primary" @click="openManualDialog('create')"></el-button>
<el-button type="primary" @click="openManualDialog('create')">
{{ t('RecipeManagement.RecipeConfig.manualCreateButton') }}
</el-button>
</div>
<el-table
v-loading="manualLoading"
@ -38,15 +67,44 @@
:show-overflow-tooltip="true"
row-key="id"
>
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="上限" align="center" prop="max" />
<el-table-column label="下限" align="center" prop="min" />
<el-table-column label="单位" align="center" prop="dataUnit" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" width="150px" fixed="right">
<el-table-column
:label="t('RecipeManagement.RecipeConfig.manualTableNameColumn')"
align="center"
prop="name"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.manualTableMaxColumn')"
align="center"
prop="max"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.manualTableMinColumn')"
align="center"
prop="min"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.manualTableDataUnitColumn')"
align="center"
prop="dataUnit"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.manualTableRemarkColumn')"
align="center"
prop="remark"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.manualTableOperateColumn')"
align="center"
width="150px"
fixed="right"
>
<template #default="scope">
<el-button link type="primary" @click="openManualDialog('update', scope.row)">编辑</el-button>
<el-button link type="danger" @click="handleManualDelete(scope.row)"></el-button>
<el-button link type="primary" @click="openManualDialog('update', scope.row)">
{{ t('RecipeManagement.RecipeConfig.manualTableEditAction') }}
</el-button>
<el-button link type="danger" @click="handleManualDelete(scope.row)">
{{ t('RecipeManagement.RecipeConfig.manualTableDeleteAction') }}
</el-button>
</template>
</el-table-column>
</el-table>
@ -60,7 +118,11 @@
</el-tabs>
<Dialog
:title="manualDialogMode === 'create' ? '新增参数' : '编辑参数'"
:title="
manualDialogMode === 'create'
? t('RecipeManagement.RecipeConfig.manualDialogCreateTitle')
: t('RecipeManagement.RecipeConfig.manualDialogEditTitle')
"
v-model="manualDialogVisible"
width="640px"
>
@ -68,20 +130,39 @@
ref="manualFormRef"
:model="manualForm"
:rules="manualRules"
label-width="90px"
class="recipe-config-manual-dialog-form"
label-width="auto"
v-loading="manualDialogLoading"
>
<el-form-item label="名称" prop="name">
<el-input v-model="manualForm.name" placeholder="请输入名称" clearable />
<el-form-item :label="t('RecipeManagement.RecipeConfig.manualDialogNameLabel')" prop="name">
<el-input
v-model="manualForm.name"
:placeholder="t('RecipeManagement.RecipeConfig.manualDialogNamePlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="上限" prop="max">
<el-input v-model="manualForm.max" placeholder="请输入上限" clearable />
<el-form-item :label="t('RecipeManagement.RecipeConfig.manualDialogMaxLabel')" prop="max">
<el-input
v-model="manualForm.max"
:placeholder="t('RecipeManagement.RecipeConfig.manualDialogMaxPlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="下限" prop="min">
<el-input v-model="manualForm.min" placeholder="请输入下限" clearable />
<el-form-item :label="t('RecipeManagement.RecipeConfig.manualDialogMinLabel')" prop="min">
<el-input
v-model="manualForm.min"
:placeholder="t('RecipeManagement.RecipeConfig.manualDialogMinPlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="数据类型" prop="dataType">
<el-select v-model="manualForm.dataType" placeholder="请选择数据类型" clearable filterable class="!w-full">
<el-form-item :label="t('RecipeManagement.RecipeConfig.manualDialogDataTypeLabel')" prop="dataType">
<el-select
v-model="manualForm.dataType"
:placeholder="t('RecipeManagement.RecipeConfig.manualDialogDataTypePlaceholder')"
clearable
filterable
class="!w-full"
>
<el-option
v-for="dict in dataTypeDictOptions"
:key="dict.value"
@ -90,8 +171,14 @@
/>
</el-select>
</el-form-item>
<el-form-item label="单位" prop="dataUnit">
<el-select v-model="manualForm.dataUnit" placeholder="请选择单位" clearable filterable class="!w-full">
<el-form-item :label="t('RecipeManagement.RecipeConfig.manualDialogDataUnitLabel')" prop="dataUnit">
<el-select
v-model="manualForm.dataUnit"
:placeholder="t('RecipeManagement.RecipeConfig.manualDialogDataUnitPlaceholder')"
clearable
filterable
class="!w-full"
>
<el-option
v-for="dict in unitDictOptions"
:key="dict.value"
@ -100,13 +187,22 @@
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="manualForm.remark" placeholder="请输入备注" clearable type="textarea" />
<el-form-item :label="t('RecipeManagement.RecipeConfig.manualDialogRemarkLabel')" prop="remark">
<el-input
v-model="manualForm.remark"
:placeholder="t('RecipeManagement.RecipeConfig.manualDialogRemarkPlaceholder')"
clearable
type="textarea"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="manualDialogVisible = false"> </el-button>
<el-button type="primary" :disabled="manualDialogLoading" @click="submitManualDialog"> </el-button>
<el-button @click="manualDialogVisible = false">
{{ t('RecipeManagement.RecipeConfig.manualDialogCancelButton') }}
</el-button>
<el-button type="primary" :disabled="manualDialogLoading" @click="submitManualDialog">
{{ t('RecipeManagement.RecipeConfig.manualDialogSaveButton') }}
</el-button>
</template>
</Dialog>
</ContentWrap>
@ -167,11 +263,41 @@ const manualForm = reactive({
remark: '' as string | undefined
})
const manualRules = reactive({
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
max: [{ required: true, message: '上限不能为空', trigger: 'blur' }],
min: [{ required: true, message: '下限不能为空', trigger: 'blur' }],
dataType: [{ required: true, message: '数据类型不能为空', trigger: 'change' }],
dataUnit: [{ required: true, message: '单位不能为空', trigger: 'change' }]
name: [
{
required: true,
message: t('RecipeManagement.RecipeConfig.manualValidatorNameRequired'),
trigger: 'blur'
}
],
max: [
{
required: true,
message: t('RecipeManagement.RecipeConfig.manualValidatorMaxRequired'),
trigger: 'blur'
}
],
min: [
{
required: true,
message: t('RecipeManagement.RecipeConfig.manualValidatorMinRequired'),
trigger: 'blur'
}
],
dataType: [
{
required: true,
message: t('RecipeManagement.RecipeConfig.manualValidatorDataTypeRequired'),
trigger: 'change'
}
],
dataUnit: [
{
required: true,
message: t('RecipeManagement.RecipeConfig.manualValidatorDataUnitRequired'),
trigger: 'change'
}
]
})
const dataTypeDictOptions = computed(() => getStrDictOptions('iot_device_data_type'))
@ -330,3 +456,9 @@ const refresh = async () => {
defineExpose({ refresh })
</script>
<style scoped>
.recipe-config-manual-dialog-form :deep(.el-form-item__label) {
min-width: 90px;
}
</style>

@ -1,34 +1,56 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="配方编码" prop="recipeCode">
<el-form
class="-mb-15px recipe-config-filter-form"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="auto"
>
<el-form-item :label="t('RecipeManagement.RecipeConfig.searchRecipeCodeLabel')" prop="recipeCode">
<el-input
v-model="queryParams.recipeCode" placeholder="请输入配方编码" clearable @keyup.enter="handleQuery"
class="!w-240px" />
v-model="queryParams.recipeCode"
:placeholder="t('RecipeManagement.RecipeConfig.searchRecipeCodePlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="配方名称" prop="name">
<el-form-item :label="t('RecipeManagement.RecipeConfig.searchNameLabel')" prop="name">
<el-input
v-model="queryParams.name" placeholder="请输入配方名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
v-model="queryParams.name"
:placeholder="t('RecipeManagement.RecipeConfig.searchNamePlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品名称" prop="productName">
<el-form-item :label="t('RecipeManagement.RecipeConfig.searchProductNameLabel')" prop="productName">
<el-input
v-model="queryParams.productName" placeholder="请输入产品名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
v-model="queryParams.productName"
:placeholder="t('RecipeManagement.RecipeConfig.searchProductNamePlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 查询
<Icon icon="ep:search" class="mr-5px" />
{{ t('RecipeManagement.RecipeConfig.searchButtonText') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
<Icon icon="ep:refresh" class="mr-5px" />
{{ t('RecipeManagement.RecipeConfig.resetButtonText') }}
</el-button>
<el-button type="primary" plain @click="openDialog('create')">
<Icon icon="ep:plus" class="mr-5px" /> 新增
<Icon icon="ep:plus" class="mr-5px" />
{{ t('RecipeManagement.RecipeConfig.createButtonText') }}
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading">
<Icon icon="ep:download" class="mr-5px" /> 导出
<Icon icon="ep:download" class="mr-5px" />
{{ t('RecipeManagement.RecipeConfig.exportButtonText') }}
</el-button>
</el-form-item>
</el-form>
@ -36,24 +58,67 @@ v-model="queryParams.productName" placeholder="请输入产品名称" clearable
<ContentWrap>
<el-table
ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id"
highlight-current-row @selection-change="handleSelectionChange" @row-click="handleRowClick">
ref="tableRef"
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
highlight-current-row
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column type="selection" width="55" reserve-selection />
<el-table-column label="配方编码" align="center" prop="recipeCode" />
<el-table-column label="配方名称" align="center" prop="name" />
<el-table-column label="配方类型" align="center" prop="recipeType">
<el-table-column
:label="t('RecipeManagement.RecipeConfig.tableRecipeCodeColumn')"
align="center"
prop="recipeCode"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.tableNameColumn')"
align="center"
prop="name"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.tableRecipeTypeColumn')"
align="center"
prop="recipeType"
>
<template #default="scope">
{{ getRecipeTypeLabel(scope.row.recipeType) }}
</template>
</el-table-column>
<el-table-column label="关联产品" align="center" prop="productName" />
<el-table-column label="关联设备" align="center" prop="machineName" />
<el-table-column label="配方描述" align="center" prop="recipeDesc" />
<el-table-column label="操作" align="center" width="240px" fixed="right">
<el-table-column
:label="t('RecipeManagement.RecipeConfig.tableProductNameColumn')"
align="center"
prop="productName"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.tableMachineNameColumn')"
align="center"
prop="machineName"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.tableRecipeDescColumn')"
align="center"
prop="recipeDesc"
/>
<el-table-column
:label="t('RecipeManagement.RecipeConfig.tableOperateColumn')"
align="center"
width="240px"
fixed="right"
>
<template #default="scope">
<el-button link type="primary" @click.stop="openDetail(scope.row)">配置</el-button>
<el-button link type="primary" @click.stop="openDialog('update', scope.row)">编辑</el-button>
<el-button link type="danger" @click.stop="handleDelete(scope.row)">删除</el-button>
<el-button link type="primary" @click.stop="openDetail(scope.row)">
{{ t('RecipeManagement.RecipeConfig.tableConfigAction') }}
</el-button>
<el-button link type="primary" @click.stop="openDialog('update', scope.row)">
{{ t('RecipeManagement.RecipeConfig.tableEditAction') }}
</el-button>
<el-button link type="danger" @click.stop="handleDelete(scope.row)">
{{ t('RecipeManagement.RecipeConfig.tableDeleteAction') }}
</el-button>
</template>
</el-table-column>
</el-table>
@ -68,54 +133,97 @@ ref="detailRef" :visible="detailVisible"
:recipe-code="detailMeta.recipeCode" :name="detailMeta.name" @config="handleDetailConfig" @close="closeDetail" />
<Dialog :title="dialogTitle" v-model="dialogVisible" width="720px">
<el-form ref="dialogFormRef" :model="dialogForm" :rules="dialogRules" label-width="100px" v-loading="dialogLoading">
<el-form-item label="配方编码" prop="recipeCode">
<el-input v-model="dialogForm.recipeCode" placeholder="请输入配方编码" clearable />
<el-form
ref="dialogFormRef"
:model="dialogForm"
:rules="dialogRules"
class="recipe-config-dialog-form"
label-width="auto"
v-loading="dialogLoading"
>
<el-form-item :label="t('RecipeManagement.RecipeConfig.dialogRecipeCodeLabel')" prop="recipeCode">
<el-input
v-model="dialogForm.recipeCode"
:placeholder="t('RecipeManagement.RecipeConfig.dialogRecipeCodePlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="配方名称" prop="name">
<el-input v-model="dialogForm.name" placeholder="请输入配方名称" clearable />
<el-form-item :label="t('RecipeManagement.RecipeConfig.dialogNameLabel')" prop="name">
<el-input
v-model="dialogForm.name"
:placeholder="t('RecipeManagement.RecipeConfig.dialogNamePlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="配方类型" prop="recipeType">
<el-form-item :label="t('RecipeManagement.RecipeConfig.dialogRecipeTypeLabel')" prop="recipeType">
<el-select
v-model="dialogForm.recipeType" placeholder="请选择配方类型" clearable filterable class="!w-full"
:loading="recipeTypeLoading">
v-model="dialogForm.recipeType"
:placeholder="t('RecipeManagement.RecipeConfig.dialogRecipeTypePlaceholder')"
clearable
filterable
class="!w-full"
:loading="recipeTypeLoading"
>
<el-option v-for="item in recipeTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="关联产品" prop="productName">
<el-form-item :label="t('RecipeManagement.RecipeConfig.dialogProductNameLabel')" prop="productName">
<el-select
v-model="dialogForm.productName" placeholder="请选择关联产品" clearable filterable class="!w-full"
:loading="productLoading">
v-model="dialogForm.productName"
:placeholder="t('RecipeManagement.RecipeConfig.dialogProductNamePlaceholder')"
clearable
filterable
class="!w-full"
:loading="productLoading"
>
<el-option v-for="item in productOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="关联设备" prop="machineName">
<el-form-item :label="t('RecipeManagement.RecipeConfig.dialogMachineNameLabel')" prop="machineName">
<el-select
v-model="dialogForm.machineName" placeholder="请选择关联设备" clearable filterable class="!w-full"
:loading="deviceLoading">
v-model="dialogForm.machineName"
:placeholder="t('RecipeManagement.RecipeConfig.dialogMachineNamePlaceholder')"
clearable
filterable
class="!w-full"
:loading="deviceLoading"
>
<el-option v-for="item in deviceOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="配方描述" prop="recipeDesc">
<el-input v-model="dialogForm.recipeDesc" placeholder="请输入配方描述" clearable type="textarea" />
<el-form-item :label="t('RecipeManagement.RecipeConfig.dialogRecipeDescLabel')" prop="recipeDesc">
<el-input
v-model="dialogForm.recipeDesc"
:placeholder="t('RecipeManagement.RecipeConfig.dialogRecipeDescPlaceholder')"
clearable
type="textarea"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitDialog" :disabled="dialogLoading"> </el-button>
<el-button @click="dialogVisible = false">
{{ t('RecipeManagement.RecipeConfig.dialogCancelButton') }}
</el-button>
<el-button type="primary" @click="submitDialog" :disabled="dialogLoading">
{{ t('RecipeManagement.RecipeConfig.dialogSaveButton') }}
</el-button>
</template>
</Dialog>
<Dialog title="配置" v-model="configVisible" width="920px">
<Dialog :title="t('RecipeManagement.RecipeConfig.configDialogTitle')" v-model="configVisible" width="920px">
<div v-loading="configLoading">
<div class="formula-config-picklist">
<div class="formula-config-panel">
<div class="formula-config-panel__header">
<div>来源</div>
<div>{{ t('RecipeManagement.RecipeConfig.configSourceTitle') }}</div>
<div class="formula-config-panel__meta">{{ filteredSourceItems.length }}</div>
</div>
<div class="formula-config-panel__filter">
<el-input v-model="sourceKeyword" placeholder="筛选" clearable />
<el-input
v-model="sourceKeyword"
:placeholder="t('RecipeManagement.RecipeConfig.configFilterPlaceholder')"
clearable
/>
</div>
<el-table
class="formula-config-panel__table"
@ -133,20 +241,24 @@ v-model="dialogForm.machineName" placeholder="请选择关联设备" clearable f
<div class="formula-config-actions">
<el-button type="primary" :disabled="!sourceCheckedKeys.length" @click="addToTarget">
&gt;&gt;
{{ t('RecipeManagement.RecipeConfig.configMoveToTargetButton') }}
</el-button>
<el-button :disabled="!targetCheckedKeys.length" @click="removeFromTarget">
&lt;&lt;
{{ t('RecipeManagement.RecipeConfig.configMoveToSourceButton') }}
</el-button>
</div>
<div class="formula-config-panel">
<div class="formula-config-panel__header">
<div>目标</div>
<div>{{ t('RecipeManagement.RecipeConfig.configTargetTitle') }}</div>
<div class="formula-config-panel__meta">{{ filteredTargetItems.length }}</div>
</div>
<div class="formula-config-panel__filter">
<el-input v-model="targetKeyword" placeholder="筛选" clearable />
<el-input
v-model="targetKeyword"
:placeholder="t('RecipeManagement.RecipeConfig.configFilterPlaceholder')"
clearable
/>
</div>
<el-table
class="formula-config-panel__table"
@ -163,8 +275,12 @@ v-model="dialogForm.machineName" placeholder="请选择关联设备" clearable f
</div>
</div>
<template #footer>
<el-button @click="configVisible = false"> </el-button>
<el-button type="primary" @click="submitConfig" :disabled="configLoading"> </el-button>
<el-button @click="configVisible = false">
{{ t('RecipeManagement.RecipeConfig.configCancelButton') }}
</el-button>
<el-button type="primary" @click="submitConfig" :disabled="configLoading">
{{ t('RecipeManagement.RecipeConfig.configSaveButton') }}
</el-button>
</template>
</Dialog>
</template>
@ -243,14 +359,14 @@ const handlePagination = () => {
const handleExport = async () => {
if (!selectedIds.value.length) {
message.error('请选择需要导出的数据')
message.error(t('RecipeManagement.RecipeConfig.exportNoSelectionMessage'))
return
}
try {
await message.exportConfirm()
exportLoading.value = true
const data = await RecipeConfigApi.exportRecipeConfig({ ids: selectedIds.value.join(',') })
download.excel(data, '配方配置.xls')
download.excel(data, t('RecipeManagement.RecipeConfig.exportFileName'))
} catch {
} finally {
exportLoading.value = false
@ -316,7 +432,11 @@ const ensureOptionsLoaded = async () => {
type DialogMode = 'create' | 'update'
const dialogVisible = ref(false)
const dialogMode = ref<DialogMode>('create')
const dialogTitle = computed(() => (dialogMode.value === 'create' ? '新增配方配置' : '编辑配方配置'))
const dialogTitle = computed(() =>
dialogMode.value === 'create'
? t('RecipeManagement.RecipeConfig.dialogCreateTitle')
: t('RecipeManagement.RecipeConfig.dialogEditTitle')
)
const dialogFormRef = ref()
const dialogLoading = ref(false)
const dialogForm = reactive({
@ -330,8 +450,20 @@ const dialogForm = reactive({
})
const dialogRules = reactive({
recipeCode: [{ required: true, message: '配方编码不能为空', trigger: 'blur' }],
name: [{ required: true, message: '配方名称不能为空', trigger: 'blur' }]
recipeCode: [
{
required: true,
message: t('RecipeManagement.RecipeConfig.validatorRecipeCodeRequired'),
trigger: 'blur'
}
],
name: [
{
required: true,
message: t('RecipeManagement.RecipeConfig.validatorNameRequired'),
trigger: 'blur'
}
]
})
const openDialog = async (mode: DialogMode, row?: RecipeConfigVO) => {
@ -416,7 +548,7 @@ const handleDetailConfig = () => {
const handleRowClick = async (row: RecipeConfigVO, column: any) => {
if (column?.type === 'selection') return
if (column?.label === '操作') return
if (column?.label === t('RecipeManagement.RecipeConfig.tableOperateColumn')) return
await openDetail(row)
}
@ -445,7 +577,7 @@ const configDeviceLabel = computed(() => {
const name = detailMeta.machineName?.trim()
if (name) return name
if (detailMeta.deviceId !== undefined && detailMeta.deviceId !== null) return String(detailMeta.deviceId)
return '-'
return t('RecipeManagement.RecipeConfig.configDeviceLabelFallback')
})
const normalizeKey = (value: any): number | undefined => {
@ -588,6 +720,14 @@ onMounted(() => {
</script>
<style scoped>
.recipe-config-filter-form :deep(.el-form-item__label) {
min-width: 68px;
}
.recipe-config-dialog-form :deep(.el-form-item__label) {
min-width: 100px;
}
.formula-config-picklist {
display: flex;
width: 100%;

@ -1,13 +1,33 @@
<template>
<el-tabs v-model="activeTab">
<el-tab-pane label="设备数据" name="detail">
<el-tab-pane :label="t('RecipeManagement.RecipeLibrary.detailTabDeviceDataLabel')" name="detail">
<el-table :data="detailList" :stripe="true" :show-overflow-tooltip="true" row-key="key">
<!-- <el-table-column type="index" label="序号" align="center" width="70" /> -->
<el-table-column label="点位名称" align="center" prop="attributeName" min-width="180" />
<el-table-column label="数据类型" align="center" prop="dataType" min-width="180" />
<!-- <el-table-column label="地址" align="center" prop="address" min-width="180" /> -->
<el-table-column label="单位" align="center" prop="dataUnit" width="120" />
<el-table-column label="采集值" align="center" prop="value" min-width="180" />
<!-- <el-table-column type="index" :label="t('RecipeManagement.RecipeLibrary.detailIndexColumn')" align="center" width="70" /> -->
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.detailDevicePointNameColumn')"
align="center"
prop="attributeName"
min-width="180"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.detailDeviceDataTypeColumn')"
align="center"
prop="dataType"
min-width="180"
/>
<!-- <el-table-column :label="t('RecipeManagement.RecipeLibrary.detailDeviceAddressColumn')" align="center" prop="address" min-width="180" /> -->
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.detailDeviceDataUnitColumn')"
align="center"
prop="dataUnit"
width="120"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.detailDeviceValueColumn')"
align="center"
prop="value"
min-width="180"
/>
</el-table>
<Pagination
:total="to"
@ -16,7 +36,7 @@
@pagination="getList"
/>
</el-tab-pane>
<el-tab-pane label="手动录入参数" name="manual">
<el-tab-pane :label="t('RecipeManagement.RecipeLibrary.detailTabManualLabel')" name="manual">
<!-- <el-form
class="-mb-15px"
:model="queryParams"
@ -70,12 +90,37 @@
</el-form-item>
</el-form> -->
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id">
<!-- <el-table-column type="index" label="序号" align="center" width="70" /> -->
<el-table-column label="名称" align="center" prop="name" min-width="140" />
<el-table-column label="数据类型" align="center" prop="dataType" width="140" />
<el-table-column label="单位" align="center" prop="dataUnit" width="140" />
<el-table-column label="参考值" align="center" prop="refer" min-width="160" />
<el-table-column label="备注" align="center" prop="remark" min-width="180" />
<!-- <el-table-column type="index" :label="t('RecipeManagement.RecipeLibrary.detailIndexColumn')" align="center" width="70" /> -->
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.manualTableNameColumn')"
align="center"
prop="name"
min-width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.manualTableDataTypeColumn')"
align="center"
prop="dataType"
width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.manualTableDataUnitColumn')"
align="center"
prop="dataUnit"
width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.manualTableReferColumn')"
align="center"
prop="refer"
min-width="160"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.manualTableRemarkColumn')"
align="center"
prop="remark"
min-width="180"
/>
</el-table>
<Pagination
:total="total"
@ -93,6 +138,8 @@ import { RecipeDeviceRecordApi } from '@/api/iot/recipeDeviceRecord'
defineOptions({ name: 'FormulaLibraryDetailTabs' })
const { t } = useI18n()
const props = defineProps({
recipeId: {
type: [String, Number],

@ -2,17 +2,56 @@
<Dialog v-model="visible" :title="title" width="920px">
<div class="formula-library-read-content">
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id">
<!-- <el-table-column type="index" label="序号" align="center" width="70" /> -->
<el-table-column label="名称" align="center" prop="name" min-width="160" />
<!-- <el-table-column label="参考值" align="center" prop="refer" min-width="160" /> -->
<el-table-column label="数据类型" align="center" prop="dataType" width="140" />
<el-table-column label="单位" align="center" prop="dataUnit" width="140" />
<el-table-column label="上限" align="center" prop="max" width="140" />
<el-table-column label="下限" align="center" prop="min" width="140" />
<el-table-column label="备注" align="center" prop="remark" min-width="180" />
<el-table-column label="采集值" align="center" min-width="160" fixed="right" prop="refer">
<!-- <el-table-column type="index" :label="t('RecipeManagement.RecipeLibrary.tableIndexColumn')" align="center" width="70" /> -->
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.readDialogNameColumn')"
align="center"
prop="name"
min-width="160"
/>
<!-- <el-table-column :label="t('RecipeManagement.RecipeLibrary.readDialogReferColumn')" align="center" prop="refer" min-width="160" /> -->
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.readDialogDataTypeColumn')"
align="center"
prop="dataType"
width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.readDialogDataUnitColumn')"
align="center"
prop="dataUnit"
width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.readDialogMaxColumn')"
align="center"
prop="max"
width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.readDialogMinColumn')"
align="center"
prop="min"
width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.readDialogRemarkColumn')"
align="center"
prop="remark"
min-width="180"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.readDialogReferColumn')"
align="center"
min-width="160"
fixed="right"
prop="refer"
>
<template #default="{ row }">
<el-input v-model="row.refer" placeholder="请输入采集值" />
<el-input
v-model="row.refer"
:placeholder="t('RecipeManagement.RecipeLibrary.readDialogReferPlaceholder')"
/>
</template>
</el-table-column>
</el-table>
@ -33,8 +72,12 @@
</div>
<template #footer>
<el-button @click="submitForm" type="primary"> </el-button>
<el-button @click="visible = false"> </el-button>
<el-button @click="submitForm" type="primary">
{{ t('RecipeManagement.RecipeLibrary.readDialogSubmitButtonText') }}
</el-button>
<el-button @click="visible = false">
{{ t('RecipeManagement.RecipeLibrary.readDialogCancelButton') }}
</el-button>
</template>
</Dialog>
</template>
@ -49,7 +92,7 @@ defineOptions({ name: 'FormulaLibraryReadDialog' })
type PageResult<T> = { list: T[]; total: number }
const visible = ref(false)
const title = ref('读取')
const title = ref('')
const loading = ref(false)
const recipeId = ref<string | number | undefined>(undefined)
@ -106,7 +149,8 @@ const open = async (options: {
visible.value = true
formulaLibraryId.value = options.id
recipeId.value = options.recipeId
title.value = options.recipeName ? `读取-${options.recipeName}` : '读取'
const baseTitle = t('RecipeManagement.RecipeLibrary.readDialogTitle')
title.value = options.recipeName ? `${baseTitle}-${options.recipeName}` : baseTitle
queryParams.pageNo = 1
list.value = options.data ?? []
// if (options.initialData) {

@ -1,34 +1,34 @@
<template>
<ContentWrap>
<el-form
class="-mb-15px"
class="-mb-15px recipe-library-filter-form"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="70px"
label-width="auto"
>
<el-form-item label="编码" prop="code">
<el-form-item :label="t('RecipeManagement.RecipeLibrary.searchCodeLabel')" prop="code">
<el-input
v-model="queryParams.code"
placeholder="请输入编码"
:placeholder="t('RecipeManagement.RecipeLibrary.searchCodePlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-form-item :label="t('RecipeManagement.RecipeLibrary.searchNameLabel')" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
:placeholder="t('RecipeManagement.RecipeLibrary.searchNamePlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="配方名称" prop="recipeId">
<el-form-item :label="t('RecipeManagement.RecipeLibrary.searchRecipeLabel')" prop="recipeId">
<el-select
v-model="queryParams.recipeId"
placeholder="请选择配方"
:placeholder="t('RecipeManagement.RecipeLibrary.searchRecipePlaceholder')"
clearable
filterable
class="!w-240px"
@ -41,10 +41,10 @@
/>
</el-select>
</el-form-item>
<el-form-item label="关联计划" prop="planId">
<el-form-item :label="t('RecipeManagement.RecipeLibrary.searchPlanLabel')" prop="planId">
<el-select
v-model="queryParams.planId"
placeholder="请选择关联计划"
:placeholder="t('RecipeManagement.RecipeLibrary.searchPlanPlaceholder')"
clearable
filterable
class="!w-240px"
@ -64,16 +64,20 @@
</el-form-item> -->
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 查询
<Icon icon="ep:search" class="mr-5px" />
{{ t('RecipeManagement.RecipeLibrary.searchButtonText') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
<Icon icon="ep:refresh" class="mr-5px" />
{{ t('RecipeManagement.RecipeLibrary.resetButtonText') }}
</el-button>
<el-button type="primary" plain @click="openDialog('create')">
<Icon icon="ep:plus" class="mr-5px" /> 新增
<Icon icon="ep:plus" class="mr-5px" />
{{ t('RecipeManagement.RecipeLibrary.createButtonText') }}
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading">
<Icon icon="ep:download" class="mr-5px" /> 导出
<Icon icon="ep:download" class="mr-5px" />
{{ t('RecipeManagement.RecipeLibrary.exportButtonText') }}
</el-button>
</el-form-item>
</el-form>
@ -89,31 +93,73 @@
highlight-current-row
@row-click="handleRowClick"
>
<el-table-column label="编码" align="center" prop="code" min-width="140" />
<el-table-column label="名称" align="center" prop="name" min-width="140" />
<el-table-column label="配方名称" align="center" prop="recipeName" min-width="160">
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.tableCodeColumn')"
align="center"
prop="code"
min-width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.tableNameColumn')"
align="center"
prop="name"
min-width="140"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.tableRecipeNameColumn')"
align="center"
prop="recipeName"
min-width="160"
>
<template #default="scope">
<span>{{ scope.row.recipeName ?? '-' }}</span>
</template>
</el-table-column>
<el-table-column label="关联计划" align="center" prop="planCode" min-width="160">
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.tablePlanCodeColumn')"
align="center"
prop="planCode"
min-width="160"
>
<template #default="scope">
<span>{{ scope.row.planCode ?? '-' }}</span>
</template>
</el-table-column>
<el-table-column label="创建人" align="center" prop="creator" width="120" />
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180" />
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.tableCreatorColumn')"
align="center"
prop="creator"
width="120"
/>
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.tableCreateTimeColumn')"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180"
/>
<!-- <el-table-column label="来源" align="center" prop="source" width="120">
<template #default="scope">
<el-tag v-if="scope.row.source" :type="getSourceTagType(scope.row.source)">{{ scope.row.source }}</el-tag>
<span v-else>-</span>
</template>
</el-table-column> -->
<el-table-column label="操作" align="center" width="180" fixed="right">
<el-table-column
:label="t('RecipeManagement.RecipeLibrary.tableOperateColumn')"
align="center"
width="180"
fixed="right"
>
<template #default="scope">
<el-button link type="primary" @click.stop="handleRead(scope.row)">读取</el-button>
<el-button link type="primary" @click.stop="openDialog('update', scope.row)">编辑</el-button>
<el-button link type="danger" @click.stop="handleDelete(scope.row)">删除</el-button>
<el-button link type="primary" @click.stop="handleRead(scope.row)">
{{ t('RecipeManagement.RecipeLibrary.tableReadAction') }}
</el-button>
<el-button link type="primary" @click.stop="openDialog('update', scope.row)">
{{ t('RecipeManagement.RecipeLibrary.tableEditAction') }}
</el-button>
<el-button link type="danger" @click.stop="handleDelete(scope.row)">
{{ t('RecipeManagement.RecipeLibrary.tableDeleteAction') }}
</el-button>
</template>
</el-table-column>
</el-table>
@ -133,32 +179,73 @@
<FormulaLibraryReadDialog ref="readDialogRef" />
<Dialog :title="dialogTitle" v-model="dialogVisible" width="720px">
<el-form ref="dialogFormRef" :model="dialogForm" :rules="dialogRules" label-width="100px" v-loading="dialogLoading">
<el-form-item label="编码" prop="code">
<el-input v-model="dialogForm.code" placeholder="请输入编码" clearable />
<el-form
ref="dialogFormRef"
:model="dialogForm"
:rules="dialogRules"
class="recipe-library-dialog-form"
label-width="auto"
v-loading="dialogLoading"
>
<el-form-item :label="t('RecipeManagement.RecipeLibrary.dialogCodeLabel')" prop="code">
<el-input
v-model="dialogForm.code"
:placeholder="t('RecipeManagement.RecipeLibrary.dialogCodePlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="dialogForm.name" placeholder="请输入名称" clearable />
<el-form-item :label="t('RecipeManagement.RecipeLibrary.dialogNameLabel')" prop="name">
<el-input
v-model="dialogForm.name"
:placeholder="t('RecipeManagement.RecipeLibrary.dialogNamePlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="配方" prop="recipeId">
<el-select v-model="dialogForm.recipeId" placeholder="请选择配方" clearable filterable class="!w-full">
<el-form-item :label="t('RecipeManagement.RecipeLibrary.dialogRecipeLabel')" prop="recipeId">
<el-select
v-model="dialogForm.recipeId"
:placeholder="t('RecipeManagement.RecipeLibrary.dialogRecipePlaceholder')"
clearable
filterable
class="!w-full"
>
<el-option v-for="opt in recipeOptions" :key="String(opt.value)" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>
<el-form-item label="关联计划" prop="planId">
<el-select v-model="dialogForm.planId" placeholder="请选择关联计划" clearable filterable class="!w-full">
<el-form-item :label="t('RecipeManagement.RecipeLibrary.dialogPlanLabel')" prop="planId">
<el-select
v-model="dialogForm.planId"
:placeholder="t('RecipeManagement.RecipeLibrary.dialogPlanPlaceholder')"
clearable
filterable
class="!w-full"
>
<el-option v-for="opt in planOptions" :key="String(opt.value)" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>
<el-form-item label="来源" prop="source">
<el-select v-model="dialogForm.source" placeholder="请选择来源" clearable class="!w-full">
<el-option v-for="opt in sourceOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
<el-form-item :label="t('RecipeManagement.RecipeLibrary.dialogSourceLabel')" prop="source">
<el-select
v-model="dialogForm.source"
:placeholder="t('RecipeManagement.RecipeLibrary.dialogSourcePlaceholder')"
clearable
class="!w-full"
>
<el-option
v-for="opt in sourceOptions"
:key="opt.value"
:label="getSourceLabel(opt.value)"
:value="opt.value"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitDialog" :disabled="dialogLoading"> </el-button>
<el-button @click="dialogVisible = false">
{{ t('RecipeManagement.RecipeLibrary.dialogCancelButton') }}
</el-button>
<el-button type="primary" @click="submitDialog" :disabled="dialogLoading">
{{ t('RecipeManagement.RecipeLibrary.dialogSaveButton') }}
</el-button>
</template>
</Dialog>
</template>
@ -270,7 +357,7 @@ const handleExport = async () => {
await message.exportConfirm()
exportLoading.value = true
const data = await RecipePlanDetailApi.exportRecipePlanDetail(buildQueryParams())
download.excel(data, '配方库.xls')
download.excel(data, t('RecipeManagement.RecipeLibrary.exportFileName'))
} catch {
} finally {
exportLoading.value = false
@ -294,6 +381,12 @@ const getSourceTagType = (source: string) => {
return 'info'
}
const getSourceLabel = (value: string) => {
if (value === '新增') return t('RecipeManagement.RecipeLibrary.sourceOptionNewLabel')
if (value === '生产中') return t('RecipeManagement.RecipeLibrary.sourceOptionProducingLabel')
return value
}
const dialogVisible = ref(false)
const dialogTitle = ref('')
const dialogLoading = ref(false)
@ -311,10 +404,18 @@ const dialogForm = ref<RecipePlanDetailVO>({
})
const dialogRules = reactive({
code: [{ required: true, message: '编码不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
recipeId: [{ required: true, message: '关联配方不能为空', trigger: 'change' }],
planId: [{ required: true, message: '关联计划不能为空', trigger: 'change' }]
code: [
{ required: true, message: t('RecipeManagement.RecipeLibrary.validatorCodeRequired'), trigger: 'blur' }
],
name: [
{ required: true, message: t('RecipeManagement.RecipeLibrary.validatorNameRequired'), trigger: 'blur' }
],
recipeId: [
{ required: true, message: t('RecipeManagement.RecipeLibrary.validatorRecipeRequired'), trigger: 'change' }
],
planId: [
{ required: true, message: t('RecipeManagement.RecipeLibrary.validatorPlanRequired'), trigger: 'change' }
]
})
const resetDialogForm = () => {
@ -356,7 +457,7 @@ const handleRead = async (row: RecipePlanDetailVO) => {
const recipeName = row?.recipeName
const data = await RecipePointApi.getRecipePointList(Number(recipeId))
if (!data?.length) {
await message.confirm('是否读取设备数据?')
await message.confirm(t('RecipeManagement.RecipeLibrary.readDeviceConfirmMessage'))
if (id != null) {
await RecipeDeviceRecordApi.createRecipeDeviceRecordBatch(id)
message.success(t('common.createSuccess'))
@ -397,3 +498,13 @@ onMounted(async () => {
await getList()
})
</script>
<style scoped>
.recipe-library-filter-form :deep(.el-form-item__label) {
min-width: 68px;
}
.recipe-library-dialog-form :deep(.el-form-item__label) {
min-width: 100px;
}
</style>

@ -1,25 +1,25 @@
<template>
<ContentWrap>
<el-form
class="-mb-15px"
class="-mb-15px recipe-type-filter-form"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
label-width="auto"
>
<el-form-item label="名称" prop="name">
<el-form-item :label="t('RecipeManagement.RecipeType.searchNameLabel')" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
:placeholder="t('RecipeManagement.RecipeType.searchNamePlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="工序" prop="process">
<el-form-item :label="t('RecipeManagement.RecipeType.searchProcessLabel')" prop="process">
<el-select
v-model="queryParams.process"
placeholder="请选择工序"
:placeholder="t('RecipeManagement.RecipeType.searchProcessPlaceholder')"
clearable
class="!w-240px"
@change="handleQuery"
@ -32,15 +32,22 @@
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 查询</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" />
{{ t('RecipeManagement.RecipeType.searchButtonText') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" />
{{ t('RecipeManagement.RecipeType.resetButtonText') }}
</el-button>
<el-button type="primary" plain @click="openDialog('create')">
<Icon icon="ep:plus" class="mr-5px" /> 新增
<Icon icon="ep:plus" class="mr-5px" />
{{ t('RecipeManagement.RecipeType.createButtonText') }}
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading">
<Icon icon="ep:download" class="mr-5px" /> 导出
<Icon icon="ep:download" class="mr-5px" />
{{ t('RecipeManagement.RecipeType.exportButtonText') }}
</el-button>
</el-form-item>
</el-form>
@ -57,17 +64,38 @@
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" reserve-selection />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="工序" align="center" prop="process">
<el-table-column
:label="t('RecipeManagement.RecipeType.tableNameColumn')"
align="center"
prop="name"
/>
<el-table-column
:label="t('RecipeManagement.RecipeType.tableProcessColumn')"
align="center"
prop="process"
>
<template #default="scope">
{{ getProcessLabel(scope.row.process) }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" width="160px" fixed="right">
<el-table-column
:label="t('RecipeManagement.RecipeType.tableRemarkColumn')"
align="center"
prop="remark"
/>
<el-table-column
:label="t('RecipeManagement.RecipeType.tableOperateColumn')"
align="center"
width="160px"
fixed="right"
>
<template #default="scope">
<el-button link type="primary" @click="openDialog('update', scope.row)">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)"></el-button>
<el-button link type="primary" @click="openDialog('update', scope.row)">
{{ t('RecipeManagement.RecipeType.tableEditAction') }}
</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">
{{ t('RecipeManagement.RecipeType.tableDeleteAction') }}
</el-button>
</template>
</el-table-column>
</el-table>
@ -84,14 +112,24 @@
ref="dialogFormRef"
:model="dialogForm"
:rules="dialogRules"
label-width="100px"
class="recipe-type-dialog-form"
label-width="auto"
v-loading="dialogLoading"
>
<el-form-item label="名称" prop="name">
<el-input v-model="dialogForm.name" placeholder="请输入名称" clearable />
<el-form-item :label="t('RecipeManagement.RecipeType.dialogNameLabel')" prop="name">
<el-input
v-model="dialogForm.name"
:placeholder="t('RecipeManagement.RecipeType.dialogNamePlaceholder')"
clearable
/>
</el-form-item>
<el-form-item label="工序" prop="process">
<el-select v-model="dialogForm.process" placeholder="请选择工序" clearable class="!w-full">
<el-form-item :label="t('RecipeManagement.RecipeType.dialogProcessLabel')" prop="process">
<el-select
v-model="dialogForm.process"
:placeholder="t('RecipeManagement.RecipeType.dialogProcessPlaceholder')"
clearable
class="!w-full"
>
<el-option
v-for="option in processOptions"
:key="option.value"
@ -100,13 +138,22 @@
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="dialogForm.remark" placeholder="请输入备注" clearable type="textarea" />
<el-form-item :label="t('RecipeManagement.RecipeType.dialogRemarkLabel')" prop="remark">
<el-input
v-model="dialogForm.remark"
:placeholder="t('RecipeManagement.RecipeType.dialogRemarkPlaceholder')"
clearable
type="textarea"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitDialog" :disabled="dialogLoading"> </el-button>
<el-button @click="dialogVisible = false">
{{ t('RecipeManagement.RecipeType.dialogCancelButton') }}
</el-button>
<el-button type="primary" @click="submitDialog" :disabled="dialogLoading">
{{ t('RecipeManagement.RecipeType.dialogSaveButton') }}
</el-button>
</template>
</Dialog>
</template>
@ -199,14 +246,14 @@ const handlePagination = () => {
const handleExport = async () => {
if (!selectedIds.value.length) {
message.error('请选择需要导出的数据')
message.error(t('RecipeManagement.RecipeType.exportNoSelectionMessage'))
return
}
try {
await message.exportConfirm()
exportLoading.value = true
const data = await RecipeApi.exportRecipe({ ids: selectedIds.value.join(',') })
download.excel(data, '配方类型.xls')
download.excel(data, t('RecipeManagement.RecipeType.exportFileName'))
} catch {
} finally {
exportLoading.value = false
@ -217,7 +264,11 @@ type DialogMode = 'create' | 'update'
const dialogVisible = ref(false)
const dialogMode = ref<DialogMode>('create')
const dialogTitle = computed(() => (dialogMode.value === 'create' ? '新增配方类型' : '编辑配方类型'))
const dialogTitle = computed(() =>
dialogMode.value === 'create'
? t('RecipeManagement.RecipeType.dialogCreateTitle')
: t('RecipeManagement.RecipeType.dialogEditTitle')
)
const dialogFormRef = ref()
const dialogLoading = ref(false)
const dialogForm = reactive({
@ -228,8 +279,14 @@ const dialogForm = reactive({
})
const dialogRules = reactive({
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
process: [{ required: true, message: '工序不能为空', trigger: 'change' }]
name: [{ required: true, message: t('RecipeManagement.RecipeType.validatorNameRequired'), trigger: 'blur' }],
process: [
{
required: true,
message: t('RecipeManagement.RecipeType.validatorProcessRequired'),
trigger: 'change'
}
]
})
const openDialog = (mode: DialogMode, row?: RecipeVO) => {
@ -291,3 +348,13 @@ onMounted(() => {
getList()
})
</script>
<style scoped>
.recipe-type-filter-form :deep(.el-form-item__label) {
min-width: 68px;
}
.recipe-type-dialog-form :deep(.el-form-item__label) {
min-width: 100px;
}
</style>

Loading…
Cancel
Save