Files
klp-oa/klp-ui/src/views/mes/qc/template/index.vue
砂糖 43dcef4aa9 refactor(mes/qc/template): 替换方案单位输入框为可创建选择器
1. 将搜索区和弹窗中的方案单位输入框改为可创建的下拉选择器
2. 从列表数据中提取已有的方案单位作为选项
3. 重置查询时不再重置页码
4. 移除冗余的分页组件展示逻辑
2026-05-13 10:37:38 +08:00

566 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-row :gutter="20">
<el-col :span="8">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
label-width="60px">
<el-form-item label="方案名称" prop="templateName">
<el-input v-model="queryParams.templateName" placeholder="请输入方案名称" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="方案单位" prop="templateUnit">
<el-select v-model="queryParams.templateUnit" placeholder="请选择方案单位" clearable filterable allow-create @keyup.enter.native="handleQuery">
<el-option v-for="unit in templateUnitOptions" :key="unit" :label="unit" :value="unit" />
</el-select>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
</el-col>
</el-row>
<div class="template-list" v-loading="loading">
<div
v-for="item in inspectionItemTemplateList"
:key="item.templateId"
class="template-item"
:class="{ 'active': currentTemplate && currentTemplate.templateId === item.templateId }"
@click="handleRowClick(item)"
>
<div class="template-item-header">
<span class="template-item-title">{{ item.templateName }}</span>
<div class="template-item-actions">
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleUpdate(item)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleDelete(item)">删除</el-button>
</div>
</div>
<div class="template-item-meta">
<span class="template-unit">所属单位{{ item.templateUnit || '-' }}</span>
</div>
<div v-if="item.templateDesc" class="template-item-desc">{{ item.templateDesc }}</div>
</div>
<el-empty v-if="inspectionItemTemplateList.length === 0" description="暂无数据" :image-size="100" />
</div>
<!-- 添加或修改待检项方案对话框 -->
<el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="方案名称" prop="templateName">
<el-input v-model="form.templateName" placeholder="请输入方案名称" />
</el-form-item>
<el-form-item label="方案单位" prop="templateUnit">
<el-select v-model="form.templateUnit" placeholder="请选择方案单位" filterable allow-create>
<el-option v-for="unit in templateUnitOptions" :key="unit" :label="unit" :value="unit" />
</el-select>
</el-form-item>
<el-form-item label="方案描述" prop="templateDesc">
<el-input v-model="form.templateDesc" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="待检项" prop="inspectionItem">
<CheckItemTransfer v-model="form.inspectionItem" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 添加现有检查项对话框 -->
<el-dialog title="添加现有检查项" :visible.sync="addItemOpen" width="500px" append-to-body>
<el-form ref="addItemForm" :model="addItemForm" label-width="80px">
<el-form-item label="检查项" prop="itemId">
<el-select v-model="addItemForm.itemId" placeholder="请选择检查项" filterable>
<el-option v-for="item in availableCheckItems" :key="item.itemId" :label="item.itemName" :value="item.itemId">
<span>{{ item.itemName }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">
({{ item.qualitativeQuantitative === 0 ? '定性' : '定量' }})
</span>
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitAddItem"> </el-button>
<el-button @click="addItemOpen = false"> </el-button>
</div>
</el-dialog>
<!-- 新建/修改检查项对话框 -->
<el-dialog :title="itemTitle" :visible.sync="itemOpen" width="600px" append-to-body>
<el-form ref="itemForm" :model="itemForm" :rules="itemRules" label-width="100px">
<el-form-item label="检查项名称" prop="itemName">
<el-input v-model="itemForm.itemName" placeholder="请输入检查项名称" />
</el-form-item>
<el-form-item label="标准目标" prop="standardTarget">
<el-input v-model="itemForm.standardTarget" placeholder="请输入标准目标" />
</el-form-item>
<el-form-item label="目标上限" prop="targetUpper">
<el-input v-model="itemForm.targetUpper" placeholder="请输入目标上限" />
</el-form-item>
<el-form-item label="目标下限" prop="targetLower">
<el-input v-model="itemForm.targetLower" placeholder="请输入目标下限" />
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input v-model="itemForm.unit" placeholder="请输入单位" />
</el-form-item>
<el-form-item label="定性定量" prop="qualitativeQuantitative">
<el-radio-group v-model="itemForm.qualitativeQuantitative">
<el-radio :label="0">定性</el-radio>
<el-radio :label="1">定量</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="itemForm.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitItemForm"> </el-button>
<el-button @click="itemOpen = false"> </el-button>
</div>
</el-dialog>
</el-col>
<el-col :span="16" v-loading="rightLoading">
<el-row :gutter="10" class="mb8" v-if="currentTemplate">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAddExistingItem">添加现有检查项</el-button>
<el-button type="success" plain icon="el-icon-plus" size="mini" @click="handleAddNewItem">新建检查项</el-button>
</el-col>
</el-row>
<KLPTable v-if="checkItemList.length > 0" v-loading="loading" :data="checkItemList"
@selection-change="handleSelectionChange">
<el-table-column label="检查项名称" align="center" prop="itemName" />
<el-table-column label="标准目标" align="center" prop="standardTarget" />
<el-table-column label="目标上限" align="center" prop="targetUpper" />
<el-table-column label="目标下限" align="center" prop="targetLower" />
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="定性定量" align="center" prop="qualitativeQuantitative">
<template slot-scope="scope">
{{ scope.row.qualitativeQuantitative === 0 ? '定性' : '定量' }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleEditItem(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDeleteItem(scope.row)">删除</el-button>
</template>
</el-table-column>
</KLPTable>
<el-empty v-else description="暂无数据" />
</el-col>
</el-row>
</div>
</template>
<script>
import { listInspectionItemTemplate, getInspectionItemTemplate, delInspectionItemTemplate, addInspectionItemTemplate, updateInspectionItemTemplate, getInfoByInspectionItem } from "@/api/mes/qc/inspectionItemTemplate";
import { listCheckItem, getCheckItem, addCheckItem, updateCheckItem, delCheckItem } from "@/api/mes/qc/checkItem";
import CheckItemTransfer from '@/components/KLPService/CheckItemSelect/index'
export default {
name: "InspectionItemTemplate",
components: {
CheckItemTransfer,
},
data() {
return {
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 待检项方案表格数据
inspectionItemTemplateList: [],
// 方案单位选项
templateUnitOptions: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
templateName: undefined,
templateUnit: undefined,
templateDesc: undefined,
inspectionItem: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
},
checkItemList: [],
rightLoading: false,
isRowClicking: false,
currentTemplate: null,
addItemOpen: false,
addItemForm: {
itemId: null
},
itemOpen: false,
itemTitle: '',
itemForm: {},
itemRules: {
itemName: [
{ required: true, message: '检查项名称不能为空', trigger: 'blur' }
]
},
availableCheckItems: [],
};
},
created() {
this.getList();
},
methods: {
/** 查询待检项方案列表 */
getList() {
this.loading = true;
listInspectionItemTemplate(this.queryParams).then(response => {
this.inspectionItemTemplateList = response.rows || response.data || response;
const units = [...new Set(this.inspectionItemTemplateList.map(item => item.templateUnit).filter(Boolean))];
this.templateUnitOptions = units.sort();
this.loading = false;
});
},
handleRowClick(row) {
if (this.isRowClicking) {
this.$message.info('正在查看数据,请稍后');
return;
}
this.isRowClicking = true;
this.currentTemplate = row;
this.rightLoading = true;
getInfoByInspectionItem(row.inspectionItem).then(response => {
this.checkItemList = response.data || [];
this.rightLoading = false;
this.isRowClicking = false;
}).catch(() => {
this.rightLoading = false;
this.isRowClicking = false;
});
},
loadAvailableCheckItems() {
listCheckItem({ pageNum: 1, pageSize: 9999 }).then(response => {
const currentItemIds = this.currentTemplate?.inspectionItem ? this.currentTemplate.inspectionItem.split(',').map(id => id.trim()) : [];
this.availableCheckItems = response.rows.filter(item => !currentItemIds.includes(String(item.itemId)));
});
},
handleAddExistingItem() {
this.addItemForm.itemId = null;
this.loadAvailableCheckItems();
this.addItemOpen = true;
},
submitAddItem() {
if (!this.addItemForm.itemId) {
this.$modal.msgError('请选择检查项');
return;
}
const currentItemIds = this.currentTemplate.inspectionItem ? this.currentTemplate.inspectionItem.split(',').filter(id => id.trim()) : [];
currentItemIds.push(this.addItemForm.itemId);
this.currentTemplate.inspectionItem = currentItemIds.join(',');
updateInspectionItemTemplate(this.currentTemplate).then(() => {
this.$modal.msgSuccess('添加成功');
this.addItemOpen = false;
this.handleRowClick(this.currentTemplate);
this.getList();
});
},
handleAddNewItem() {
this.itemForm = {
itemName: undefined,
standardTarget: undefined,
targetUpper: undefined,
targetLower: undefined,
unit: undefined,
qualitativeQuantitative: 0,
remark: undefined
};
this.itemTitle = '新建检查项';
this.itemOpen = true;
},
handleEditItem(row) {
this.itemForm = { ...row };
this.itemTitle = '修改检查项';
this.itemOpen = true;
},
submitItemForm() {
this.$refs['itemForm'].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.itemForm.itemId) {
updateCheckItem(this.itemForm).then(() => {
this.$modal.msgSuccess('修改成功');
this.itemOpen = false;
this.handleRowClick(this.currentTemplate);
}).finally(() => {
this.buttonLoading = false;
});
} else {
addCheckItem(this.itemForm).then(response => {
this.$modal.msgSuccess('新增成功');
const newItemId = response.data || response.msg;
const currentItemIds = this.currentTemplate.inspectionItem ? this.currentTemplate.inspectionItem.split(',').filter(id => id.trim()) : [];
currentItemIds.push(newItemId);
this.currentTemplate.inspectionItem = currentItemIds.join(',');
updateInspectionItemTemplate(this.currentTemplate).then(() => {
this.itemOpen = false;
this.handleRowClick(this.currentTemplate);
this.getList();
});
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
handleDeleteItem(row) {
this.$modal.confirm('是否确认删除检查项"' + row.itemName + '"').then(() => {
return delCheckItem(row.itemId);
}).then(() => {
const currentItemIds = this.currentTemplate.inspectionItem ? this.currentTemplate.inspectionItem.split(',').filter(id => id.trim()) : [];
const newIds = currentItemIds.filter(id => id !== String(row.itemId));
this.currentTemplate.inspectionItem = newIds.join(',');
return updateInspectionItemTemplate(this.currentTemplate);
}).then(() => {
this.handleRowClick(this.currentTemplate);
this.getList();
this.$modal.msgSuccess('删除成功');
}).catch(() => {});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
templateId: undefined,
templateName: undefined,
templateDesc: undefined,
inspectionItem: undefined,
createBy: undefined,
createTime: undefined,
updateBy: undefined,
updateTime: undefined,
delFlag: undefined,
remark: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.templateId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加待检项方案";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
const templateId = row.templateId || this.ids
getInspectionItemTemplate(templateId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改待检项方案";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (!this.form.inspectionItem) {
this.form.inspectionItem = '';
}
if (this.form.templateId != null) {
updateInspectionItemTemplate(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
this.checkItemList = [];
}).finally(() => {
this.buttonLoading = false;
});
} else {
addInspectionItemTemplate(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
this.handleRowClick(this.form);
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const templateIds = row.templateId || this.ids;
this.$modal.confirm('是否确认删除待检项方案编号为"' + templateIds + '"的数据项?').then(() => {
this.loading = true;
return delInspectionItemTemplate(templateIds);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport() {
this.download('qc/inspectionItemTemplate/export', {
...this.queryParams
}, `inspectionItemTemplate_${new Date().getTime()}.xlsx`)
}
}
};
</script>
<style scoped>
.template-list {
height: calc(100vh - 200px);
overflow-y: auto;
padding: 10px;
background: #f5f7fa;
border-radius: 4px;
}
.template-item {
background: #fff;
border: 1px solid #e4e7ed;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.template-item:hover {
border-color: #409eff;
box-shadow: 0 4px 16px rgba(64, 158, 255, 0.15);
transform: translateY(-2px);
}
.template-item.active {
border-color: #409eff;
background: linear-gradient(135deg, #ecf5ff 0%, #f0f7ff 100%);
box-shadow: 0 4px 20px rgba(64, 158, 255, 0.25);
}
.template-item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.template-item-title {
font-size: 16px;
font-weight: 600;
color: #303133;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.template-item-actions {
display: flex;
gap: 8px;
opacity: 0;
transition: opacity 0.3s;
}
.template-item:hover .template-item-actions {
opacity: 1;
}
.template-item.active .template-item-actions {
opacity: 1;
}
.template-item-meta {
font-size: 13px;
color: #67c23a;
margin-top: 8px;
}
.template-unit {
padding: 2px 8px;
background: #f0f9eb;
border-radius: 4px;
}
.template-item-desc {
font-size: 13px;
color: #909399;
line-height: 1.5;
padding-top: 10px;
margin-top: 10px;
border-top: 1px solid #f0f0f0;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
/* 滚动条样式 */
.template-list::-webkit-scrollbar {
width: 6px;
}
.template-list::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.template-list::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.template-list::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
</style>