<template>
|
<div class="list">
|
<TableCustom :queryForm="queryForm" :height="0" :total="total" @currentChange="handleCurrentChange"
|
@sizeChange="handleSizeChange">
|
<template #search>
|
<el-form ref="searchForm" :model="form" :rules="rules" label-width="auto" inline>
|
<el-form-item label="所属项目组:">
|
<el-input v-model="form.teamName" placeholder="请输入"></el-input>
|
</el-form-item>
|
<el-form-item label="检测项名称:">
|
<el-input v-model="form.itemName" placeholder="请输入"></el-input>
|
</el-form-item>
|
<el-form-item label="检测项编号:">
|
<el-input v-model="form.itemCode" placeholder="请输入"></el-input>
|
</el-form-item>
|
<el-form-item label="报告内容:">
|
<el-select v-model="form.reportContent" placeholder="请选择">
|
<el-option label="国家标准" value="1"></el-option>
|
<el-option label="分析方法开发" value="2"></el-option>
|
<el-option label="方法验证报告" value="3"></el-option>
|
<el-option label="方法确认" value="4"></el-option>
|
<el-option label="操作规程" value="5"></el-option>
|
<el-option label="方法转移记录清单" value="6"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="状态:">
|
<el-select v-model="form.status" placeholder="请选择">
|
<el-option label="全部" value=""></el-option>
|
<el-option label="草稿箱" value="-1"></el-option>
|
<el-option label="已提交" value="1"></el-option>
|
<el-option label="待评定" value="2"></el-option>
|
<el-option label="已评定" value="3"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="" style="margin-left: 63px;">
|
<el-button type="default" style="margin-right: 10px;" @click="handleReset">重置</el-button>
|
<el-button type="primary" @click="handleSearch">查询</el-button>
|
</el-form-item>
|
</el-form>
|
</template>
|
<template #setting>
|
<div class="table-setting">
|
<div class="flex a-center">
|
<div class="table-title" :class="{ active: currentType == 'list' }"
|
@click="handleTypeChange('list')">
|
项目检测项、检验包列表
|
</div>
|
<div v-if="isChemist" class="table-tit" :class="{ active: currentType == 'draft' }"
|
@click="handleTypeChange('draft')">
|
草稿箱
|
</div>
|
</div>
|
<el-button v-if="isChemist" @click="handleAddProject" class="el-icon-plus" type="primary">
|
新增检测项</el-button>
|
</div>
|
</template>
|
<template #tableCustom>
|
<Table :data="tableData" :total="total" @row-click="handleRowClick" row-key="id" :height="null"
|
:expand-row-keys="expandRowKeys">
|
<el-table-column type="expand" width="1">
|
<template #default="{ row }">
|
<div v-if="isChemist && currentType !== 'draft'" class="expand-box">
|
<div style="display: flex;align-items: center;">
|
<div class="expand-box-title">报告列表</div>
|
<el-button style="margin-left: 10px;" @click="handleAdd(row)" class="el-icon-plus"
|
type="primary">
|
新增报告
|
</el-button>
|
</div>
|
|
<Table :data="reportList[row.id] || []" :total="0" :height="null">
|
<el-table-column prop="reportContent" label="报告内容">
|
<template #default="{ row }">
|
<span>{{ getReportContentText(row.reportContent) }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column prop="developPerson" label="制订人" />
|
<el-table-column prop="developDate" label="制订日期" />
|
<el-table-column prop="auditPersonId" label="审批人" />
|
<el-table-column prop="auditTime" label="审批时间" />
|
<el-table-column prop="status" label="状态">
|
<template #default="{ row }">
|
<el-tag v-if="row.status == 1" type="info" color="#fff">待审核</el-tag>
|
<el-tag v-if="row.status == 2" type="success" color="#fff">已通过</el-tag>
|
<el-tag v-if="row.status == 3" type="danger">已驳回</el-tag>
|
<el-tag v-if="row.status == 4" type="danger">已撤销</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="age" label="操作">
|
<template #default="{ row }">
|
<template v-if="row.status === 2">
|
<el-button type="text" @click="handleReportDetail(row)">详情</el-button>
|
</template>
|
<template v-else-if="row.status === 1">
|
<el-button type="text"
|
@click="handleRevokeApproval(row)">撤销审批</el-button>
|
</template>
|
<template v-else-if="row.status === 3">
|
<el-button type="text" @click="handleReportDetail(row)">详情</el-button>
|
<el-button type="text" @click="handleWithdraw(row)">编辑</el-button>
|
<el-button type="text" @click="handleDelete(row)">删除</el-button>
|
</template>
|
</template>
|
</el-table-column>
|
</Table>
|
</div>
|
</template>
|
</el-table-column>
|
<el-table-column prop="teamName" label="所属项目组" />
|
<el-table-column prop="itemName" label="检测项名称" />
|
<el-table-column prop="itemCode" label="检测项编号" />
|
<el-table-column prop="remark" label="备注" v-if="isChemist" />
|
<el-table-column prop="reportContent" label="报告内容" v-else>
|
<template #default="{ row }">
|
<span>{{ getReportContentText(row.reportContent) }}</span>
|
</template>
|
</el-table-column>
|
|
<el-table-column prop="createBy" label="创建人" />
|
<el-table-column prop="createTime" label="创建时间" />
|
<el-table-column prop="auditTime" label="审批时间" v-if="!isChemist" />
|
<el-table-column prop="age" label="状态">
|
<template #default="{ row }">
|
<!-- 化验师的状态显示 -->
|
<template v-if="isChemist">
|
<el-tag v-if="row.status == -1" type="info" color="#fff">草稿箱</el-tag>
|
<el-tag v-else-if="row.status == 1" type="warning">已提交</el-tag>
|
<el-tag v-else-if="row.status == 2" type="primary">待评定</el-tag>
|
<el-tag v-else-if="row.status == 3" type="success">已评定</el-tag>
|
</template>
|
<!-- 其他角色的状态显示 -->
|
<template v-else>
|
<el-tag v-if="row.status == -1" type="info" color="#fff">草稿箱</el-tag>
|
<el-tag v-else-if="row.status == 1" type="warning">待审核</el-tag>
|
<el-tag v-else-if="row.status == 2" type="success">已通过</el-tag>
|
<el-tag v-else-if="row.status == 3" type="danger">已驳回</el-tag>
|
<el-tag v-else-if="row.status == 4" type="danger">已撤销</el-tag>
|
</template>
|
</template>
|
</el-table-column>
|
<el-table-column prop="age" label="操作">
|
<template #default="{ row }">
|
<!-- 化验师的操作按钮 -->
|
<template v-if="isChemist">
|
<el-button v-if="currentType == 'draft'" type="text"
|
@click="handleEdit(row)">编辑</el-button>
|
<el-button v-if="currentType == 'draft'" type="text"
|
@click="handleDelete(row)">删除</el-button>
|
<el-button v-if="currentType == 'list' && row.status == 1" type="text"
|
@click="handleSubmit(row)">提交评定</el-button>
|
<el-button v-if="currentType == 'list'" type="text"
|
@click="handleDetail(row)">详情</el-button>
|
</template>
|
<!-- 工艺工程师的操作按钮 -->
|
<template v-else-if="isProcessEngineer">
|
<el-button v-if="row.status == 1" type="text" @click="handleApprove(row)">审核</el-button>
|
<el-button v-else type="text" @click="handleDetail(row)">详情</el-button>
|
</template>
|
<!-- 其他角色的操作按钮 -->
|
<template v-else>
|
<el-button type="text" @click="handleDetail(row)">详情</el-button>
|
</template>
|
</template>
|
</el-table-column>
|
</Table>
|
</template>
|
</TableCustom>
|
|
<!-- 统一的确认框组件 -->
|
<ShowDelConfirm :show="showDelConfirm" :title="confirmTitle" :tip="confirmTip" @close="closeConfirm"
|
@confirm="handleConfirm" />
|
<!-- 提交评定确认框:用于提交检测项评定时的确认 -->
|
<ShowDelConfirm :title="submitTitle" :tip="submitTip" :show="showSubmitConfirm"
|
@close="showSubmitConfirm = false" @confirm="handleSubmitConfirm" />
|
<Approval :visible="showApproval" @close="closeApproval" :data="rowData" :type="approvalType" />
|
<ItemApproval :visible="showItemApproval" @close="showItemApproval = false" :id="rowId" />
|
</div>
|
</template>
|
|
<script>
|
import Approval from './components/approval'
|
import ItemApproval from './components/itemApproval'
|
import { getDataList, detailPageList, getListByItemId, commitEvaluate, revokedReport, deleteDetail, deleteData } from './service'
|
|
export default {
|
name: 'ProjectList',
|
components: {
|
Approval,
|
ItemApproval
|
},
|
data() {
|
return {
|
currentType: 'list', // 当前显示类型:list-列表,draft-草稿箱
|
form: {
|
itemCode: '', // 检测项编号
|
itemName: '', // 检测项名称
|
reportContent: '', // 报告内容
|
status: '', // 状态,默认为空字符串表示全部
|
teamName: '', // 项目组名称
|
pageNum: 1,
|
pageSize: 10
|
},
|
rules: {
|
itemCode: [
|
{ max: 50, message: '检测项编号不能超过50个字符', trigger: 'blur' }
|
],
|
itemName: [
|
{ max: 100, message: '检测项名称不能超过100个字符', trigger: 'blur' }
|
],
|
teamName: [
|
{ max: 100, message: '项目组名称不能超过100个字符', trigger: 'blur' }
|
]
|
},
|
showSubmitConfirm: false,
|
showDelConfirm: false,
|
confirmTitle: '', // 确认框标题
|
confirmTip: '', // 确认框提示
|
confirmType: '', // 确认框类型:'deleteReport'-删除报告, 'deleteItem'-删除检测项, 'revoke'-撤销审批
|
rowId: '',
|
showApproval: false,
|
approvalType: '', // 新增:审批类型
|
submitTitle: '', // 新增:提交评定确认框标题
|
submitTip: '', // 新增:提交评定确认框提示
|
queryForm: {
|
pageSize: 10,
|
pageNum: 1
|
},
|
tableData: [],
|
expandRowKeys: [],
|
total: 0,
|
rowData: {},
|
reportList: {}, // 修改为对象,用行ID作为key
|
currentRow: null,
|
currentAction: '',
|
showItemApproval: false,
|
loading: false
|
}
|
},
|
computed: {
|
isChemist() {
|
const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
|
return userInfo.roleType == 4; // 2是化验师
|
},
|
isProcessEngineer() {
|
const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
|
return userInfo.roleType == 3; // 3是工艺工程师
|
}
|
},
|
methods: {
|
handleAddProject() {
|
this.$router.push('/chemistQa/add')
|
},
|
handleAdd(row) {
|
this.$router.push({
|
path: '/chemistQa/addDetectionReport',
|
query: {
|
itemId: row.id,
|
type: 'add'
|
}
|
})
|
},
|
closeApproval() {
|
this.showApproval = false;
|
this.rowData = {};
|
this.approvalType = '';
|
this.getList();
|
},
|
async handleRowClick(row, column, event) {
|
if (column.label == '操作') return
|
if (this.isChemist && this.currentType !== 'draft') {
|
try {
|
// 切换展开状态
|
if (this.expandRowKeys.includes(row.id)) {
|
this.expandRowKeys = this.expandRowKeys.filter(key => key !== row.id);
|
// 删除该行的报告数据
|
delete this.reportList[row.id];
|
} else {
|
this.expandRowKeys.push(row.id);
|
// 获取报告列表
|
const res = await getListByItemId({ id: row.id });
|
if (res) {
|
// 使用行ID作为key存储报告数据
|
this.$set(this.reportList, row.id, res || []);
|
} else {
|
this.msgError(res.msg || '获取报告列表失败');
|
}
|
}
|
} catch (error) {
|
console.error('获取报告列表失败:', error);
|
this.msgError('获取报告列表失败');
|
}
|
}
|
},
|
handleEdit(row) {
|
// 编辑操作
|
this.$router.push({
|
path: '/chemistQa/add',
|
query: {
|
id: row.id,
|
type: 'edit'
|
}
|
})
|
},
|
handleDelete(row) {
|
this.currentRow = row;
|
this.currentAction = 'delete';
|
this.confirmType = row.reportContent ? 'deleteReport' : 'deleteItem';
|
this.confirmTitle = '确认要删除这条记录吗?';
|
this.confirmTip = '删除后记录将无法找回';
|
this.showDelConfirm = true;
|
},
|
handleSubmit(row) {
|
// 提交评定操作
|
this.submitTitle = '确认要提交评定吗?'
|
this.submitTip = '提交后将进入评定流程'
|
this.showSubmitConfirm = true
|
this.rowId = row.id
|
},
|
handleDetail(row) {
|
if (this.isChemist) {
|
// 化验师角色使用原有逻辑
|
this.$router.push({
|
path: '/chemistQa/add',
|
query: {
|
id: row.id,
|
type: 'detail'
|
}
|
})
|
} else {
|
// 非化验师角色使用ItemApproval组件
|
this.showItemApproval = true
|
this.rowId = row.itemId
|
this.rowData = row
|
}
|
},
|
handleApprove(row) {
|
this.showApproval = true
|
this.rowId = row.id
|
this.rowData = row
|
this.approvalType = 'approve'
|
},
|
closeConfirm() {
|
this.showDelConfirm = false;
|
this.currentRow = null;
|
this.currentAction = '';
|
this.confirmType = '';
|
this.confirmTitle = '';
|
this.confirmTip = '';
|
},
|
async handleConfirm() {
|
if (!this.currentRow) return;
|
try {
|
this.loading = true;
|
if (this.currentAction === 'delete') {
|
if (this.confirmType === 'deleteReport') {
|
const res = await deleteDetail({ id: this.currentRow.id });
|
if (res.code === 200) {
|
this.$message.success('删除成功');
|
this.closeConfirm();
|
await this.getList();
|
} else {
|
this.$message.error(res.msg || '删除失败');
|
}
|
} else if (this.confirmType === 'deleteItem') {
|
const res = await deleteData({ id: this.currentRow.id });
|
if (res.code === 200) {
|
this.$message.success('删除成功');
|
this.closeConfirm();
|
await this.getList();
|
} else {
|
this.$message.error(res.msg || '删除失败');
|
}
|
}
|
} else if (this.currentAction === 'revoke') {
|
const res = await revokedReport({ id: this.currentRow.id });
|
if (res.code === 200) {
|
this.$message.success('撤销审批成功');
|
this.closeConfirm();
|
await this.getList();
|
} else {
|
this.$message.error(res.msg || '撤销审批失败');
|
}
|
}
|
} catch (error) {
|
console.error('操作失败:', error);
|
this.$message.error('操作失败,请重试');
|
} finally {
|
this.loading = false;
|
}
|
},
|
handleCurrentChange(page) {
|
this.queryForm.pageNum = page
|
this.getList()
|
},
|
handleSizeChange(size) {
|
this.queryForm.pageSize = size
|
this.getList()
|
},
|
async getList() {
|
if (this.loading) return;
|
try {
|
this.loading = true;
|
const params = {
|
...this.form,
|
pageNum: this.queryForm.pageNum,
|
pageSize: this.queryForm.pageSize
|
};
|
let res;
|
if (this.isChemist) {
|
res = await getDataList(params);
|
} else {
|
res = await detailPageList(params);
|
}
|
if (res.code === 200) {
|
this.tableData = res.data.records || [];
|
this.total = res.data.total || 0;
|
} else {
|
this.$message.error(res.msg || '获取列表失败');
|
}
|
} catch (error) {
|
console.error('获取列表失败:', error);
|
this.$message.error('获取列表失败,请重试');
|
} finally {
|
this.loading = false;
|
}
|
},
|
handleTypeChange(type) {
|
this.currentType = type;
|
this.form.status = type == 'draft' ? -1 : '';
|
this.getList();
|
},
|
handleReportDetail(row) {
|
this.rowData = row;
|
this.showApproval = true;
|
this.approvalType = 'detail';
|
},
|
getReportContentText(value) {
|
const contentMap = {
|
'1': '国家标准',
|
'2': '分析方法开发',
|
'3': '方法验证报告',
|
'4': '方法确认',
|
'5': '操作规程',
|
'6': '方法转移记录清单'
|
};
|
return contentMap[value] || value;
|
},
|
handleRevokeApproval(row) {
|
this.currentRow = row;
|
this.currentAction = 'revoke';
|
this.confirmType = 'revoke';
|
this.confirmTitle = '确认要撤销这条审批吗?';
|
this.confirmTip = '撤销后工艺工程师将无法收到此条审批信息';
|
this.showDelConfirm = true;
|
},
|
handleWithdraw(row) {
|
// 从父级检测项获取itemId
|
const parentItemId = Object.keys(this.reportList).find(key =>
|
this.reportList[key].some(report => report.id === row.id)
|
);
|
|
this.$router.push({
|
path: '/chemistQa/addDetectionReport',
|
query: {
|
id: row.id,
|
itemId: parentItemId,
|
type: 'edit'
|
}
|
})
|
},
|
async handleSubmitConfirm() {
|
if (!this.rowId) return;
|
try {
|
this.loading = true;
|
const res = await commitEvaluate({ id: this.rowId });
|
if (res.code === 200) {
|
this.$message.success('提交评定成功');
|
this.showSubmitConfirm = false;
|
this.rowId = '';
|
await this.getList();
|
} else {
|
this.$message.error(res.msg || '提交评定失败');
|
}
|
} catch (error) {
|
console.error('提交评定失败:', error);
|
this.$message.error('提交评定失败,请重试');
|
} finally {
|
this.loading = false;
|
}
|
},
|
async handleSearch() {
|
try {
|
this.loading = true;
|
await this.$refs.searchForm.validate();
|
this.queryForm.pageNum = 1;
|
await this.getList();
|
} catch (error) {
|
if (error === false) {
|
this.$message.warning('请检查表单填写是否正确');
|
} else {
|
this.$message.error('查询失败,请重试');
|
}
|
} finally {
|
this.loading = false;
|
}
|
},
|
async handleReset() {
|
try {
|
this.loading = true;
|
this.$refs.searchForm.resetFields();
|
this.form = {
|
itemCode: '',
|
itemName: '',
|
reportContent: '',
|
status: '',
|
teamName: '',
|
pageNum: 1,
|
pageSize: 10
|
};
|
this.queryForm.pageNum = 1;
|
await this.getList();
|
} catch (error) {
|
this.$message.error('重置失败,请重试');
|
} finally {
|
this.loading = false;
|
}
|
}
|
},
|
mounted() {
|
this.getList()
|
}
|
}
|
</script>
|
|
<style scoped lang="less">
|
.el-icon-plus {
|
margin-bottom: 20px;
|
}
|
|
.header-content {
|
font-family: PingFangSC, PingFang SC;
|
font-weight: 400;
|
font-size: 14px;
|
color: rgba(0, 0, 0, 0.88);
|
margin-left: 30px;
|
}
|
|
.box-title {
|
font-family: SourceHanSansCN, SourceHanSansCN;
|
font-weight: bold;
|
font-size: 18px;
|
color: #222222;
|
line-height: 27px;
|
display: flex;
|
align-items: center;
|
}
|
|
.header-icon {
|
width: 20px;
|
height: 20px;
|
margin-right: 10px;
|
|
}
|
|
.header-box {
|
border-radius: 16px;
|
margin-bottom: 30px;
|
}
|
|
.table-setting {
|
display: flex;
|
padding-bottom: 20px;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.flex {
|
display: flex;
|
align-items: center;
|
}
|
|
.table-title {
|
width: 220px;
|
height: 50px;
|
background: #fafafc;
|
border-radius: 8px 8px 0px 0px;
|
border: 1px solid #dcdfe6;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-family: SourceHanSansCN, SourceHanSansCN;
|
font-weight: bold;
|
font-size: 18px;
|
color: #606266;
|
line-height: 27px;
|
cursor: pointer;
|
transition: all 0.3s ease;
|
|
&.active {
|
color: #049c9a;
|
background: #ffffff;
|
border: 1px solid #049c9a;
|
}
|
}
|
|
.table-tit {
|
width: 166px;
|
height: 50px;
|
background: #fafafc;
|
border-radius: 8px 8px 0px 0px;
|
border: 1px solid #dcdfe6;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-family: SourceHanSansCN, SourceHanSansCN;
|
font-weight: bold;
|
font-size: 18px;
|
color: #606266;
|
line-height: 27px;
|
margin-left: 16px;
|
cursor: pointer;
|
transition: all 0.3s ease;
|
|
&.active {
|
color: #049c9a;
|
background: #ffffff;
|
border: 1px solid #049c9a;
|
}
|
}
|
|
.list {
|
height: 100%;
|
}
|
|
.expand-box {
|
padding: 20px;
|
background: linear-gradient(180deg, #049C9A 0%, #0ACBCA 100%);
|
border-radius: 20px;
|
|
&-title {
|
font-weight: 500;
|
font-size: 16px;
|
color: #FFFFFF;
|
line-height: 24px;
|
margin-bottom: 20px;
|
}
|
}
|
</style>
|