From 03b3624455b2f3a495ebb34349080e3bd35faff9 Mon Sep 17 00:00:00 2001 From: zhouwx <1175765986@qq.com> Date: 星期二, 19 八月 2025 14:19:40 +0800 Subject: [PATCH] 修改 --- public/purchaseRequisitionExample.docx | 0 public/qualityOrganizeExample.docx | 0 src/api/standardSys/standardSys.js | 34 src/views/work/procurementPlatform/purchaseContract/index.vue | 266 ++ src/views/work/onlineEducation/offlineEducation/components/recordDialog.vue | 2 src/views/work/onlineEducation/offlineEducation/index.vue | 2 src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/components/editDialog.vue | 392 ++++ src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/index.vue | 271 +++ src/views/work/procurementPlatform/incomingInspection/inspectionRecords/index.vue | 260 ++ src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/index.vue | 270 +++ src/views/work/procurementPlatform/purchaseRequisition/index.vue | 286 +++ src/views/work/procurementPlatform/purchaseRequisition/components/editDialog.vue | 500 +++++ src/views/work/procurementPlatform/incomingInspection/inspectionStandards/index.vue | 267 +++ src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/index.vue | 270 +++ src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/components/editDialog.vue | 391 ++++ public/recordsExample.docx | 0 src/views/work/procurementPlatform/incomingInspection/inspectionRecords/components/editDialog.vue | 348 +++ src/api/procurementPlatform/procurementPlatform.js | 129 + src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/index.vue | 299 +++ src/views/work/procurementPlatform/purchaseContract/components/editDialog.vue | 215 ++ src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/components/editDialog.vue | 390 ++++ src/views/work/procurementPlatform/incomingInspection/inspectionStandards/components/editDialog.vue | 215 ++ src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/components/editDialog.vue | 409 ++++ src/api/satisfiedNew/satisfiedNew.js | 100 + 24 files changed, 5,313 insertions(+), 3 deletions(-) diff --git a/public/purchaseRequisitionExample.docx b/public/purchaseRequisitionExample.docx new file mode 100644 index 0000000..2b012bb --- /dev/null +++ b/public/purchaseRequisitionExample.docx Binary files differ diff --git a/public/qualityOrganizeExample.docx b/public/qualityOrganizeExample.docx new file mode 100644 index 0000000..a1d3929 --- /dev/null +++ b/public/qualityOrganizeExample.docx Binary files differ diff --git a/public/recordsExample.docx b/public/recordsExample.docx new file mode 100644 index 0000000..fe38604 --- /dev/null +++ b/public/recordsExample.docx Binary files differ diff --git a/src/api/procurementPlatform/procurementPlatform.js b/src/api/procurementPlatform/procurementPlatform.js new file mode 100644 index 0000000..786064e --- /dev/null +++ b/src/api/procurementPlatform/procurementPlatform.js @@ -0,0 +1,129 @@ +import request from "@/utils/request"; + +//采购申请 +export function getApply(params) { + return request({ + url: '/purchase/audit/apply/list', + method: 'get', + params: params + }) +} + +export function addApply(data) { + return request({ + url: '/purchase/audit/apply/insert', + method: 'post', + data: data + }) +} + +export function editApply(params) { + return request({ + url: `/purchase/audit/apply/update`, + method: 'post', + data: params + }) +} + +export function delApply(data) { + return request({ + url: `/purchase/audit/apply/deleted?applyId=${data}`, + method: 'get' + }) +} + +//采购合同 +export function getContract(params) { + return request({ + url: '/purchase/audit/contract/list', + method: 'get', + params: params + }) +} + +export function addContract(data) { + return request({ + url: '/purchase/audit/contract/insert', + method: 'post', + data: data + }) +} + +export function editContract(params) { + return request({ + url: `/purchase/audit/contract/update`, + method: 'post', + data: params + }) +} + +export function delContract(data) { + return request({ + url: `purchase/audit/contract/deleted?contractId=${data}`, + method: 'get' + }) +} + +//检验规范 +export function getStandard(params) { + return request({ + url: '/purchase/audit/specification/list', + method: 'get', + params: params + }) +} + +export function addStandard(data) { + return request({ + url: '/purchase/audit/specification/insert', + method: 'post', + data: data + }) +} + +export function editStandard(params) { + return request({ + url: `/purchase/audit/specification/update`, + method: 'post', + data: params + }) +} + +export function delStandard(data) { + return request({ + url: `/purchase/audit/specification/deleted?specificationId=${data}`, + method: 'get' + }) +} + +//检验记录 +export function getRecord(params) { + return request({ + url: '/purchase/audit/record/list', + method: 'get', + params: params + }) +} + +export function addRecord(data) { + return request({ + url: '/purchase/audit/record/insert', + method: 'post', + data: data + }) +} + +export function editRecord(params) { + return request({ + url: `/purchase/audit/record/update`, + method: 'post', + data: params + }) +} + +export function delRecord(data) { + return request({ + url: `/purchase/audit/record/deleted?recordId=${data}`, + method: 'get' + }) +} diff --git a/src/api/satisfiedNew/satisfiedNew.js b/src/api/satisfiedNew/satisfiedNew.js new file mode 100644 index 0000000..419c896 --- /dev/null +++ b/src/api/satisfiedNew/satisfiedNew.js @@ -0,0 +1,100 @@ +import request from "@/utils/request"; + +//在研项目 +export function getResearch(params) { + return request({ + url: '/internal/audit/research/list', + method: 'get', + params: params + }) +} + +export function addResearch(data) { + return request({ + url: '/internal/audit/research/insert', + method: 'post', + data: data + }) +} + +export function editResearch(params) { + return request({ + url: `/internal/audit/research/update`, + method: 'post', + data: params + }) +} + +export function delResearch(data) { + return request({ + url: `/internal/audit/research/deleted?researchId=${data}`, + method: 'get' + }) +} + + +//交付项目 +export function getDelivery(params) { + return request({ + url: '/internal/audit/delivery/list', + method: 'get', + params: params + }) +} + +export function addDelivery(data) { + return request({ + url: '/internal/audit/delivery/insert', + method: 'post', + data: data + }) +} + +export function editDelivery(params) { + return request({ + url: `/internal/audit/delivery/update`, + method: 'post', + data: params + }) +} + +export function delDelivery(data) { + return request({ + url: `/internal/audit/delivery/deleted?deliveryId=${data}`, + method: 'get' + }) +} + +//年度报告 +export function getReport(params) { + return request({ + url: '/internal/audit/annual/list', + method: 'get', + params: params + }) +} + +export function addReport(data) { + return request({ + url: '/internal/audit/annual/insert', + method: 'post', + data: data + }) +} + +export function editReport(params) { + return request({ + url: `/internal/audit/annual/update`, + method: 'post', + data: params + }) +} + +export function delReport(data) { + return request({ + url: `/internal/audit/annual/deleted?annualId=${data}`, + method: 'get' + }) +} + + diff --git a/src/api/standardSys/standardSys.js b/src/api/standardSys/standardSys.js index fb192d8..5a924e0 100644 --- a/src/api/standardSys/standardSys.js +++ b/src/api/standardSys/standardSys.js @@ -62,4 +62,36 @@ method: 'get', params: params }) -} \ No newline at end of file +} + +//质量体系策划 +export function getQualityTemplate(params) { + return request({ + url: '/template/list', + method: 'get', + params: params + }) +} + +export function addQualityTemplate(data) { + return request({ + url: '/template/insert', + method: 'post', + data: data + }) +} + +export function editQualityTemplate(params) { + return request({ + url: `/template/update`, + method: 'post', + data: params + }) +} + +export function delQualityTemplate(data) { + return request({ + url: `/template/deleted?planId=${data}`, + method: 'get' + }) +} diff --git a/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/components/editDialog.vue b/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/components/editDialog.vue new file mode 100644 index 0000000..53c3ed4 --- /dev/null +++ b/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/components/editDialog.vue @@ -0,0 +1,392 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="50%" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules" > + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin"> + <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="年份:" prop="year" > + <el-select + v-model="state.form.year" + placeholder="请选择年份" + :disabled="title === '查看'" + style="width: 100%" + filterable + allow-create + default-first-option + :reserve-keyword="false" + @change="handleChangeNum" + > + <el-option + v-for="item in state.yearList" + :key="item.value" + :label="item.label" + :value="item.label" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <div style="display: flex;align-items: center;margin-bottom: 10px"> + <span style="font-size: 15px;font-weight: 700;" >质量管理体系工作策划安排及完成情况:</span> + <el-button + :disabled="title === '查看'" + type="primary" + @click="addTableData" + style="margin-left: 20px" + >新增</el-button> + </div> + <el-table :data="state.form.planMesses" style="margin-bottom: 15px" :border="true" > + <el-table-column type="index" label="序号" align="center"></el-table-column> + <el-table-column label="项目" prop="project" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'planMesses.' + '[' + $index + ']' + '.project'" :rules="state.rules.project"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="4" type="textarea" v-model="row.project" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="内容" prop="content" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'planMesses.' + '[' + $index + ']' + '.content'" :rules="state.rules.content"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="4" type="textarea" v-model="row.content" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="参加人员" prop="participant" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'planMesses.' + '[' + $index + ']' + '.participant'" :rules="state.rules.participant"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="4" type="textarea" v-model="row.participant" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="时间" prop="applyTime" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'planMesses.' + '[' + $index + ']' + '.applyTime'" :rules="state.rules.applyTime"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="4" type="textarea" v-model="row.applyTime" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="完成时间" prop="accomplishTime" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'planMesses.' + '[' + $index + ']' + '.accomplishTime'" :rules="state.rules.accomplishTime"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="4" type="textarea" v-model="row.accomplishTime" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="完成情况" prop="accomplishStatus" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'planMesses.' + '[' + $index + ']' + '.accomplishStatus'" :rules="state.rules.accomplishStatus"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="4" type="textarea" v-model="row.accomplishStatus" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="操作" align="center" v-if="title !== '查看'" > + <template #default="scope"> + <el-button link type="danger" @click="delTableData(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="编制:" prop="writeId" > + <el-select clearable v-model="state.form.writeId" :disabled="title =='查看'" filterable style="width: 240px"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="审核:" prop="checkId" > + <el-select clearable v-model="state.form.checkId" :disabled="title =='查看'" filterable style="width: 240px"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="批准:" prop="ratifyId" > + <el-select clearable v-model="state.form.ratifyId" :disabled="title =='查看'" filterable style="width: 240px"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer v-if="title !== '查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {onMounted, reactive, ref, toRefs} from 'vue' +import Cookies from "js-cookie"; +import {getCompany} from "@/api/onlineEducation/company"; +import {ElMessage} from "element-plus"; +import {getUser} from "@/api/onlineEducation/user"; +import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object"; +import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table"; +import {addNeedDiscren, editNeedDiscren} from "@/api/need/need"; +import {addQualityTemplate, editQualityTemplate} from "@/api/standardSys/standardSys"; + +const dialogVisible = ref(false); +const title = ref(""); +const busRef = ref(); +const length = ref() +const selectPopperClass = "max-width-select"; +const emit = defineEmits(["getList"]); +const dataRef = ref(); +const state = reactive({ + form: { + id: '', + companyId: null, + year: '', + writeId: null, + checkId: null, + ratifyId: null, + planMesses:[], + }, + rules: { + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + year: [{ required: true, message: '请选择年份', trigger: 'blur' }], + writeId: [{ required: true, message: '请选择编制人', trigger: 'blur' }], + ratifyId: [{ required: true, message: '请选择批准人', trigger: 'blur' }], + checkId: [{ required: true, message: '请选择审核人', trigger: 'blur' }], + project: [{required: true, message: "", trigger: "blur"}], + content: [{required: true, message: "", trigger: "blur"}], + participant: [{required: true, message: "", trigger: "blur"}], + applyTime: [{required: true, message: "", trigger: "blur"}], + accomplishTime: [{required: true, message: "", trigger: "blur"}], + accomplishStatus: [{required: true, message: "", trigger: "blur"}], + planMesses:[{ required: true, message: '请填写质量管理体系工作策划安排及完成情况表', trigger: 'blur' }], + }, + peopleList: [], + isAdmin: false, + companyList: [], + deptList: [], + yearList: [ + { + value: 1, + label: '2025' + }, + { + value: 2, + label: '2024' + }, + { + value: 3, + label: '2023' + }, + { + value: 4, + label: '2022' + }, + { + value: 5, + label: '2021' + }, + ], +}) + +onMounted(() => { + + +}); +const openDialog = async (type, value,companyList) => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + state.isAdmin = userInfo.userType === 0; + state.form.companyName = userInfo.companyName + state.form.companyId = userInfo.companyId + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + state.companyList = companyList + } + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ; + if(type === 'edit' || type === 'review') { + state.form = JSON.parse(JSON.stringify(value)); + + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + } + } + await getPeopleList() + dialogVisible.value = true; +} + + +const onSubmit = async () => { + if(state.form.planMesses && state.form.planMesses.length == 0){ + ElMessage.warning('请填写质量管理体系工作策划安排及完成情况') + return + } + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + console.log('sta',state.form) + const {id, ...data} = JSON.parse(JSON.stringify(state.form)) + const res = await addQualityTemplate(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + }else if(title.value === '编辑'){ + state.form.planMesses.forEach(item => { + item.planId = state.form.id + }) + const {...data} = JSON.parse(JSON.stringify(state.form)) + const res = await editQualityTemplate(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '编辑成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + emit("getList") + +} +const reset = () => { + state.form = { + id: '', + companyId: null, + year: '', + writeId: null, + checkId: null, + ratifyId: null, + planMesses:[], + } + state.peopleList = [] + state.companyList = [] +} +const getPeopleList = async ()=> { + if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){ + return + } + const queryParams = { + pageNum: 1, + pageSize: 9999, + companyId: state.form.companyId + } + const res = await getUser(queryParams) + if(res.code == 200){ + state.peopleList = res.data.list?res.data.list:[] + }else{ + ElMessage.warning(res.message) + } +}; + + + + +const selectValueCom = (val) => { + state.form.writeId = null + state.form.checkId = null + state.form.ratifyId = null + state.companyList.forEach(item => { + if(item.name === val){ + state.form.companyId = item.id + } + }) + getPeopleList() +} + +const handleChangeNum = (value) => { + if (!/^\d+$/.test(value)) { // 验证是否为数字 + ElMessage.warning('只能输入数字') + state.form.year = '' // 重置选择,避免非法值被添加到options中 + } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项 + state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同) + } +} +const addTableData = () => { + state.form.planMesses.push({}) +} +const delTableData = (val) => { + state.form.planMesses = state.form.planMesses.filter(item=> item != val) +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/index.vue b/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/index.vue new file mode 100644 index 0000000..e8190ef --- /dev/null +++ b/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityOrganize/index.vue @@ -0,0 +1,299 @@ +<template> + <div class="app-container"> + <div style="margin-bottom: 10px"> + <el-form style="display: flex;flex-wrap: wrap;"> + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px"> + <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable> + <el-option + v-for="item in data.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item label="年份:" style="margin-left: 20px"> + <el-select + v-model="data.queryParams.year" + placeholder="请选择年份" + style="width: 240px" + filterable + allow-create + default-first-option + :reserve-keyword="false" + @change="handleChangeNum" + > + <el-option + v-for="item in data.yearList" + :key="item.value" + :label="item.label" + :value="item.label" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </el-form-item> + <el-form-item style="margin-left: 15px"> + <el-button + type="primary" + @click="exportData" + >导出</el-button> + </el-form-item> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column type="index" label="序号" width="80" align="center"></el-table-column> + <el-table-column label="名称" prop="companyName" align="center" > + <template #default="scope"> + <span>{{scope.row.year}}年度{{scope.row.companyName}}质量管理体系工作策划安排及完成情况</span> + </template> + </el-table-column> + <el-table-column label="操作" align="center" class-naame="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + + <div class="pag-container"> + <el-pagination + v-model:current-page="data.queryParams.pageNum" + v-model:page-size="data.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <editDialog ref="noticeRef" @getList = "getList"></editDialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue"; +import editDialog from "./components/editDialog.vue" +import {ElMessage, ElMessageBox} from "element-plus"; +import {getCompany} from "@/api/onlineEducation/company"; +import Cookies from "js-cookie"; +import {generateWordDocument} from "@/utils/exportWord"; +import {delTable, getTable} from "@/api/qualityObjectives/table"; +import {delDiscern, getDiscern} from "@/api/environment/factors"; +import {delQualityTemplate, getQualityTemplate} from "@/api/standardSys/standardSys"; +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const noticeRef = ref(); +const deptRef = ref() +const loadingCompany = ref(false) +const choosedData = ref([]) +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + year: '', + type: '' + }, + companyList: [], + isAdmin: false, + dialogVisible: false, + yearList: [ + { + value: 1, + label: '2025' + }, + { + value: 2, + label: '2024' + }, + { + value: 3, + label: '2023' + }, + { + value: 4, + label: '2022' + }, + { + value: 5, + label: '2021' + }, + ], +}); +const dataList = ref([]); +const total = ref(0); + +const { queryParams } = toRefs(data); + +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + console.log("userInfo",userInfo) + data.isAdmin = userInfo.userType === 0; + if(data.isAdmin){ + data.queryParams.companyId = null + }else { + data.queryParams.companyId = userInfo.companyId + } + getList(); + if(data.isAdmin){ + getCompanyList() + } +}); +const getList = async () => { + loading.value = true; + const res = await getQualityTemplate(data.queryParams); + if(res.code === 200){ + dataList.value = res.data.list + total.value = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false; +} + +const searchClick = () => { + getList(); +} + +const openDialog = (type, value) => { + noticeRef.value.openDialog(type, value,data.companyList); +} + +const selectValue = (val) => { + data.companyList.forEach(item => { + if(item.name === val){ + data.queryParams.companyId = item.id + } + }) +} + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + } else { + ElMessage.warning(res.message) + } +} + +const handleSizeChange = (val) => { + data.queryParams.pageSize = val + getList() +} +const handleCurrentChange = (val) => { + data.queryParams.pageNum = val + getList() +} +const handleClose = () => { + data.dialogVisible = false +} + +/** 重置新增的表单以及其他数据 */ +function reset() { + if(data.isAdmin){ + data.queryParams = { + companyId: '', + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + choosedData.value = [] + data.companyList = []; + getCompanyList() + }else { + data.queryParams = { + companyId: data.queryParams.companyId, + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + } + getList(); + +} +const exportData = () => { + if(choosedData.value && choosedData.value.length === 0){ + ElMessage.warning('请选择需要导出的数据') + }else { + startGeneration() + } +} +const templatePath = ref('/qualityOrganizeExample.docx') +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(choosedData.value)) + data.forEach(item => { + + item.tableList = item.planMesses + + try { + generateWordDocument(templatePath.value, item, item.companyName+`_质量管理体系工作策划安排及完成情况.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '导出失败' + }); + } + }) +} + +const handleSelectionChange = (val) => { + choosedData.value = val +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delQualityTemplate(val.id); + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '删除成功' + }); + getList(); + }else{ + ElMessage.warning(res.message) + } + }) +} +const handleChangeNum = (value) => { + if (!/^\d+$/.test(value)) { // 验证是否为数字 + ElMessage.warning('只能输入数字') + data.queryParams.year = '' // 重置选择,避免非法值被添加到options中 + } else if (!data.yearList.some(option => option.label === value)) { // 确保不是已存在的选项 + data.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同) + } +} + +</script> +<style lang="scss"> +.pag-container{ + float: right; + margin-top: 10px; +} +</style> diff --git a/src/views/work/onlineEducation/offlineEducation/components/recordDialog.vue b/src/views/work/onlineEducation/offlineEducation/components/recordDialog.vue index 84a4743..390ac8f 100644 --- a/src/views/work/onlineEducation/offlineEducation/components/recordDialog.vue +++ b/src/views/work/onlineEducation/offlineEducation/components/recordDialog.vue @@ -89,7 +89,7 @@ <!-- </el-radio-group>--> <!-- </el-form-item>--> <el-form-item label="培训记录:" prop="passed" > - <el-upload accept=".jpg,.jpeg,.png,.doc,.docx,.pdf,.xls,xlsx,ppt,pptx" style="width: 100%" :action="state.uploadUrl" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile)" :on-exceed="showTip" v-model:file-list="state.fileList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles)" > + <el-upload accept=".jpg,.jpeg,.png,.doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx" style="width: 100%" :action="state.uploadUrl" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile)" :on-exceed="showTip" v-model:file-list="state.fileList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles)" > <el-button type="primary">点击上传</el-button> <!-- <template #tip>--> <!-- <div class="el-upload__tip">尺寸小于5M,最多可上传1份</div>--> diff --git a/src/views/work/onlineEducation/offlineEducation/index.vue b/src/views/work/onlineEducation/offlineEducation/index.vue index d7bb0ff..7bea66f 100644 --- a/src/views/work/onlineEducation/offlineEducation/index.vue +++ b/src/views/work/onlineEducation/offlineEducation/index.vue @@ -205,7 +205,7 @@ } const openFile = async(path)=>{ const ext = path.split('.').pop().toLowerCase(); - if (ext === 'doc' || ext === 'xls' || ext === 'xlsx') { + if (ext === 'doc' || ext === 'xls' || ext === 'xlsx' || ext === 'ppt' || ext === 'pptx') { ElMessageBox.confirm(`暂不支持线上预览.${ext}文件,是否下载查看?`, '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => { window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank'); }).catch(() => { diff --git a/src/views/work/procurementPlatform/incomingInspection/inspectionRecords/components/editDialog.vue b/src/views/work/procurementPlatform/incomingInspection/inspectionRecords/components/editDialog.vue new file mode 100644 index 0000000..5203848 --- /dev/null +++ b/src/views/work/procurementPlatform/incomingInspection/inspectionRecords/components/editDialog.vue @@ -0,0 +1,348 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="50%" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules" > + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin"> + <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="记录名称:" prop="recordName" > + <el-input :disabled="title === '查看'" v-model="state.form.recordName" placeholder="请输入"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <div style="display: flex;align-items: center;margin-bottom: 10px"> + <span style="font-size: 15px;font-weight: 700;" >材料清单:</span> + <el-button + :disabled="title === '查看'" + type="primary" + @click="addTableData" + style="margin-left: 20px" + >新增</el-button> + </div> + <el-table :data="state.form.recordMesses" style="margin-bottom: 10px" :border="true" > + <el-table-column type="index" label="序号" align="center"></el-table-column> + <el-table-column label="材料名称" prop="materialsName" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'recordMesses.' + '[' + $index + ']' + '.materialsName'" :rules="state.rules.materialsName"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.materialsName" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="合格证明材料检验" prop="qualifiedMaterials" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'recordMesses.' + '[' + $index + ']' + '.qualifiedMaterials'" :rules="state.rules.qualifiedMaterials"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.qualifiedMaterials" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="外观检验" prop="appearance" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'recordMesses.' + '[' + $index + ']' + '.appearance'" :rules="state.rules.appearance"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.appearance" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="功能检验" prop="function" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'recordMesses.' + '[' + $index + ']' + '.function'" :rules="state.rules.function"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.function" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="单位" prop="unit" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'recordMesses.' + '[' + $index + ']' + '.unit'" :rules="state.rules.unit"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.unit" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="数量" prop="amount" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'recordMesses.' + '[' + $index + ']' + '.amount'" :rules="state.rules.amount"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" v-model.trim.number="row.amount" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="检验员" prop="checkUser" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'recordMesses.' + '[' + $index + ']' + '.checkUser'" :rules="state.rules.checkUser"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.checkUser" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="操作" align="center" v-if="title !== '查看'" > + <template #default="scope"> + <el-button link type="danger" @click="delTableData(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="说明:" prop="explain" > + <el-input :disabled="title === '查看'" :rows="4" type="textarea" v-model="state.form.explain" placeholder="请输入"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="现场签收人:" prop="signId" > + <el-select clearable v-model="state.form.signId" :disabled="title =='查看'" filterable style="width: 240px"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="日期:" prop="signTime" > + <el-date-picker + :disabled="title === '查看'" + v-model="state.form.signTime" + type="date" + placeholder="请选择日期" + /> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="备注:" prop="remark" > + <el-input :disabled="title === '查看'" :rows="4" type="textarea" v-model="state.form.remark" placeholder="请输入"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer v-if="title !== '查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {onMounted, reactive, ref, toRefs} from 'vue' +import Cookies from "js-cookie"; +import {getCompany} from "@/api/onlineEducation/company"; +import {ElMessage} from "element-plus"; +import {getUser} from "@/api/onlineEducation/user"; +import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object"; +import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table"; +import {addNeedDiscren, editNeedDiscren} from "@/api/need/need"; +import {addRecord, editRecord} from "@/api/procurementPlatform/procurementPlatform"; + +const dialogVisible = ref(false); +const title = ref(""); +const busRef = ref(); +const length = ref() +const selectPopperClass = "max-width-select"; +const emit = defineEmits(["getList"]); +const dataRef = ref(); +const state = reactive({ + form: { + id: '', + companyId: null, + recordName: null, + explain: '', + signId: null, + signTime: null, + remark: '', + recordMesses:[], + }, + rules: { + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + recordName: [{ required: true, message: '请输入记录名称', trigger: 'blur' }], + signId: [{ required: true, message: '请选择现场签收人', trigger: 'blur' }], + signTime: [{ required: true, message: '请选择日期', trigger: 'blur' }], + materialsName: [{required: true, message: "", trigger: "blur"}], + qualifiedMaterials: [{required: true, message: "", trigger: "blur"}], + appearance: [{required: true, message: "", trigger: "blur"}], + function: [{required: true, message: "", trigger: "blur"}], + unit: [{required: true, message: "", trigger: "blur"}], + amount: [{required: true, message: "", trigger: "blur"}], + checkUser: [{required: true, message: "", trigger: "blur"}], + + }, + peopleList: [], + isAdmin: false, + companyList: [], +}) + +onMounted(() => { + + +}); +const openDialog = async (type, value,companyList) => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + state.isAdmin = userInfo.userType === 0; + state.form.companyName = userInfo.companyName + state.form.companyId = userInfo.companyId + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + state.companyList = companyList + } + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ; + if(type === 'edit' || type === 'review') { + state.form = JSON.parse(JSON.stringify(value)); + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + } + } + await getPeopleList() + dialogVisible.value = true; +} + + +const onSubmit = async () => { + if(state.form.recordMesses && state.form.recordMesses.length == 0){ + ElMessage.warning('请填写材料清单') + return + } + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + console.log('sta',state.form) + const {id, ...data} = JSON.parse(JSON.stringify(state.form)) + const res = await addRecord(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + }else if(title.value === '编辑'){ + state.form.recordMesses.forEach(item => { + item.recordId = state.form.id + }) + const {...data} = JSON.parse(JSON.stringify(state.form)) + const res = await editRecord(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '编辑成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + emit("getList") + +} +const reset = () => { + state.form = { + id: '', + companyId: null, + recordName: null, + explain: '', + signId: null, + signTime: null, + remark: '', + recordMesses:[], + } + state.peopleList = [] + state.companyList = [] +} +const getPeopleList = async ()=> { + if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){ + return + } + const queryParams = { + pageNum: 1, + pageSize: 9999, + companyId: state.form.companyId + } + const res = await getUser(queryParams) + if(res.code == 200){ + state.peopleList = res.data.list?res.data.list:[] + }else{ + ElMessage.warning(res.message) + } +}; + + + + +const selectValueCom = (val) => { + state.form.signId = null + state.companyList.forEach(item => { + if(item.name === val){ + state.form.companyId = item.id + } + }) + getPeopleList() +} + +const addTableData = () => { + state.form.recordMesses.push({}) +} +const delTableData = (val) => { + state.form.recordMesses = state.form.recordMesses.filter(item=> item != val) +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/work/procurementPlatform/incomingInspection/inspectionRecords/index.vue b/src/views/work/procurementPlatform/incomingInspection/inspectionRecords/index.vue new file mode 100644 index 0000000..685920e --- /dev/null +++ b/src/views/work/procurementPlatform/incomingInspection/inspectionRecords/index.vue @@ -0,0 +1,260 @@ +<template> + <div class="app-container"> + <div style="margin-bottom: 10px"> + <el-form style="display: flex;flex-wrap: wrap;"> + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px"> + <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable> + <el-option + v-for="item in data.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="data.isAdmin"> + <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </el-form-item> + <el-form-item style="margin-left: 15px"> + <el-button + type="primary" + @click="exportData" + >导出</el-button> + </el-form-item> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column type="index" label="序号" width="80" align="center"></el-table-column> + <el-table-column label="记录名称" prop="recordName" align="center" /> + <el-table-column label="操作" align="center" class-naame="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + + <div class="pag-container"> + <el-pagination + v-model:current-page="data.queryParams.pageNum" + v-model:page-size="data.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <editDialog ref="noticeRef" @getList = "getList"></editDialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue"; +import editDialog from "./components/editDialog.vue" +import {ElMessage, ElMessageBox} from "element-plus"; +import {getCompany} from "@/api/onlineEducation/company"; +import Cookies from "js-cookie"; +import {generateWordDocument} from "@/utils/exportWord"; +import {delTable, getTable} from "@/api/qualityObjectives/table"; +import {delDiscern, getDiscern} from "@/api/environment/factors"; +import {delRecord, getRecord} from "@/api/procurementPlatform/procurementPlatform"; +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const noticeRef = ref(); +const deptRef = ref() +const loadingCompany = ref(false) +const choosedData = ref([]) +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + year: '', + type: '' + }, + companyList: [], + isAdmin: false, + dialogVisible: false, + +}); +const dataList = ref([]); +const total = ref(0); + +const { queryParams } = toRefs(data); + +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + console.log("userInfo",userInfo) + data.isAdmin = userInfo.userType === 0; + if(data.isAdmin){ + data.queryParams.companyId = null + }else { + data.queryParams.companyId = userInfo.companyId + } + getList(); + if(data.isAdmin){ + getCompanyList() + } +}); +const getList = async () => { + loading.value = true; + const res = await getRecord(data.queryParams); + if(res.code === 200){ + dataList.value = res.data.list + total.value = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false; +} + +const searchClick = () => { + getList(); +} + +const openDialog = (type, value) => { + noticeRef.value.openDialog(type, value,data.companyList); +} + +const selectValue = (val) => { + data.companyList.forEach(item => { + if(item.name === val){ + data.queryParams.companyId = item.id + } + }) +} + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + } else { + ElMessage.warning(res.message) + } +} + +const handleSizeChange = (val) => { + data.queryParams.pageSize = val + getList() +} +const handleCurrentChange = (val) => { + data.queryParams.pageNum = val + getList() +} +const handleClose = () => { + data.dialogVisible = false +} + +/** 重置新增的表单以及其他数据 */ +function reset() { + if(data.isAdmin){ + data.queryParams = { + companyId: '', + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + choosedData.value = [] + data.companyList = []; + getCompanyList() + }else { + data.queryParams = { + companyId: data.queryParams.companyId, + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + } + getList(); + +} +const exportData = () => { + if(choosedData.value && choosedData.value.length === 0){ + ElMessage.warning('请选择需要导出的数据') + }else { + startGeneration() + } +} +const templatePath = ref('/recordsExample.docx') +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(choosedData.value)) + data.forEach(item => { + item.signTime = item.signTime.substring(0,10) + item.tableList = item.recordMesses.map((item,index) => { + return { + ...item, + num: index +1 + } + }) + + try { + generateWordDocument(templatePath.value, item, item.companyName+`_原材料产品检验验收单.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '导出失败' + }); + } + }) +} + +const handleSelectionChange = (val) => { + choosedData.value = val +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delRecord(val.id); + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '删除成功' + }); + getList(); + }else{ + ElMessage.warning(res.message) + } + }) +} +const handleChangeNum = (value) => { + if (!/^\d+$/.test(value)) { // 验证是否为数字 + ElMessage.warning('只能输入数字') + data.queryParams.year = '' // 重置选择,避免非法值被添加到options中 + } else if (!data.yearList.some(option => option.label === value)) { // 确保不是已存在的选项 + data.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同) + } +} + +</script> +<style lang="scss"> +.pag-container{ + float: right; + margin-top: 10px; +} +</style> diff --git a/src/views/work/procurementPlatform/incomingInspection/inspectionStandards/components/editDialog.vue b/src/views/work/procurementPlatform/incomingInspection/inspectionStandards/components/editDialog.vue new file mode 100644 index 0000000..2191325 --- /dev/null +++ b/src/views/work/procurementPlatform/incomingInspection/inspectionStandards/components/editDialog.vue @@ -0,0 +1,215 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="state.title" + width="600px" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" > + <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId"> + <el-select v-model="state.form.companyId" placeholder="请选择" clearable style="width: 100%"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item label="文件名称:" prop="fileName"> + <el-input v-model.trim="state.form.fileName" :disabled="state.title =='查看'" placeholder="文件名称"></el-input> + </el-form-item> + <el-form-item label="文件:" prop="filePath"> + <el-upload accept=".jpg,.jpeg,.png,.doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx" :action="state.uploadUrl" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile)" :on-exceed="showTip" :limit='state.fileLimit' v-model:file-list="state.fileList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles)" > + <el-button type="primary">点击上传</el-button> + <template #tip> + <div class="el-upload__tip">尺寸小于5M,最多可上传1张</div> + </template> + </el-upload> + </el-form-item> + </el-form> + <template #footer v-if="state.title !='查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue' +import {ElMessage} from "element-plus"; +import {addUser, editUser, getUserById, resetPwd} from "@/api/onlineEducation/user" +import {Base64} from "js-base64" +import {getCompany} from "@/api/onlineEducation/company"; +import {addIndustryTemp, updateIndustryTemp, updateInfoPlatforms} from "@/api/staffManage/staff"; +import {getToken} from "@/utils/auth"; +import {delPic} from "@/api/onlineEducation/banner"; +import {getIndustry} from "@/api/system/industry"; +import {addContract, addStandard, editContract, editStandard} from "@/api/procurementPlatform/procurementPlatform"; + +const emit = defineEmits(["getList"]); +const dialogVisible = ref(false) +const superRef = ref() + +const state = reactive({ + title: '', + form: { + id: null, + fileName: '', + filePath: '', + + format: '', + companyId: null, + + }, + formRules:{ + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + fileName: [{ required: true, message: '请输入文件名称', trigger: 'blur' }], + filePath: [{ required: true, message: '请上传文件', trigger: 'blur' }], + }, + isAdmin: false, + companyList: [], + industryList: [], + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/system/common/uploadFile', + header: { + Authorization: getToken() + }, + fileLimit: 1, + fileList: [] +}) +onMounted(() => { + +}); + +const openDialog = async (type, value,companyId, isAdmin, companyList) => { + state.isAdmin = isAdmin + if(isAdmin){ + state.companyList = companyList + } + state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' + state.form.companyId = companyId + if(state.title == '编辑'||state.title == '查看'){ + Object.keys(state.form).forEach(key => { + if (key in value) { + state.form[key] = value[key] + } + }) + if(value.filePath) { + const obj = { + url: value.filePath, + name: value.fileName + } + state.fileList = [obj] + } + } + dialogVisible.value = true +} + +const onSubmit = async () => { + const valid = await superRef.value.validate(); + if(valid){ + if(state.title == '新增'){ + const {id,...data} = state.form + const res = await addStandard(data) + if(res.code == 200){ + ElMessage.success(res.message) + emit('getList') + handleClose() + dialogVisible.value = false; + }else{ + ElMessage.warning(res.message) + } + }else{ + const res = await editStandard(state.form) + if(res.code == 200){ + ElMessage.success(res.message) + emit('getList') + handleClose() + dialogVisible.value = false; + }else{ + ElMessage.warning(res.message) + } + } + } +} + +const handleAvatarSuccess = (res, uploadFile) => { + if(res.code == 200){ + state.form.fileName = res.data.originName + state.form.filePath = res.data.path + }else{ + state.fileList = [] + ElMessage({ + type: 'warning', + message: '文件上传失败' + }) + } +} + +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; +const handleRemove = async (file, uploadFiles) => { + let path = state.form.filePath; + await delPic({path: path}).then(res => { + if(res.code == 200){ + state.form.filePath = '' + state.form.fileName = '' + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } + }).catch(() => { + }); +} + +const handleClose = () => { + state.form = { + id: null, + filePath: '', + fileName: '', + companyId: null, + } + state.fileList = [] + superRef.value.clearValidate(); + superRef.value.resetFields() + dialogVisible.value = false; +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/work/procurementPlatform/incomingInspection/inspectionStandards/index.vue b/src/views/work/procurementPlatform/incomingInspection/inspectionStandards/index.vue new file mode 100644 index 0000000..1cb9bdd --- /dev/null +++ b/src/views/work/procurementPlatform/incomingInspection/inspectionStandards/index.vue @@ -0,0 +1,267 @@ +<template> + <div class="app-container"> + <div style="display: flex;justify-content: space-between"> + <el-form :inline="true" style="display: flex;align-items: center;flex-wrap: wrap;" > + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item v-if="isAdmin" label="企业:" > + <el-select v-model="data.queryParams.companyId" placeholder="请选择" clearable> + <el-option + v-for="item in companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="isAdmin"> + <el-button type="primary" @click="getList">查询</el-button> + <el-button type="primary" plain @click="reset">重置</el-button> + </el-form-item> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true"> + <el-table-column label="序号" type="index" align="center" width="80"/> + <el-table-column label="规范" prop="fileNameSimple" align="center"/> + <el-table-column label="文件" prop="fileName" align="center"> + <template #default="scope"> + <el-link style="" type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName}}</el-link> + </template> + </el-table-column> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="downloadFile(scope.row)">下载</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)">编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + v-model:page="queryParams.pageNum" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + + <edit-dialog ref="dialogRef" @getList=getList></edit-dialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, onUnmounted, reactive, ref, toRefs} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {delCompany, getCompany} from "@/api/onlineEducation/company"; +import { Plus, Upload, Download} from '@element-plus/icons-vue'; +import {delUser, getUser} from "@/api/onlineEducation/user"; +import Cookies from "js-cookie"; +import editDialog from './components/editDialog.vue' +import { + delIndustryTemp, + getIndustryTemp, uploadTemplate, +} from "@/api/staffManage/staff"; +import useUserStore from "@/store/modules/user"; +import axios from "axios"; +import {getToken} from "@/utils/auth"; +import {getIndustry} from "@/api/system/industry"; +import {renderAsync} from "docx-preview"; +import {delContract, delStandard, getContract, getStandard} from "@/api/procurementPlatform/procurementPlatform"; +const userStore = useUserStore() +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const dialogRef = ref(); + +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + industryType: null, + type: '', + templateName: '' + }, + total: 0, + dataList: [], + companyList: [], + industryList: [], + isAdmin: false, + typeList: [], + exportDialog: false, + +}); + + +const { queryParams, total, dataList,companyList,industryList, isAdmin } = toRefs(data); +const userInfo = ref() +onMounted(async ()=>{ + if(userStore.roles.includes('admin')){ + data.isAdmin = true + data.queryParams.companyId = null + await getCompanyList() + }else{ + data.isAdmin = false + data.queryParams.companyId = userStore.companyId + } + await getList() +}) + +onUnmounted(()=>{ + +}) +const openFile = async(path)=>{ + const ext = path.split('.').pop().toLowerCase(); + if (ext === 'doc' || ext === 'xls' || ext === 'xlsx' || ext === 'ppt' || ext === 'pptx') { + ElMessageBox.confirm('暂不支持线上预览文件,是否下载查看?', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => { + window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank'); + }).catch(() => { + console.log('取消预览') + }); + return + } + if(ext === 'docx'){ + try { + // 1. 获取文件 + const response = await fetch(import.meta.env.VITE_APP_BASE_API + '/' + path); + const arrayBuffer = await response.arrayBuffer(); + // 2. 创建新窗口 + const win = window.open('', '_blank') + win.document.write(` + <!DOCTYPE html> + <html> + <head> + <title>预览</title> + <style> + body { margin: 20px; font-family: Arial; } + .docx-container { width: 100%; height: 100%; } + </style> + </head> + <body> + <div id="container" class="docx-container"></div> + </body> + </html> + `); + // 3. 渲染 DOCX + await renderAsync(arrayBuffer, win.document.getElementById('container')); + + } catch (error) { + console.error('预览失败:', error); + alert(`预览失败: ${error.message}`); + } + }else { + window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank'); + } + +} +const getList = async () => { + loading.value = true + const res = await getStandard(data.queryParams) + if(res.code == 200){ + data.dataList = res.data.list.map(item => { + return { + ...item, + fileNameSimple: item.fileName.split('.')[0] + } + }) + data.total = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false +} + + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + // data.queryParams.companyId = data.companyList[0].id + } else { + ElMessage.warning(res.message) + } +} + +const downloadFile = (e)=>{ + axios.get(import.meta.env.VITE_APP_BASE_API + '/' +e.filePath,{headers:{'Content-Type': 'application/json','Authorization': `${getToken()}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", e.fileName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + ElMessage({ + type: 'warning', + message: '文件读取失败' + }); + } + }) +} + +const openDialog = (type, value) => { + dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList); +} + + + + +/** 重置新增的表单以及其他数据 */ +const reset= async()=> { + if(data.isAdmin){ + data.queryParams = { + pageNum: 1, + pageSize: 10, + companyId: null, + industryType: null, + type: '', + templateName: '' + } + await getCompanyList() + }else { + data.queryParams = { + pageNum: 1, + pageSize: 10, + companyId: data.queryParams.companyId, + industryType: null, + type: '', + templateName: '' + } + } + await getList() +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delStandard(val.id) + if(res.code == 200){ + ElMessage.success('数据删除成功') + await getList() + }else{ + ElMessage.warning(res.message) + } + }) +} + + +</script> diff --git a/src/views/work/procurementPlatform/purchaseContract/components/editDialog.vue b/src/views/work/procurementPlatform/purchaseContract/components/editDialog.vue new file mode 100644 index 0000000..572dd86 --- /dev/null +++ b/src/views/work/procurementPlatform/purchaseContract/components/editDialog.vue @@ -0,0 +1,215 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="state.title" + width="600px" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" > + <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId"> + <el-select v-model="state.form.companyId" placeholder="请选择" clearable style="width: 100%"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item label="文件名称:" prop="fileName"> + <el-input v-model.trim="state.form.fileName" :disabled="state.title =='查看'" placeholder="文件名称"></el-input> + </el-form-item> + <el-form-item label="文件:" prop="filePath"> + <el-upload accept=".jpg,.jpeg,.png,.doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx" :action="state.uploadUrl" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile)" :on-exceed="showTip" :limit='state.fileLimit' v-model:file-list="state.fileList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles)" > + <el-button type="primary">点击上传</el-button> + <template #tip> + <div class="el-upload__tip">尺寸小于5M,最多可上传1张</div> + </template> + </el-upload> + </el-form-item> + </el-form> + <template #footer v-if="state.title !='查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue' +import {ElMessage} from "element-plus"; +import {addUser, editUser, getUserById, resetPwd} from "@/api/onlineEducation/user" +import {Base64} from "js-base64" +import {getCompany} from "@/api/onlineEducation/company"; +import {addIndustryTemp, updateIndustryTemp, updateInfoPlatforms} from "@/api/staffManage/staff"; +import {getToken} from "@/utils/auth"; +import {delPic} from "@/api/onlineEducation/banner"; +import {getIndustry} from "@/api/system/industry"; +import {addContract, editContract} from "@/api/procurementPlatform/procurementPlatform"; + +const emit = defineEmits(["getList"]); +const dialogVisible = ref(false) +const superRef = ref() + +const state = reactive({ + title: '', + form: { + id: null, + fileName: '', + filePath: '', + + format: '', + companyId: null, + + }, + formRules:{ + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + fileName: [{ required: true, message: '请输入文件名称', trigger: 'blur' }], + filePath: [{ required: true, message: '请上传文件', trigger: 'blur' }], + }, + isAdmin: false, + companyList: [], + industryList: [], + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/system/common/uploadFile', + header: { + Authorization: getToken() + }, + fileLimit: 1, + fileList: [] +}) +onMounted(() => { + +}); + +const openDialog = async (type, value,companyId, isAdmin, companyList) => { + state.isAdmin = isAdmin + if(isAdmin){ + state.companyList = companyList + } + state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' + state.form.companyId = companyId + if(state.title == '编辑'||state.title == '查看'){ + Object.keys(state.form).forEach(key => { + if (key in value) { + state.form[key] = value[key] + } + }) + if(value.filePath) { + const obj = { + url: value.filePath, + name: value.fileName + } + state.fileList = [obj] + } + } + dialogVisible.value = true +} + +const onSubmit = async () => { + const valid = await superRef.value.validate(); + if(valid){ + if(state.title == '新增'){ + const {id,...data} = state.form + const res = await addContract(data) + if(res.code == 200){ + ElMessage.success(res.message) + emit('getList') + handleClose() + dialogVisible.value = false; + }else{ + ElMessage.warning(res.message) + } + }else{ + const res = await editContract(state.form) + if(res.code == 200){ + ElMessage.success(res.message) + emit('getList') + handleClose() + dialogVisible.value = false; + }else{ + ElMessage.warning(res.message) + } + } + } +} + +const handleAvatarSuccess = (res, uploadFile) => { + if(res.code == 200){ + state.form.fileName = res.data.originName + state.form.filePath = res.data.path + }else{ + state.fileList = [] + ElMessage({ + type: 'warning', + message: '文件上传失败' + }) + } +} + +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; +const handleRemove = async (file, uploadFiles) => { + let path = state.form.filePath; + await delPic({path: path}).then(res => { + if(res.code == 200){ + state.form.filePath = '' + state.form.fileName = '' + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } + }).catch(() => { + }); +} + +const handleClose = () => { + state.form = { + id: null, + filePath: '', + fileName: '', + companyId: null, + } + state.fileList = [] + superRef.value.clearValidate(); + superRef.value.resetFields() + dialogVisible.value = false; +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/work/procurementPlatform/purchaseContract/index.vue b/src/views/work/procurementPlatform/purchaseContract/index.vue new file mode 100644 index 0000000..8eb2eb6 --- /dev/null +++ b/src/views/work/procurementPlatform/purchaseContract/index.vue @@ -0,0 +1,266 @@ +<template> + <div class="app-container"> + <div style="display: flex;justify-content: space-between"> + <el-form :inline="true" style="display: flex;align-items: center;flex-wrap: wrap;" > + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item v-if="isAdmin" label="企业:" > + <el-select v-model="data.queryParams.companyId" placeholder="请选择" clearable> + <el-option + v-for="item in companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="isAdmin"> + <el-button type="primary" @click="getList">查询</el-button> + <el-button type="primary" plain @click="reset">重置</el-button> + </el-form-item> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true"> + <el-table-column label="序号" type="index" align="center" width="80"/> + <el-table-column label="文件名称" prop="fileNameSimple" align="center"/> + <el-table-column label="文件" prop="fileName" align="center"> + <template #default="scope"> + <el-link style="" type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName}}</el-link> + </template> + </el-table-column> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="downloadFile(scope.row)">下载</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)">编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + v-model:page="queryParams.pageNum" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + + <edit-dialog ref="dialogRef" @getList=getList></edit-dialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, onUnmounted, reactive, ref, toRefs} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {delCompany, getCompany} from "@/api/onlineEducation/company"; +import { Plus, Upload, Download} from '@element-plus/icons-vue'; +import {delUser, getUser} from "@/api/onlineEducation/user"; +import Cookies from "js-cookie"; +import editDialog from './components/editDialog.vue' +import { + delIndustryTemp, + getIndustryTemp, uploadTemplate, +} from "@/api/staffManage/staff"; +import useUserStore from "@/store/modules/user"; +import axios from "axios"; +import {getToken} from "@/utils/auth"; +import {getIndustry} from "@/api/system/industry"; +import {renderAsync} from "docx-preview"; +import {delContract, getContract} from "@/api/procurementPlatform/procurementPlatform"; +const userStore = useUserStore() +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const dialogRef = ref(); + +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + industryType: null, + type: '', + templateName: '' + }, + total: 0, + dataList: [], + companyList: [], + industryList: [], + isAdmin: false, + typeList: [], + exportDialog: false, + +}); + +const { queryParams, total, dataList,companyList,industryList, isAdmin } = toRefs(data); +const userInfo = ref() +onMounted(async ()=>{ + if(userStore.roles.includes('admin')){ + data.isAdmin = true + data.queryParams.companyId = null + await getCompanyList() + }else{ + data.isAdmin = false + data.queryParams.companyId = userStore.companyId + } + await getList() +}) + +onUnmounted(()=>{ + +}) +const openFile = async(path)=>{ + const ext = path.split('.').pop().toLowerCase(); + if (ext === 'doc' || ext === 'xls' || ext === 'xlsx' || ext === 'ppt' || ext === 'pptx') { + ElMessageBox.confirm('暂不支持线上预览文件,是否下载查看?', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => { + window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank'); + }).catch(() => { + console.log('取消预览') + }); + return + } + if(ext === 'docx'){ + try { + // 1. 获取文件 + const response = await fetch(import.meta.env.VITE_APP_BASE_API + '/' + path); + const arrayBuffer = await response.arrayBuffer(); + // 2. 创建新窗口 + const win = window.open('', '_blank') + win.document.write(` + <!DOCTYPE html> + <html> + <head> + <title>预览</title> + <style> + body { margin: 20px; font-family: Arial; } + .docx-container { width: 100%; height: 100%; } + </style> + </head> + <body> + <div id="container" class="docx-container"></div> + </body> + </html> + `); + // 3. 渲染 DOCX + await renderAsync(arrayBuffer, win.document.getElementById('container')); + + } catch (error) { + console.error('预览失败:', error); + alert(`预览失败: ${error.message}`); + } + }else { + window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank'); + } + +} +const getList = async () => { + loading.value = true + const res = await getContract(data.queryParams) + if(res.code == 200){ + data.dataList = res.data.list.map(item => { + return { + ...item, + fileNameSimple: item.fileName.split('.')[0] + } + }) + data.total = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false +} + + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + // data.queryParams.companyId = data.companyList[0].id + } else { + ElMessage.warning(res.message) + } +} + +const downloadFile = (e)=>{ + axios.get(import.meta.env.VITE_APP_BASE_API + '/' +e.filePath,{headers:{'Content-Type': 'application/json','Authorization': `${getToken()}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", e.fileName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + ElMessage({ + type: 'warning', + message: '文件读取失败' + }); + } + }) +} + +const openDialog = (type, value) => { + dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList); +} + + + + +/** 重置新增的表单以及其他数据 */ +const reset= async()=> { + if(data.isAdmin){ + data.queryParams = { + pageNum: 1, + pageSize: 10, + companyId: null, + industryType: null, + type: '', + templateName: '' + } + await getCompanyList() + }else { + data.queryParams = { + pageNum: 1, + pageSize: 10, + companyId: data.queryParams.companyId, + industryType: null, + type: '', + templateName: '' + } + } + await getList() +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delContract(val.id) + if(res.code == 200){ + ElMessage.success('数据删除成功') + await getList() + }else{ + ElMessage.warning(res.message) + } + }) +} + + +</script> diff --git a/src/views/work/procurementPlatform/purchaseRequisition/components/editDialog.vue b/src/views/work/procurementPlatform/purchaseRequisition/components/editDialog.vue new file mode 100644 index 0000000..1e11f93 --- /dev/null +++ b/src/views/work/procurementPlatform/purchaseRequisition/components/editDialog.vue @@ -0,0 +1,500 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="50%" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules" > + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin"> + <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="申购单名称:" prop="applyName" > + <el-input :disabled="title === '查看'" v-model="state.form.applyName" placeholder="请输入"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="申请部门:" prop="deptId" > + <el-select + :disabled="title === '查看'" + v-model="state.form.deptId" + placeholder="请选择部门" + style="width: 240px" + > + <el-option + v-for="item in state.deptList" + :key="item.deptId" + :label="item.deptName" + :value="item.deptId" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="申请日期:" prop="applyTime" > + <el-date-picker + :disabled="title === '查看'" + v-model="state.form.applyTime" + type="date" + placeholder="请选择日期" + style="width: 100%" + /> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="申请理由:" prop="applyReason" > + <el-input :disabled="title === '查看'" :rows="2" type="textarea" v-model="state.form.applyReason" placeholder="请输入"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="申请人:" prop="applyUser" > + <el-select clearable v-model="state.form.applyUser" :disabled="title =='查看'" filterable style="width: 100%"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="直属部门领导:" prop="deptUser" > + <el-select clearable v-model="state.form.deptUser" :disabled="title =='查看'" filterable style="width: 100%"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="财务部:" prop="financeUser" > + <el-select clearable v-model="state.form.financeUser" :disabled="title =='查看'" filterable style="width: 100%"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <div style="display: flex;align-items: center;margin-bottom: 10px"> + <span style="font-size: 15px;font-weight: 700;" >采购计划:</span> + <el-button + :disabled="title === '查看'" + type="primary" + @click="addTableData" + style="margin-left: 20px" + >新增</el-button> + </div> + <el-table + ref="tableRef" + :data="state.form.purchaseApplyPlans" + show-summary + :summary-method="getSummaries" + style="margin-bottom: 10px" + :border="true" + + > + <el-table-column type="index" label="序号" width="80" align="center"></el-table-column> + <el-table-column label="品名" prop="name" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'purchaseApplyPlans.' + '[' + $index + ']' + '.name'" :rules="state.rules.name"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.name" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="型号规格" prop="model" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'purchaseApplyPlans.' + '[' + $index + ']' + '.model'" :rules="state.rules.model"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.model" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="建议供应商" prop="supplier" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'purchaseApplyPlans.' + '[' + $index + ']' + '.supplier'" :rules="state.rules.supplier"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.supplier" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="数量" prop="amount" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'purchaseApplyPlans.' + '[' + $index + ']' + '.amount'" :rules="state.rules.amount"> + <el-input + :disabled="title === '查看'" + v-model.trim.number="row.amount" + placeholder="请输入" + @input="debouncedUpdate" + @blur="handleBlur(row, 'amount')" + > + </el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="预计单价" prop="money" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'purchaseApplyPlans.' + '[' + $index + ']' + '.money'" :rules="state.rules.money"> + <el-input + :disabled="title === '查看'" + v-model="row.money" + placeholder="请输入" + @change="debouncedUpdate" + @input="row.money= row.money.replace(/[^\d.]/g, '') .replace(/\.+/g, '.').replace(/^\./, '0.').replace(/^(\d*\.?\d{0,2}).*/, '$1')" + @blur="handleBlur(row, 'money')" + > + </el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="分类" prop="solutions" align="center" width="150"> + <template #default="{row,$index}"> + <el-form-item :prop="'purchaseApplyPlans.' + '[' + $index + ']' + '.type'" :rules="state.rules.type"> + <el-input style="margin-top: 10px" :disabled="title === '查看'" :rows="2" type="textarea" v-model="row.type" placeholder="请输入"></el-input> + </el-form-item> + </template> + </el-table-column> + <el-table-column label="操作" align="center" v-if="title !== '查看'" > + <template #default="scope"> + <el-button link type="danger" @click="delTableData(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + </el-col> + </el-row> + </el-form> + <template #footer v-if="title !== '查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {computed, onMounted, reactive, ref, toRefs} from 'vue' +import Cookies from "js-cookie"; +import {getCompany} from "@/api/onlineEducation/company"; +import {ElMessage} from "element-plus"; +import {getUser} from "@/api/onlineEducation/user"; +import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object"; +import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table"; +import {addNeedDiscren, editNeedDiscren} from "@/api/need/need"; +import {debounce} from "@/utils"; +import {addApply, editApply} from "@/api/procurementPlatform/procurementPlatform"; + +const dialogVisible = ref(false); +const title = ref(""); +const busRef = ref(); +const length = ref() +const selectPopperClass = "max-width-select"; +const emit = defineEmits(["getList"]); +const dataRef = ref(); +const tableRef = ref(); +const state = reactive({ + form: { + id: '', + companyId: null, + deptId: null, + applyName: '', + applyTime: null, + applyReason: null, + applyUser: null, + deptUser: null, + financeUser: '', + purchaseApplyPlans:[], + }, + rules: { + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + deptId: [{ required: true, message: '请选择部门', trigger: 'blur' }], + applyName: [{ required: true, message: '请输入申购单名称', trigger: 'blur' }], + applyTime: [{ required: true, message: '请选择申请日期', trigger: 'blur' }], + applyReason: [{ required: true, message: '请输入申请理由', trigger: 'blur' }], + applyUser: [{ required: true, message: '请选择申请人', trigger: 'blur' }], + deptUser: [{ required: true, message: '请选择直属部门领导', trigger: 'blur' }], + financeUser: [{ required: true, message: '请选择财务部人员', trigger: 'blur' }], + name: [{required: true, message: "", trigger: "blur"}], + model: [{required: true, message: "", trigger: "blur"}], + supplier: [{required: true, message: "", trigger: "blur"}], + amount: [{required: true, message: "", trigger: "blur"}], + money: [{required: true, message: "", trigger: "blur"}], + type: [{required: true, message: "", trigger: "blur"}], + }, + peopleList: [], + isAdmin: false, + companyList: [], + deptList: [], +}) + +onMounted(() => { + + +}); + + +const openDialog = async (type, value,companyList) => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + state.isAdmin = userInfo.userType === 0; + state.form.companyName = userInfo.companyName + state.form.companyId = userInfo.companyId + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + state.companyList = companyList + } + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ; + if(type === 'edit' || type === 'review') { + state.form = JSON.parse(JSON.stringify(value)); + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + } + } + await getDeptList() + await getPeopleList() + dialogVisible.value = true; +} + +const getDeptList = async () => { + if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){ + return + } + const param = { + pageNum: 1, + pageSize: 999, + companyId: state.form.companyId + } + const res = await getDept(param) + if(res.code === 200){ + state.deptList = res.data + } +} +const onSubmit = async () => { + + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + console.log('sta',state.form) + const {id, ...data} = JSON.parse(JSON.stringify(state.form)) + const res = await addApply(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + }else if(title.value === '编辑'){ + state.form.purchaseApplyPlans.forEach(item => { + item.applyId = state.form.id + }) + const {...data} = JSON.parse(JSON.stringify(state.form)) + const res = await editApply(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '编辑成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + emit("getList") + +} +const reset = () => { + state.form = { + id: '', + companyId: null, + deptId: null, + year: '', + fictionId: null, + checkId: null, + ratifyId: null, + fictionTime: null, + frequency: '', + purchaseApplyPlans:[], + } + state.deptList = [] + state.peopleList = [] + state.companyList = [] +} +const getPeopleList = async ()=> { + if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){ + return + } + const queryParams = { + pageNum: 1, + pageSize: 9999, + companyId: state.form.companyId + } + const res = await getUser(queryParams) + if(res.code == 200){ + state.peopleList = res.data.list?res.data.list:[] + }else{ + ElMessage.warning(res.message) + } +}; + + + +const selectValueCom = (val) => { + state.form.applyUser = null + state.form.deptUser = null + state.form.financeUser = null + state.form.deptId = null + state.companyList.forEach(item => { + if(item.name === val){ + state.form.companyId = item.id + } + }) + getDeptList() + getPeopleList() +} + +const handleChangeNum = (value) => { + if (!/^\d+$/.test(value)) { // 验证是否为数字 + ElMessage.warning('只能输入数字') + state.form.year = '' // 重置选择,避免非法值被添加到options中 + } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项 + state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同) + } +} +// const addTableData = () => { +// state.form.purchaseApplyPlans.push({}) +// } +// const delTableData = (val) => { +// state.form.purchaseApplyPlans = state.form.purchaseApplyPlans.filter(item=> item != val) +// } + + +const summaryData = computed(() => { + return state.form.purchaseApplyPlans.reduce((acc, row) => { + const money = Number(row.money) || 0 + const quantity = Number(row.amount) || 0 + acc.money += money + acc.amount += quantity + return acc + }, { + money: 0, + amount: 0, + }) +}) +// 格式化货币显示 +const formatCurrency = (value) => { + return '¥' + (Number(value) || 0).toFixed(2) +} +// 自定义合计行方法 +const getSummaries = ({ columns }) => { + const sums = [] + const data = summaryData.value + columns.forEach((column, index) => { + if (index === 0) { + sums[index] = `合计` + return + } + switch (column.property) { + case 'money': + sums[index] = `${formatCurrency(data.money)}` + break + case 'amount': + sums[index] = data.amount + break + default: + sums[index] = '' + } + }) + + return sums +} +// 防抖更新 - 防止频繁触发重计算 +const debouncedUpdate = debounce(() => { + // 强制更新表格布局 + tableRef.value?.doLayout() +}, 300) + +// 输入框失去焦点时的处理 +const handleBlur = (row, field) => { + row[field] = Number(row[field]) || 0 + debouncedUpdate() +} +// 添加新行 +const addTableData = () => { + state.form.purchaseApplyPlans.push({ + money: null, + amount: null + }) + + debouncedUpdate() +} +// 删除行 +const delTableData = (index) => { + state.form.purchaseApplyPlans.splice(index, 1) + debouncedUpdate() +} + + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/work/procurementPlatform/purchaseRequisition/index.vue b/src/views/work/procurementPlatform/purchaseRequisition/index.vue new file mode 100644 index 0000000..6f4b804 --- /dev/null +++ b/src/views/work/procurementPlatform/purchaseRequisition/index.vue @@ -0,0 +1,286 @@ +<template> + <div class="app-container"> + <div style="margin-bottom: 10px"> + <el-form style="display: flex;flex-wrap: wrap;"> + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px"> + <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable> + <el-option + v-for="item in data.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="data.isAdmin"> + <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </el-form-item> + <el-form-item style="margin-left: 15px"> + <el-button + type="primary" + @click="exportData" + >导出</el-button> + </el-form-item> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column type="index" label="序号" width="80" align="center"></el-table-column> + <el-table-column label="申购单名称" prop="applyName" align="center" /> + <el-table-column label="申请部门" prop="deptName" align="center" /> + <el-table-column label="申请人" prop="applyUserName" align="center" /> + <el-table-column label="操作" align="center" class-naame="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + + <div class="pag-container"> + <el-pagination + v-model:current-page="data.queryParams.pageNum" + v-model:page-size="data.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <editDialog ref="noticeRef" @getList = "getList"></editDialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue"; +import editDialog from "./components/editDialog.vue" +import {ElMessage, ElMessageBox} from "element-plus"; +import {getCompany} from "@/api/onlineEducation/company"; +import Cookies from "js-cookie"; +import {generateWordDocument} from "@/utils/exportWord"; +import {delTable, getTable} from "@/api/qualityObjectives/table"; +import {delDiscern, getDiscern} from "@/api/environment/factors"; +import {delApply, getApply} from "@/api/procurementPlatform/procurementPlatform"; +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const noticeRef = ref(); +const deptRef = ref() +const loadingCompany = ref(false) +const choosedData = ref([]) +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + year: '', + type: '' + }, + companyList: [], + isAdmin: false, + dialogVisible: false, + yearList: [ + { + value: 1, + label: '2025' + }, + { + value: 2, + label: '2024' + }, + { + value: 3, + label: '2023' + }, + { + value: 4, + label: '2022' + }, + { + value: 5, + label: '2021' + }, + ], +}); +const dataList = ref([]); +const total = ref(0); + +const { queryParams } = toRefs(data); + +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + console.log("userInfo",userInfo) + data.isAdmin = userInfo.userType === 0; + if(data.isAdmin){ + data.queryParams.companyId = null + }else { + data.queryParams.companyId = userInfo.companyId + } + getList(); + if(data.isAdmin){ + getCompanyList() + } +}); +const getList = async () => { + loading.value = true; + const res = await getApply(data.queryParams); + if(res.code === 200){ + dataList.value = res.data.list + total.value = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false; +} + +const searchClick = () => { + getList(); +} + +const openDialog = (type, value) => { + noticeRef.value.openDialog(type, value,data.companyList); +} + +const selectValue = (val) => { + data.companyList.forEach(item => { + if(item.name === val){ + data.queryParams.companyId = item.id + } + }) +} + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + } else { + ElMessage.warning(res.message) + } +} + +const handleSizeChange = (val) => { + data.queryParams.pageSize = val + getList() +} +const handleCurrentChange = (val) => { + data.queryParams.pageNum = val + getList() +} +const handleClose = () => { + data.dialogVisible = false +} + +/** 重置新增的表单以及其他数据 */ +function reset() { + if(data.isAdmin){ + data.queryParams = { + companyId: '', + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + choosedData.value = [] + data.companyList = []; + getCompanyList() + }else { + data.queryParams = { + companyId: data.queryParams.companyId, + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + } + getList(); + +} +const exportData = () => { + if(choosedData.value && choosedData.value.length === 0){ + ElMessage.warning('请选择需要导出的数据') + }else { + startGeneration() + } +} +const templatePath = ref('/purchaseRequisitionExample.docx') +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(choosedData.value)) + let amountSum = 0 + let moneySum = 0 + data.forEach(item => { + amountSum = 0 + moneySum = 0 + item.applyTime = item.applyTime.substring(0,10) + item.purchaseApplyPlans.forEach(i => { + amountSum += i.amount + moneySum += i.money + }) + item.amountSum = amountSum + item.moneySum = moneySum.toFixed(2) + item.tableList = item.purchaseApplyPlans.map((item,index) => { + return { + ...item, + num: index +1 , + } + }) + + try { + generateWordDocument(templatePath.value, item, item.companyName+`_采购申请单.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '导出失败' + }); + } + }) +} + +const handleSelectionChange = (val) => { + choosedData.value = val +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delApply(val.id); + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '删除成功' + }); + getList(); + }else{ + ElMessage.warning(res.message) + } + }) +} + + +</script> +<style lang="scss"> +.pag-container{ + float: right; + margin-top: 10px; +} +</style> diff --git a/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/components/editDialog.vue b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/components/editDialog.vue new file mode 100644 index 0000000..49fa348 --- /dev/null +++ b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/components/editDialog.vue @@ -0,0 +1,391 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="700px" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules" > + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin"> + <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="问卷名称:" prop="questionName" > + <el-input :disabled="title === '查看'" v-model="state.form.questionName" placeholder="问卷名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="编号:" prop="number" > + <el-input :disabled="title === '查看'" v-model="state.form.number" placeholder="编号"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="单位名称:" prop="unitName" > + <el-input :disabled="title === '查看'" v-model="state.form.unitName" placeholder="单位名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="联系人:" prop="person" > + <el-input :disabled="title === '查看'" v-model="state.form.person" placeholder="联系人"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="联系地址:" prop="address" > + <el-input :disabled="title === '查看'" v-model="state.form.address" placeholder="联系地址"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="电话、传真:" prop="phone" > + <el-input :disabled="title === '查看'" v-model="state.form.phone" placeholder="电话、传真"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <div style="display:flex;flex-direction: column"> + <span style="font-size: 11px;font-weight: 700;margin-bottom: 5px" >贵单位使用我所何种类型的产品(可多选,在相应的选项“⬜︎︎︎”内打“√”):</span> + <el-checkbox-group v-model="state.checkProductTypes" size="small" :disabled="title === '查看'" style="display:flex;flex-wrap: wrap;margin-left: 20px"> + <div v-for="item in state.productTypeList"> + <el-checkbox :label="item.id" :key="item.id" style="margin-left: 20px;">{{item.name}}</el-checkbox> + </div> + </el-checkbox-group> + </div> + <div style="display: flex;align-items: center;margin-top: 5px"> + <span style="font-size: 11px;font-weight: 700;margin-bottom: 5px;margin-right: 10px" >请注明产品的名称(如有保密情况可以不填):</span> + <el-input style="width: 200px;" size="small" :disabled="title === '查看'" v-model="state.form.productName"></el-input> + </div> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-table style="margin: 20px 0" :data="state.dataList" :border="true"> + <el-table-column label="序号" width="80" prop="num" align="center"></el-table-column> + <el-table-column label="调查项目" prop="item" align="center" > + <template #default="scope"> + <div v-if="scope.row.num == '说明'"> + <span>{{scope.row.item}}</span> + </div> + <div v-else style="display: flex;align-items: center"> + <span v-if="scope.row.num == 1" style="width: 210px">交付产品质量:</span> + <span v-if="scope.row.num == 2" style="width: 210px">项目进度的符合性:</span> + <span v-if="scope.row.num == 3" style="width: 210px">售后服务情况:</span> + <span v-if="scope.row.num == 4" style="width: 210px">技术/售后服务人员:</span> + <span v-if="scope.row.num == 5" style="width: 210px">市场人员服务与跟踪意识:</span> + <el-checkbox-group v-model="scope.row.checkItem" size="small" :disabled="title === '查看'" style="display:flex;flex-wrap: wrap;width: 600px;margin-left: 10px"> + <div v-for="item in scope.row.item"> + <el-checkbox style="margin-right: 15px" :label="item" :key="item" >{{item}}</el-checkbox> + </div> + </el-checkbox-group> + </div> + </template> + </el-table-column> + <el-table-column label="满意度" prop="satisfied" align="center" > + <template #default="scope"> + <div v-if="scope.row.num == '说明'"> + <span>{{scope.row.satisfied}}</span> + </div> + <el-radio-group v-else v-model="scope.row.check" size="small" :disabled="title === '查看'" style="display:flex;flex-wrap: wrap;margin-left: 20px"> + <div v-for="item in scope.row.satisfied"> + <el-radio style="margin-right: 15px" :label="item" :key="item" >{{item}}</el-radio> + </div> + </el-radio-group> + </template> + </el-table-column> + </el-table> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <span style="font-size: 12px;font-weight: 700;margin-bottom: 5px" >重点说明不满意的原因以及其他意见、要求或建议,如同类产品的差距、市场信息、改进的建议等:</span> + <el-input style="margin-top: 5px" :disabled="title === '查看'" v-model="state.form.suggest" type="textarea" :rows="4"></el-input> + </el-col> + </el-row> + </el-form> + <template #footer v-if="title !== '查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {onMounted, reactive, ref, toRefs} from 'vue' +import Cookies from "js-cookie"; +import {getCompany} from "@/api/onlineEducation/company"; +import {ElMessage} from "element-plus"; +import {getUser} from "@/api/onlineEducation/user"; +import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object"; +import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table"; +import {addNeedDiscren, editNeedDiscren} from "@/api/need/need"; +import {verifyPhone} from "@/utils/validate"; +import {developList} from "@/views/work/qualityInfo/supplierQuality/supplierList/components/qualityDatas"; +import {addDelivery, editDelivery} from "@/api/satisfiedNew/satisfiedNew"; + +const dialogVisible = ref(false); +const title = ref(""); +const busRef = ref(); +const length = ref() +const selectPopperClass = "max-width-select"; +const emit = defineEmits(["getList"]); +const dataRef = ref(); +const validatePhone = (rule, value, callback)=>{ + if(value === ''){ + callback(new Error('请输入手机号')) + }else{ + if(!verifyPhone(value)){ + callback(new Error('手机号格式有误')) + }else{ + callback() + } + } +} +const state = reactive({ + form: { + id: '', + companyId: null, + questionName: null, + number: '', + unitName: null, + person: null, + address: null, + phone: null, + product: '', + productName:'', + mess: '', + suggest: '' + }, + rules: { + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + questionName: [{ required: true, message: '请输入问卷名称', trigger: 'blur' }], + number: [{ required: true, message: '请输入编号', trigger: 'blur' }], + unitName: [{ required: true, message: '请输入单位名称', trigger: 'blur' }], + person: [{ required: true, message: '请输入联系人', trigger: 'blur' }], + address: [{ required: true, message: '请输入联系地址', trigger: 'blur' }], + product: [{ required: true, message: '请选择产品', trigger: 'blur' }], + phone: [{required: true, trigger: "blur", validator: validatePhone}], + + }, + isAdmin: false, + companyList: [], + dataList: [ + { + num: '说明', + item: '哪项不满意,请在相应的选项“⬜︎︎︎”内打“√”', + satisfied:'总体评价,请在相应的选项“⬜︎︎︎”内打“√”' + }, + { + num: '1', + item: ['产品性能','技术资料','操作性','维护性','稳定性'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '2', + item: ['节点控制','交付及时性','可靠性'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '3', + item: ['顾客培训','技术支持','售后维修','备品及备件供应'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '4', + item: ['技术技能','服务态度','过程规范','综合素质'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '5', + item: ['服务的及时性','有效性','服务态度'], + satisfied:['满意','基本满意','不满意'] + }, + ], + productTypeList: [ + { + id: 1, + name: '系统' + }, + { + id: 2, + name: '软件' + }, + { + id: 3, + name: '整机' + }, + { + id: 4, + name: '试剂柜' + }, + { + id: 5, + name: '印制板' + }, + { + id: 6, + name: '手持终端' + }, + { + id: 7, + name: '其他' + }, + ], + checkProductTypes: [] +}) + +onMounted(() => { + + +}); +const openDialog = async (type, value,companyList) => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + state.isAdmin = userInfo.userType === 0; + state.form.companyName = userInfo.companyName + state.form.companyId = userInfo.companyId + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + state.companyList = companyList + } + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ; + if(type === 'edit' || type === 'review') { + state.form = JSON.parse(JSON.stringify(value)); + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + } + //解析json + state.dataList = JSON.parse(value.mess) + state.checkProductTypes = value.product.split(',').map(Number) + } + dialogVisible.value = true; +} + +const onSubmit = async () => { + state.form.mess = JSON.stringify(state.dataList) + state.form.product = state.checkProductTypes.join(',') + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + console.log('sta',state.form) + const {id, ...data} = JSON.parse(JSON.stringify(state.form)) + const res = await addDelivery(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + }else if(title.value === '编辑'){ + const {...data} = JSON.parse(JSON.stringify(state.form)) + const res = await editDelivery(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '编辑成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + emit("getList") + +} +const reset = () => { + state.form = { + id: '', + companyId: null, + deptId: null, + year: '', + fictionId: null, + checkId: null, + ratifyId: null, + fictionTime: null, + frequency: '', + expectContents:[], + } + state.checkProductTypes = [] + state.companyList = [] +} + + + +const selectValueCom = (val) => { + state.form.fictionId = null + state.form.checkId = null + state.form.ratifyId = null + state.form.deptId = null + state.companyList.forEach(item => { + if(item.name === val){ + state.form.companyId = item.id + } + }) +} + +const handleChangeNum = (value) => { + if (!/^\d+$/.test(value)) { // 验证是否为数字 + ElMessage.warning('只能输入数字') + state.form.year = '' // 重置选择,避免非法值被添加到options中 + } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项 + state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同) + } +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + :deep(.el-table .cell){ + font-size: small; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/index.vue b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/index.vue new file mode 100644 index 0000000..f2acac4 --- /dev/null +++ b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/deliver/index.vue @@ -0,0 +1,270 @@ +<template> + <div class="app-container"> + <div style="margin-bottom: 10px"> + <el-form style="display: flex;flex-wrap: wrap;"> + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px"> + <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable> + <el-option + v-for="item in data.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="data.isAdmin"> + <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </el-form-item> +<!-- <el-form-item style="margin-left: 15px">--> +<!-- <el-button--> +<!-- type="primary"--> +<!-- @click="exportData"--> +<!-- >导出</el-button>--> +<!-- </el-form-item>--> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange"> +<!-- <el-table-column type="selection" width="55" />--> + <el-table-column type="index" label="序号" width="80" align="center"></el-table-column> + <el-table-column label="名称" prop="questionName" align="center" /> + <el-table-column label="操作" align="center" class-naame="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + + <div class="pag-container"> + <el-pagination + v-model:current-page="data.queryParams.pageNum" + v-model:page-size="data.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <editDialog ref="noticeRef" @getList = "getList"></editDialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue"; +import editDialog from "./components/editDialog.vue" +import {ElMessage, ElMessageBox} from "element-plus"; +import {getCompany} from "@/api/onlineEducation/company"; +import Cookies from "js-cookie"; +import {generateWordDocument} from "@/utils/exportWord"; +import {delTable, getTable} from "@/api/qualityObjectives/table"; +import {delDiscern, getDiscern} from "@/api/environment/factors"; +import {delDelivery, getDelivery} from "@/api/satisfiedNew/satisfiedNew"; +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const noticeRef = ref(); +const deptRef = ref() +const loadingCompany = ref(false) +const choosedData = ref([]) +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + year: '', + type: '' + }, + companyList: [], + isAdmin: false, + dialogVisible: false, +}); +const dataList = ref([]); +const total = ref(0); + +const { queryParams } = toRefs(data); + +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + console.log("userInfo",userInfo) + data.isAdmin = userInfo.userType === 0; + if(data.isAdmin){ + data.queryParams.companyId = null + }else { + data.queryParams.companyId = userInfo.companyId + } + getList(); + if(data.isAdmin){ + getCompanyList() + } +}); +const getList = async () => { + loading.value = true; + const res = await getDelivery(data.queryParams); + if(res.code === 200){ + dataList.value = res.data.list + total.value = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false; +} + +const searchClick = () => { + getList(); +} + +const openDialog = (type, value) => { + noticeRef.value.openDialog(type, value,data.companyList); +} + +const selectValue = (val) => { + data.companyList.forEach(item => { + if(item.name === val){ + data.queryParams.companyId = item.id + } + }) +} + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + } else { + ElMessage.warning(res.message) + } +} + +const handleSizeChange = (val) => { + data.queryParams.pageSize = val + getList() +} +const handleCurrentChange = (val) => { + data.queryParams.pageNum = val + getList() +} +const handleClose = () => { + data.dialogVisible = false +} + +/** 重置新增的表单以及其他数据 */ +function reset() { + if(data.isAdmin){ + data.queryParams = { + companyId: '', + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + choosedData.value = [] + data.companyList = []; + getCompanyList() + }else { + data.queryParams = { + companyId: data.queryParams.companyId, + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + } + getList(); + +} +const exportData = () => { + if(choosedData.value && choosedData.value.length === 0){ + ElMessage.warning('请选择需要导出的数据') + }else { + startGeneration() + } +} +const templatePath = ref('/environmentalFactorsExample.docx') +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(choosedData.value)) + data.forEach(item => { + item.fictionTime = item.fictionTime.substring(0,10) + console.log('u',item) + const datax = idGroupToTree(item.factorContents) + item.tableList = datax.map((item,index) => { + return { + ...item, + fileList: item.children.map((f,findex) => { + return{ + ...f, + first: findex == 0, + typeName: f.type == 1 ? '外部环境' : '内部环境' + } + }) + } + }) + console.log(' item.tableList', item.tableList) + try { + generateWordDocument(templatePath.value, item, item.companyName+`_${item.year}年内、外部环境要素识别表.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '导出失败' + }); + } + }) +} +function idGroupToTree(data) { + const groups = data.reduce((map, item) => { + map.has(item.type) || map.set(item.type, []); + map.get(item.type).push(item); + return map; + }, new Map()); + return Array.from(groups).map(([type, items]) => ({ + type, + children: items + })); +} +const handleSelectionChange = (val) => { + choosedData.value = val +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delDelivery(val.id); + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '删除成功' + }); + await getList(); + }else{ + ElMessage.warning(res.message) + } + }) +} + + +</script> +<style lang="scss"> +.pag-container{ + float: right; + margin-top: 10px; +} +</style> diff --git a/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/components/editDialog.vue b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/components/editDialog.vue new file mode 100644 index 0000000..7721461 --- /dev/null +++ b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/components/editDialog.vue @@ -0,0 +1,390 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="800px" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules" label-position="left" label-width="135"> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin"> + <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="报告名称:" prop="reportName" > + <el-input :disabled="title === '查看'" v-model="state.form.reportName" placeholder="报告名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="编号:" prop="number" > + <el-input :disabled="title === '查看'" v-model="state.form.number" placeholder="编号"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="实施调查的部门:" prop="deptId" > + <el-select v-model="state.form.deptId" placeholder="请选择" :disabled="title === '查看'" clearable> + <el-option + v-for="item in state.deptList" + :key="item.deptId" + :label="item.deptName" + :value="item.deptId"> + </el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="调查结束日期:" prop="endTime" > + <el-date-picker + :disabled="title === '查看'" + v-model="state.form.endTime" + type="date" + placeholder="请选择" + /> + </el-form-item> + </el-col> + </el-row> + <div style="text-align: center;font-weight: 600;font-size: 18px;margin-bottom: 15px">调查情况</div> + <el-row :gutter="24"> + <el-col :span="8"> + <el-form-item label="问卷发放数:" prop="grantAmount" > + <el-input :disabled="title === '查看'" v-model="state.form.grantAmount" placeholder="问卷发放数"></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="问卷回收数:" prop="recycleAmount" > + <el-input :disabled="title === '查看'" v-model="state.form.recycleAmount" placeholder="问卷回收数"></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="回收率:" prop="recycleRate" > + <el-input :disabled="title === '查看'" v-model="state.form.recycleRate" placeholder="回收率"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="8"> + <el-form-item label="检查的项目总数:" prop="checkAmount" > + <el-input :disabled="title === '查看'" v-model="state.form.checkAmount" placeholder="检查的项目总数"></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="今年项目覆盖率:" prop="yearRate" > + <el-input :disabled="title === '查看'" v-model="state.form.yearRate" placeholder="今年项目覆盖率"></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="以往项目覆盖率:" prop="ancientlyRate" > + <el-input :disabled="title === '查看'" v-model="state.form.ancientlyRate" placeholder="以往项目覆盖率"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="8"> + <el-form-item label="在研项目顾客满意度:" prop="researchSatisficing" > + <el-input :disabled="title === '查看'" v-model="state.form.researchSatisficing" placeholder="在研项目顾客满意度"></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="交付项目顾客满意度:" prop="deliverySatisficing" > + <el-input :disabled="title === '查看'" v-model="state.form.deliverySatisficing" placeholder="交付项目顾客满意度"></el-input> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="总体顾客满意度:" prop="sumSatisficing" > + <el-input :disabled="title === '查看'" v-model="state.form.sumSatisficing" placeholder="总体顾客满意度"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24" style="margin-top: 15px"> + <el-col :span="24" > + <span style="font-size: 14px;font-weight: 700;" >用户反馈的主要意见和建议:</span> + <el-input style="margin-top: 5px" :disabled="title === '查看'" v-model="state.form.suggest" type="textarea" :rows="4"></el-input> + </el-col> + </el-row> + <el-row :gutter="24" style="margin-top: 15px"> + <el-col :span="24"> + <el-form-item label="经办人:" prop="agentId" > + <el-select clearable v-model="state.form.agentId" :disabled="title =='查看'" filterable style="width: 240px"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="部门领导:" prop="deptUser" > + <el-select clearable v-model="state.form.deptUser" :disabled="title =='查看'" filterable style="width: 240px"> + <el-option + v-for="item in state.peopleList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer v-if="title !== '查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {onMounted, reactive, ref, toRefs} from 'vue' +import Cookies from "js-cookie"; +import {getCompany} from "@/api/onlineEducation/company"; +import {ElMessage} from "element-plus"; +import {getUser} from "@/api/onlineEducation/user"; +import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object"; +import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table"; +import {addNeedDiscren, editNeedDiscren} from "@/api/need/need"; +import {verifyPhone} from "@/utils/validate"; +import {developList} from "@/views/work/qualityInfo/supplierQuality/supplierList/components/qualityDatas"; +import {getDepart} from "@/api/orgStructure/depart"; +import {addReport, editReport} from "@/api/satisfiedNew/satisfiedNew"; + +const dialogVisible = ref(false); +const title = ref(""); +const busRef = ref(); +const length = ref() +const selectPopperClass = "max-width-select"; +const emit = defineEmits(["getList"]); +const dataRef = ref(); +const validatePhone = (rule, value, callback)=>{ + if(value === ''){ + callback(new Error('请输入手机号')) + }else{ + if(!verifyPhone(value)){ + callback(new Error('手机号格式有误')) + }else{ + callback() + } + } +} +const state = reactive({ + form: { + id: '', + companyId: null, + deptId: null, + reportName: '', + number: null, + endTime: null, + grantAmount: null, + recycleAmount: null, + recycleRate: '', + checkAmount:'', + yearRate:'', + ancientlyRate:'', + researchSatisficing:'', + deliverySatisficing:'', + sumSatisficing:'', + suggest:'', + agentId:'', + deptUser:'', + }, + rules: { + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + reportName: [{ required: true, message: '请输入报告名称', trigger: 'blur' }], + number: [{ required: true, message: '请输入编号', trigger: 'blur' }], + deptId: [{ required: true, message: '请选择实施部门', trigger: 'blur' }], + endTime: [{ required: true, message: '请选择调查结束日期', trigger: 'blur' }], + grantAmount: [{ required: true, message: '请输入问卷发放数', trigger: 'blur' }], + recycleAmount: [{ required: true, message: '请输入问卷回收数', trigger: 'blur' }], + recycleRate: [{ required: true, message: '请输入回收率', trigger: 'blur' }], + checkAmount: [{ required: true, message: '请输入检查项目数量', trigger: 'blur' }], + yearRate: [{ required: true, message: '请输入今年覆盖率', trigger: 'blur' }], + ancientlyRate: [{ required: true, message: '请输入以往覆盖率', trigger: 'blur' }], + researchSatisficing: [{ required: true, message: '请输入在研满意度', trigger: 'blur' }], + deliverySatisficing: [{ required: true, message: '请输入交付满意度', trigger: 'blur' }], + sumSatisficing: [{ required: true, message: '请输入总体满意度', trigger: 'blur' }], + agentId: [{ required: true, message: '请选择经办人', trigger: 'blur' }], + deptUser: [{ required: true, message: '请选择部门领导', trigger: 'blur' }], + + }, + isAdmin: false, + companyList: [], + deptList:[], + peopleList: [], +}) + +onMounted(() => { + + +}); +const openDialog = async (type, value,companyList) => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + state.isAdmin = userInfo.userType === 0; + state.form.companyName = userInfo.companyName + state.form.companyId = userInfo.companyId + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + state.companyList = companyList + } + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ; + if(type === 'edit' || type === 'review') { + state.form = JSON.parse(JSON.stringify(value)); + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + } + // state.dataList = JSON.parse(value.data) + } + await getDepartList() + await getPeopleList() + dialogVisible.value = true; +} + +const onSubmit = async () => { + state.form.mess = JSON.stringify(state.dataList) + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + console.log('sta',state.form) + const {id, ...data} = JSON.parse(JSON.stringify(state.form)) + const res = await addReport(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + }else if(title.value === '编辑'){ + const {...data} = JSON.parse(JSON.stringify(state.form)) + const res = await editReport(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '编辑成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + emit("getList") + +} +const reset = () => { + state.form = { + id: '', + companyId: null, + deptId: null, + year: '', + fictionId: null, + checkId: null, + ratifyId: null, + fictionTime: null, + frequency: '', + expectContents:[], + } + state.checkProductTypes = [] + state.companyList = [] +} +const getDepartList = async (companyId)=> { + const params = { + companyId: companyId + } + const res = await getDepart(params) + if(res.code == 200){ + state.deptList = res.data + }else{ + ElMessage.warning(res.message) + } +} + +const getPeopleList = async ()=> { + if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){ + return + } + const queryParams = { + pageNum: 1, + pageSize: 9999, + companyId: state.form.companyId + } + const res = await getUser(queryParams) + if(res.code == 200){ + state.peopleList = res.data.list?res.data.list:[] + }else{ + ElMessage.warning(res.message) + } +}; + +const selectValueCom = async (val) => { + state.form.agentId = null + state.form.deptUser = null + state.form.deptId = null + state.companyList.forEach(item => { + if(item.name === val){ + state.form.companyId = item.id + } + }) + await getDepartList() + await getPeopleList() +} + + + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + :deep(.el-table .cell){ + font-size: small; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/index.vue b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/index.vue new file mode 100644 index 0000000..745859f --- /dev/null +++ b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/report/index.vue @@ -0,0 +1,271 @@ +<template> + <div class="app-container"> + <div style="margin-bottom: 10px"> + <el-form style="display: flex;flex-wrap: wrap;"> + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px"> + <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable> + <el-option + v-for="item in data.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="data.isAdmin"> + <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </el-form-item> + <!-- <el-form-item style="margin-left: 15px">--> + <!-- <el-button--> + <!-- type="primary"--> + <!-- @click="exportData"--> + <!-- >导出</el-button>--> + <!-- </el-form-item>--> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange"> +<!-- <el-table-column type="selection" width="55" />--> + <el-table-column type="index" label="序号" width="80" align="center"></el-table-column> + <el-table-column label="报告名称" prop="reportName" align="center" /> + <el-table-column label="操作" align="center" class-naame="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + + <div class="pag-container"> + <el-pagination + v-model:current-page="data.queryParams.pageNum" + v-model:page-size="data.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <editDialog ref="noticeRef" @getList = "getList"></editDialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue"; +import editDialog from "./components/editDialog.vue" +import {ElMessage, ElMessageBox} from "element-plus"; +import {getCompany} from "@/api/onlineEducation/company"; +import Cookies from "js-cookie"; +import {generateWordDocument} from "@/utils/exportWord"; +import {delTable, getTable} from "@/api/qualityObjectives/table"; +import {delDiscern, getDiscern} from "@/api/environment/factors"; +import {delReport, getReport} from "@/api/satisfiedNew/satisfiedNew"; +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const noticeRef = ref(); +const deptRef = ref() +const loadingCompany = ref(false) +const choosedData = ref([]) +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + year: '', + type: '' + }, + companyList: [], + isAdmin: false, + dialogVisible: false, +}); +const dataList = ref([]); +const total = ref(0); + +const { queryParams } = toRefs(data); + +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + console.log("userInfo",userInfo) + data.isAdmin = userInfo.userType === 0; + if(data.isAdmin){ + data.queryParams.companyId = null + }else { + data.queryParams.companyId = userInfo.companyId + } + getList(); + if(data.isAdmin){ + getCompanyList() + } +}); +const getList = async () => { + loading.value = true; + const res = await getReport(data.queryParams); + if(res.code === 200){ + dataList.value = res.data.list + total.value = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false; + +} + +const searchClick = () => { + getList(); +} + +const openDialog = (type, value) => { + noticeRef.value.openDialog(type, value,data.companyList); +} + +const selectValue = (val) => { + data.companyList.forEach(item => { + if(item.name === val){ + data.queryParams.companyId = item.id + } + }) +} + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + } else { + ElMessage.warning(res.message) + } +} + +const handleSizeChange = (val) => { + data.queryParams.pageSize = val + getList() +} +const handleCurrentChange = (val) => { + data.queryParams.pageNum = val + getList() +} +const handleClose = () => { + data.dialogVisible = false +} + +/** 重置新增的表单以及其他数据 */ +function reset() { + if(data.isAdmin){ + data.queryParams = { + companyId: '', + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + choosedData.value = [] + data.companyList = []; + getCompanyList() + }else { + data.queryParams = { + companyId: data.queryParams.companyId, + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + } + getList(); + +} +const exportData = () => { + if(choosedData.value && choosedData.value.length === 0){ + ElMessage.warning('请选择需要导出的数据') + }else { + startGeneration() + } +} +const templatePath = ref('/environmentalFactorsExample.docx') +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(choosedData.value)) + data.forEach(item => { + item.fictionTime = item.fictionTime.substring(0,10) + console.log('u',item) + const datax = idGroupToTree(item.factorContents) + item.tableList = datax.map((item,index) => { + return { + ...item, + fileList: item.children.map((f,findex) => { + return{ + ...f, + first: findex == 0, + typeName: f.type == 1 ? '外部环境' : '内部环境' + } + }) + } + }) + console.log(' item.tableList', item.tableList) + try { + generateWordDocument(templatePath.value, item, item.companyName+`_${item.year}年内、外部环境要素识别表.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '导出失败' + }); + } + }) +} +function idGroupToTree(data) { + const groups = data.reduce((map, item) => { + map.has(item.type) || map.set(item.type, []); + map.get(item.type).push(item); + return map; + }, new Map()); + return Array.from(groups).map(([type, items]) => ({ + type, + children: items + })); +} +const handleSelectionChange = (val) => { + choosedData.value = val +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delReport(val.id); + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '删除成功' + }); + await getList(); + }else{ + ElMessage.warning(res.message) + } + }) +} + + +</script> +<style lang="scss"> +.pag-container{ + float: right; + margin-top: 10px; +} +</style> diff --git a/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/components/editDialog.vue b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/components/editDialog.vue new file mode 100644 index 0000000..3113075 --- /dev/null +++ b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/components/editDialog.vue @@ -0,0 +1,409 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="700px" + :before-close="handleClose" + :close-on-press-escape="false" + :close-on-click-modal="false" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules" > + <el-row :gutter="24"> + <el-col :span="24"> + <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin"> + <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom"> + <el-option + v-for="item in state.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="问卷名称:" prop="questionName" > + <el-input :disabled="title === '查看'" v-model="state.form.questionName" placeholder="问卷名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="编号:" prop="number" > + <el-input :disabled="title === '查看'" v-model="state.form.number" placeholder="编号"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="单位名称:" prop="unitName" > + <el-input :disabled="title === '查看'" v-model="state.form.unitName" placeholder="单位名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="联系人:" prop="person" > + <el-input :disabled="title === '查看'" v-model="state.form.person" placeholder="联系人"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="12"> + <el-form-item label="联系地址:" prop="address" > + <el-input :disabled="title === '查看'" v-model="state.form.address" placeholder="联系地址"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="电话、传真:" prop="phone" > + <el-input :disabled="title === '查看'" v-model="state.form.phone" placeholder="电话、传真"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <div style="display:flex;flex-direction: column"> + <span style="font-size: 11px;font-weight: 700;margin-bottom: 5px" >贵单位使用我所何种类型的产品(可多选,在相应的选项“⬜︎︎︎”内打“√”):</span> + <el-checkbox-group v-model="state.checkProductTypes" size="small" :disabled="title === '查看'" style="display:flex;flex-wrap: wrap;margin-left: 20px"> + <div v-for="item in state.productTypeList"> + <el-checkbox :label="item.id" :key="item.id" style="margin-left: 20px;">{{item.name}}</el-checkbox> + </div> + </el-checkbox-group> + </div> + <div style="display: flex;align-items: center;margin-top: 5px"> + <span style="font-size: 11px;font-weight: 700;margin-bottom: 5px;margin-right: 10px" >请注明产品的名称(如有保密情况可以不填):</span> + <el-input style="width: 200px;" size="small" :disabled="title === '查看'" v-model="state.form.productName"></el-input> + </div> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <el-table style="margin: 20px 0" :data="state.dataList" :border="true"> + <el-table-column label="序号" width="80" prop="num" align="center"></el-table-column> + <el-table-column label="调查项目" prop="item" align="center" > + <template #default="scope"> + <div v-if="scope.row.num == '说明'"> + <span>{{scope.row.item}}</span> + </div> + <div v-else style="display: flex;align-items: center"> + <span v-if="scope.row.num == 3" style="width: 210px">技术人员:</span> + <span v-if="scope.row.num == 4" style="width: 210px">市场人员服务与跟踪意识:</span> + <el-checkbox-group v-model="scope.row.checkItem" size="small" :disabled="title === '查看'" style="display:flex;flex-wrap: wrap;width: 600px;margin-left: 10px"> + <div v-for="item in scope.row.item"> + <el-checkbox style="margin-right: 15px" :label="item" :key="item" >{{item}}</el-checkbox> + </div> + </el-checkbox-group> + </div> + </template> + </el-table-column> + <el-table-column label="满意度" prop="satisfied" align="center" > + <template #default="scope"> + <div v-if="scope.row.num == '说明'"> + <span>{{scope.row.satisfied}}</span> + </div> + <el-radio-group v-else v-model="scope.row.check" size="small" :disabled="title === '查看'" style="display:flex;flex-wrap: wrap;margin-left: 20px"> + <div v-for="item in scope.row.satisfied"> + <el-radio style="margin-right: 15px" :label="item" :key="item" >{{item}}</el-radio> + </div> + </el-radio-group> + </template> + </el-table-column> + </el-table> + </el-col> + </el-row> + <el-row :gutter="24"> + <el-col :span="24"> + <span style="font-size: 12px;font-weight: 700;margin-bottom: 5px" >重点说明不满意的原因以及其他意见、要求或建议,如同类产品的差距、市场信息、改进的建议等:</span> + <el-input style="margin-top: 5px" :disabled="title === '查看'" v-model="state.form.suggest" type="textarea" :rows="4"></el-input> + </el-col> + </el-row> + </el-form> + <template #footer v-if="title !== '查看'"> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {onMounted, reactive, ref, toRefs} from 'vue' +import Cookies from "js-cookie"; +import {getCompany} from "@/api/onlineEducation/company"; +import {ElMessage} from "element-plus"; +import {getUser} from "@/api/onlineEducation/user"; +import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object"; +import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table"; +import {addNeedDiscren, editNeedDiscren} from "@/api/need/need"; +import {verifyPhone} from "@/utils/validate"; +import {developList} from "@/views/work/qualityInfo/supplierQuality/supplierList/components/qualityDatas"; +import {addResearch, editResearch} from "@/api/satisfiedNew/satisfiedNew"; + +const dialogVisible = ref(false); +const title = ref(""); +const busRef = ref(); +const length = ref() +const selectPopperClass = "max-width-select"; +const emit = defineEmits(["getList"]); +const dataRef = ref(); +const validatePhone = (rule, value, callback)=>{ + if(value === ''){ + callback(new Error('请输入手机号')) + }else{ + if(!verifyPhone(value)){ + callback(new Error('手机号格式有误')) + }else{ + callback() + } + } +} +const state = reactive({ + form: { + id: '', + companyId: null, + questionName: null, + number: '', + unitName: null, + person: null, + address: null, + phone: null, + product: '', + productName:'', + mess:'', + suggest: '' + }, + rules: { + companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }], + questionName: [{ required: true, message: '请输入问卷名称', trigger: 'blur' }], + number: [{ required: true, message: '请输入编号', trigger: 'blur' }], + unitName: [{ required: true, message: '请输入单位名称', trigger: 'blur' }], + person: [{ required: true, message: '请输入联系人', trigger: 'blur' }], + address: [{ required: true, message: '请输入联系地址', trigger: 'blur' }], + product: [{ required: true, message: '请选择产品', trigger: 'blur' }], + phone: [{required: true, trigger: "blur", validator: validatePhone}], + + }, + isAdmin: false, + companyList: [], + dataList: [ + { + num: '说明', + item: '哪项不满意,请在相应的选项“⬜︎︎︎”内打“√”', + satisfied:'总体评价,请在相应的选项“⬜︎︎︎”内打“√”' + }, + { + num: '1', + item: ['研制过程质里管理'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '2', + item: ['项目进度的符合性','节点控制'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '3', + item: ['技术技能','工作态度','过程规范','综合素质'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '4', + item: ['服务的及时性','有效性','服务态度'], + satisfied:['满意','基本满意','不满意'] + }, + ], + productTypeList: [ + { + id: 1, + name: '系统' + }, + { + id: 2, + name: '软件' + }, + { + id: 3, + name: '整机' + }, + { + id: 4, + name: '试剂柜' + }, + { + id: 5, + name: '印制板' + }, + { + id: 6, + name: '手持终端' + }, + { + id: 7, + name: '其他' + }, + ], + checkProductTypes: [] +}) + +onMounted(() => { + + +}); +const openDialog = async (type, value,companyList) => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + state.isAdmin = userInfo.userType === 0; + state.form.companyName = userInfo.companyName + state.form.companyId = userInfo.companyId + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + state.companyList = companyList + } + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ; + if(type === 'edit' || type === 'review') { + state.form = JSON.parse(JSON.stringify(value)); + if(state.isAdmin){ + state.form.companyId = value.companyId + state.form.companyName = value.companyName + } + state.dataList = JSON.parse(value.mess) + state.checkProductTypes = value.product.split(',').map(Number) + + } + dialogVisible.value = true; +} + +const onSubmit = async () => { + state.form.mess = JSON.stringify(state.dataList) + state.form.product = state.checkProductTypes.join(',') + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + console.log('sta',state.form) + const {id, ...data} = JSON.parse(JSON.stringify(state.form)) + const res = await addResearch(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + }else if(title.value === '编辑'){ + const {...data} = JSON.parse(JSON.stringify(state.form)) + const res = await editResearch(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '编辑成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + reset(); + dialogVisible.value = false; + emit("getList") + +} +const reset = () => { + state.form = { + id: '', + companyId: null, + questionName: null, + number: '', + unitName: null, + person: null, + address: null, + phone: null, + product: '', + productName:'', + mess:'', + suggest: '' + } + state.checkProductTypes = [] + state.companyList = [] + state.dataList = [ + { + num: '说明', + item: '哪项不满意,请在相应的选项“⬜︎︎︎”内打“√”', + satisfied:'总体评价,请在相应的选项“⬜︎︎︎”内打“√”' + }, + { + num: '1', + item: ['研制过程质里管理'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '2', + item: ['项目进度的符合性','节点控制'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '3', + item: ['技术技能','工作态度','过程规范','综合素质'], + satisfied:['满意','基本满意','不满意'] + }, + { + num: '4', + item: ['服务的及时性','有效性','服务态度'], + satisfied:['满意','基本满意','不满意'] + }, + ] +} + + + +const selectValueCom = (val) => { + + state.companyList.forEach(item => { + if(item.name === val){ + state.form.companyId = item.id + } + }) +} + +const handleChangeNum = (value) => { + if (!/^\d+$/.test(value)) { // 验证是否为数字 + ElMessage.warning('只能输入数字') + state.form.year = '' // 重置选择,避免非法值被添加到options中 + } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项 + state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同) + } +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + :deep(.el-table .cell){ + font-size: small; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/index.vue b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/index.vue new file mode 100644 index 0000000..5742182 --- /dev/null +++ b/src/views/work/qualityInfo/supplierQuality/satisfiedEvaluste/research/index.vue @@ -0,0 +1,270 @@ +<template> + <div class="app-container"> + <div style="margin-bottom: 10px"> + <el-form style="display: flex;flex-wrap: wrap;"> + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px"> + <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable> + <el-option + v-for="item in data.companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="data.isAdmin"> + <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </el-form-item> +<!-- <el-form-item style="margin-left: 15px">--> +<!-- <el-button--> +<!-- type="primary"--> +<!-- @click="exportData"--> +<!-- >导出</el-button>--> +<!-- </el-form-item>--> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange"> +<!-- <el-table-column type="selection" width="55" />--> + <el-table-column type="index" label="序号" width="80" align="center"></el-table-column> + <el-table-column label="名称" prop="questionName" align="center" /> + <el-table-column label="操作" align="center" class-naame="small-padding fixed-width" > + <template #default="scope"> + <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button> + </template> + </el-table-column> + </el-table> + + <div class="pag-container"> + <el-pagination + v-model:current-page="data.queryParams.pageNum" + v-model:page-size="data.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <editDialog ref="noticeRef" @getList = "getList"></editDialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue"; +import editDialog from "./components/editDialog.vue" +import {ElMessage, ElMessageBox} from "element-plus"; +import {getCompany} from "@/api/onlineEducation/company"; +import Cookies from "js-cookie"; +import {generateWordDocument} from "@/utils/exportWord"; +import {delTable, getTable} from "@/api/qualityObjectives/table"; +import {delDiscern, getDiscern} from "@/api/environment/factors"; +import {delResearch, getResearch} from "@/api/satisfiedNew/satisfiedNew"; +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const noticeRef = ref(); +const deptRef = ref() +const loadingCompany = ref(false) +const choosedData = ref([]) +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null, + year: '', + type: '' + }, + companyList: [], + isAdmin: false, + dialogVisible: false, +}); +const dataList = ref([]); +const total = ref(0); + +const { queryParams } = toRefs(data); + +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + console.log("userInfo",userInfo) + data.isAdmin = userInfo.userType === 0; + if(data.isAdmin){ + data.queryParams.companyId = null + }else { + data.queryParams.companyId = userInfo.companyId + } + getList(); + if(data.isAdmin){ + getCompanyList() + } +}); +const getList = async () => { + loading.value = true; + const res = await getResearch(data.queryParams); + if(res.code === 200){ + dataList.value = res.data.list + total.value = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false; +} + +const searchClick = () => { + getList(); +} + +const openDialog = (type, value) => { + noticeRef.value.openDialog(type, value,data.companyList); +} + +const selectValue = (val) => { + data.companyList.forEach(item => { + if(item.name === val){ + data.queryParams.companyId = item.id + } + }) +} + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + } else { + ElMessage.warning(res.message) + } +} + +const handleSizeChange = (val) => { + data.queryParams.pageSize = val + getList() +} +const handleCurrentChange = (val) => { + data.queryParams.pageNum = val + getList() +} +const handleClose = () => { + data.dialogVisible = false +} + +/** 重置新增的表单以及其他数据 */ +function reset() { + if(data.isAdmin){ + data.queryParams = { + companyId: '', + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + choosedData.value = [] + data.companyList = []; + getCompanyList() + }else { + data.queryParams = { + companyId: data.queryParams.companyId, + pageNum: 1, + pageSize: 10, + year: '', + type: '' + } + } + getList(); + +} +const exportData = () => { + if(choosedData.value && choosedData.value.length === 0){ + ElMessage.warning('请选择需要导出的数据') + }else { + startGeneration() + } +} +const templatePath = ref('/environmentalFactorsExample.docx') +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(choosedData.value)) + data.forEach(item => { + item.fictionTime = item.fictionTime.substring(0,10) + console.log('u',item) + const datax = idGroupToTree(item.factorContents) + item.tableList = datax.map((item,index) => { + return { + ...item, + fileList: item.children.map((f,findex) => { + return{ + ...f, + first: findex == 0, + typeName: f.type == 1 ? '外部环境' : '内部环境' + } + }) + } + }) + console.log(' item.tableList', item.tableList) + try { + generateWordDocument(templatePath.value, item, item.companyName+`_${item.year}年内、外部环境要素识别表.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '导出失败' + }); + } + }) +} +function idGroupToTree(data) { + const groups = data.reduce((map, item) => { + map.has(item.type) || map.set(item.type, []); + map.get(item.type).push(item); + return map; + }, new Map()); + return Array.from(groups).map(([type, items]) => ({ + type, + children: items + })); +} +const handleSelectionChange = (val) => { + choosedData.value = val +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delResearch(val.id); + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '删除成功' + }); + await getList(); + }else{ + ElMessage.warning(res.message) + } + }) +} + + +</script> +<style lang="scss"> +.pag-container{ + float: right; + margin-top: 10px; +} +</style> -- Gitblit v1.9.2