From b2555a328ee990e8e25f32040633c2ec2fde8221 Mon Sep 17 00:00:00 2001
From: 祖安之光 <11848914+light-of-zuan@user.noreply.gitee.com>
Date: 星期一, 18 八月 2025 16:47:57 +0800
Subject: [PATCH] 修改新增
---
src/views/work/qualityInfo/outsourcingCooperate/outsourcedProductName/index.vue | 160 ++
src/views/work/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/index.vue | 215 +++
src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/index.vue | 299 +++++
src/views/work/qualityInfo/outsourcingCooperate/inspectQualifyRecord/components/editDialog.vue | 257 ++++
src/views/work/qualityInfo/outsourcingCooperate/inspectQualifyRecord/index.vue | 215 +++
src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/components/editDialog.vue | 603 +++++++++++
src/views/work/qualityInfo/outsourcingCooperate/unqualifiedHandle/components/editDialog.vue | 265 ++++
src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/components/editDialog.vue | 257 ++++
src/views/work/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/components/editDialog.vue | 257 ++++
src/views/work/qualityInfo/outsourcingCooperate/outsourcedProductName/components/editDialog.vue | 168 +++
public/outsourceProcessReview.docx | 0
src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue | 215 +++
src/api/outsourcingCooperate/outsourcingCooperate.js | 105 +
src/views/work/qualityInfo/outsourcingCooperate/unqualifiedHandle/index.vue | 214 +++
14 files changed, 3,230 insertions(+), 0 deletions(-)
diff --git a/public/outsourceProcessReview.docx b/public/outsourceProcessReview.docx
new file mode 100644
index 0000000..1c0e585
--- /dev/null
+++ b/public/outsourceProcessReview.docx
Binary files differ
diff --git a/src/api/outsourcingCooperate/outsourcingCooperate.js b/src/api/outsourcingCooperate/outsourcingCooperate.js
new file mode 100644
index 0000000..05bceac
--- /dev/null
+++ b/src/api/outsourcingCooperate/outsourcingCooperate.js
@@ -0,0 +1,105 @@
+import request from '@/utils/request'
+
+export function getOutsourcedProductNameList(query) {
+ return request({
+ url: '/system/outsourcedProduct/selectOutsourcedProductList',
+ method: 'get',
+ params: query
+ })
+}
+
+export function delOutsourcedProductNameList(query) {
+ return request({
+ url: '/system/outsourcedProduct/deletedOutsourcedProduct',
+ method: 'get',
+ params: query
+ })
+}
+
+export function updateOutsourcedProductNameList(data) {
+ return request({
+ url: '/system/outsourcedProduct/saveOutsourcedProduct',
+ method: 'post',
+ data: data
+ })
+}
+
+export function getOutsourcedCommonList(query) {
+ return request({
+ url: '/system/outsourcedCommon/selectOutsourcedCommonList',
+ method: 'get',
+ params: query
+ })
+}
+
+export function delOutsourcedCommon(query) {
+ return request({
+ url: '/system/outsourcedCommon/deletedOutsourcedCommon',
+ method: 'get',
+ params: query
+ })
+}
+
+export function updateOutsourcedCommon(data) {
+ return request({
+ url: '/system/outsourcedCommon/saveOutsourcedCommon',
+ method: 'post',
+ data: data
+ })
+}
+
+export function getOutsourcedUnqualifiedList(query) {
+ return request({
+ url: '/system/outsourcedUnqualified/selectOutsourcedUnqualifiedList',
+ method: 'get',
+ params: query
+ })
+}
+
+export function delOutsourcedUnqualified(query) {
+ return request({
+ url: '/system/outsourcedUnqualified/deletedOutsourcedUnqualified',
+ method: 'get',
+ params: query
+ })
+}
+
+export function updateOutsourcedUnqualified(data) {
+ return request({
+ url: '/system/outsourcedUnqualified/saveOutsourcedUnqualified',
+ method: 'post',
+ data: data
+ })
+}
+
+export function getOutsourcedReviewList(query) {
+ return request({
+ url: '/system/outsourcedReview/selectOutsourcedReviewList',
+ method: 'get',
+ params: query
+ })
+}
+
+export function delOutsourcedReview(query) {
+ return request({
+ url: '/system/outsourcedReview/deletedOutsourcedReview',
+ method: 'get',
+ params: query
+ })
+}
+
+export function getOutsourcedReviewDetail(query) {
+ return request({
+ url: '/system/outsourcedReview/getOutsourcedReview',
+ method: 'get',
+ params: query
+ })
+}
+
+export function updateOutsourcedReview(data) {
+ return request({
+ url: '/system/outsourcedReview/saveOutsourcedReview',
+ method: 'post',
+ data: data
+ })
+}
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/inspectQualifyRecord/components/editDialog.vue b/src/views/work/qualityInfo/outsourcingCooperate/inspectQualifyRecord/components/editDialog.vue
new file mode 100644
index 0000000..1cf9ef4
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/inspectQualifyRecord/components/editDialog.vue
@@ -0,0 +1,257 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="700px"
+ :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="请选择" :disabled="state.title =='查看'" 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="supplierId">
+ <el-select v-model="state.form.supplierId" placeholder="请选择" :disabled="state.title =='查看'" clearable style="width: 100%">
+ <el-option
+ v-for="item in state.supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="文件名称:" prop="fileName">
+ <el-input v-model.trim="state.form.fileName" :readonly="state.title =='查看'" placeholder="文件名称"></el-input>
+ </el-form-item>
+ <el-form-item label="文件:" prop="filePath">
+ <el-upload :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 {updateInfoPlatforms} from "@/api/staffManage/staff";
+import {getSupplierPage} from "@/api/supplier/supplierList";
+import {updateOutsourcedCommon, updateOutsourcedProductNameList} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {delPic} from "@/api/onlineEducation/banner";
+import {getToken} from "@/utils/auth";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const checkFiles = (rule, value, callback) => {
+ if (state.fileList.length == 0) {
+ callback(new Error('请上传文件'))
+ } else {
+ callback()
+ }
+}
+const superRef = ref()
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ fileName: '',
+ filePath: '',
+ format: '',
+ osType: 3
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ supplierId: [{ required: true, message: '请选择供应商', trigger: 'blur' }],
+ filePath: [{ required: true, validator: checkFiles, trigger: 'blur' }]
+ },
+ isAdmin: false,
+ companyList: [],
+ supplierList: [],
+ 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
+ }
+ await getSupplierList()
+ 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: '工艺流程图'
+ }
+ state.fileList = [obj]
+ }
+ }
+ dialogVisible.value = true
+}
+
+const getSupplierList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getSupplierPage(queryParams)
+ if (res.code == 200) {
+ state.supplierList = res.data.list?res.data.list:[]
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ let data = {}
+ if(state.title == '新增'){
+ data = {
+ companyId: state.form.companyId,
+ fileName: state.form.fileName,
+ supplierId: state.form.supplierId,
+ supplierName: state.supplierList.find(i=>i.id == state.form.supplierId)?.supplierName,
+ filePath: state.form.filePath,
+ format: state.form.format,
+ osType: 3
+ }
+ }else{
+ data = state.form
+ }
+ const res = await updateOutsourcedCommon(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+
+ }
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ fileName: '',
+ filePath: '',
+ format: '',
+ osType: 3
+ }
+ state.fileList = []
+ superRef.value.clearValidate();
+ superRef.value.resetFields()
+ dialogVisible.value = false;
+}
+
+const handleAvatarSuccess = (res, uploadFile) => {
+ if(res.code == 200){
+ state.form.filePath = res.data.path
+ state.form.format = '.' + res.data.filename.split('.')[1]
+ }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){
+ // ElMessage({
+ // type: 'success',
+ // message: '文件已删除'
+ // })
+ state.form.filePath = ''
+ state.form.format = ''
+ }else{
+ ElMessage({
+ type: 'warning',
+ message: res.message
+ })
+ }
+ }).catch(() => {
+ state.form.imgUrl = ''
+ });
+}
+
+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/qualityInfo/outsourcingCooperate/inspectQualifyRecord/index.vue b/src/views/work/qualityInfo/outsourcingCooperate/inspectQualifyRecord/index.vue
new file mode 100644
index 0000000..006cfed
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/inspectQualifyRecord/index.vue
@@ -0,0 +1,215 @@
+<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 >
+ <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button>
+ <el-button v-if="isAdmin" 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="supplierName" align="center"/>
+ <el-table-column label="检验记录" align="center">
+ <template #default="scope">
+ <el-link type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName !== '' ?scope.row.fileName + scope.row.format : '检验记录'}}</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.filePath)">下载</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 Cookies from "js-cookie";
+import editDialog from './components/editDialog.vue'
+import useUserStore from "@/store/modules/user";
+import {
+ delOutsourcedCommon,
+ delOutsourcedProductNameList, getOutsourcedCommonList,
+ getOutsourcedProductNameList
+} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {renderAsync} from "docx-preview";
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ osType: 3
+ },
+ total: 0,
+ dataList: [],
+ companyList: [],
+ isAdmin: false
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = toRefs(data);
+const userInfo = ref()
+onMounted(async ()=>{
+ userInfo.value = JSON.parse(Cookies.get('userInfo'))
+ if(userStore.roles.includes('admin')){
+ data.isAdmin = true
+ await getCompanyList()
+ }else{
+ data.isAdmin = false
+ data.queryParams.companyId = userStore.companyId
+ }
+ await getList()
+})
+
+onUnmounted(()=>{
+
+})
+
+const getList = async () => {
+ loading.value = true
+ const res = await getOutsourcedCommonList(data.queryParams)
+ if(res.code == 200){
+ data.dataList = res.data.list || []
+ 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 = (path)=>{
+ window.open(import.meta.env.VITE_APP_BASE_API + '/' + path)
+}
+
+const openFile = async(path)=>{
+ const ext = path.split('.').pop().toLowerCase();
+ if (ext === 'doc' || ext === 'pptx' || ext === 'ppt') {
+ ElMessageBox.confirm(`暂不支持线上预览.${ext}文件,是否下载查看?`, '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => {
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }).catch(() => {
+ console.log('取消预览')
+ });
+ return
+ }else if(ext === 'pdf' || ext === 'jpg' || ext === 'jpeg' || ext === 'png' || ext === 'cad'){
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }else{
+ 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}`);
+ }
+ }
+}
+
+const openDialog = (type, value) => {
+ dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList );
+}
+
+/** 重置新增的表单以及其他数据 */
+const reset= async()=> {
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ osType: 3
+ }
+ await getCompanyList()
+ await getList()
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delOutsourcedCommon({id: val.id})
+ if(res.code == 200){
+ ElMessage.success('数据删除成功')
+ await getList()
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/components/editDialog.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/components/editDialog.vue
new file mode 100644
index 0000000..9bcadbe
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/components/editDialog.vue
@@ -0,0 +1,257 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="700px"
+ :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="请选择" :disabled="state.title =='查看'" 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="supplierId">
+ <el-select v-model="state.form.supplierId" placeholder="请选择" :disabled="state.title =='查看'" clearable style="width: 100%">
+ <el-option
+ v-for="item in state.supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="文件名称:" prop="fileName">
+ <el-input v-model.trim="state.form.fileName" :readonly="state.title =='查看'" placeholder="文件名称"></el-input>
+ </el-form-item>
+ <el-form-item label="文件:" prop="filePath">
+ <el-upload :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 {updateInfoPlatforms} from "@/api/staffManage/staff";
+import {getSupplierPage} from "@/api/supplier/supplierList";
+import {updateOutsourcedCommon, updateOutsourcedProductNameList} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {delPic} from "@/api/onlineEducation/banner";
+import {getToken} from "@/utils/auth";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const checkFiles = (rule, value, callback) => {
+ if (state.fileList.length == 0) {
+ callback(new Error('请上传文件'))
+ } else {
+ callback()
+ }
+}
+const superRef = ref()
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ fileName: '',
+ filePath: '',
+ format: '',
+ osType: 2
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ supplierId: [{ required: true, message: '请选择供应商', trigger: 'blur' }],
+ filePath: [{ required: true, validator: checkFiles, trigger: 'blur' }]
+ },
+ isAdmin: false,
+ companyList: [],
+ supplierList: [],
+ 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
+ }
+ await getSupplierList()
+ 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: '工艺流程图'
+ }
+ state.fileList = [obj]
+ }
+ }
+ dialogVisible.value = true
+}
+
+const getSupplierList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getSupplierPage(queryParams)
+ if (res.code == 200) {
+ state.supplierList = res.data.list?res.data.list:[]
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ let data = {}
+ if(state.title == '新增'){
+ data = {
+ companyId: state.form.companyId,
+ fileName: state.form.fileName,
+ supplierId: state.form.supplierId,
+ supplierName: state.supplierList.find(i=>i.id == state.form.supplierId)?.supplierName,
+ filePath: state.form.filePath,
+ format: state.form.format,
+ osType: 2
+ }
+ }else{
+ data = state.form
+ }
+ const res = await updateOutsourcedCommon(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+
+ }
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ fileName: '',
+ filePath: '',
+ format: '',
+ osType: 2
+ }
+ state.fileList = []
+ superRef.value.clearValidate();
+ superRef.value.resetFields()
+ dialogVisible.value = false;
+}
+
+const handleAvatarSuccess = (res, uploadFile) => {
+ if(res.code == 200){
+ state.form.filePath = res.data.path
+ state.form.format = '.' + res.data.filename.split('.')[1]
+ }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){
+ // ElMessage({
+ // type: 'success',
+ // message: '文件已删除'
+ // })
+ state.form.filePath = ''
+ state.form.format = ''
+ }else{
+ ElMessage({
+ type: 'warning',
+ message: res.message
+ })
+ }
+ }).catch(() => {
+ state.form.imgUrl = ''
+ });
+}
+
+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/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/index.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/index.vue
new file mode 100644
index 0000000..9a12289
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedContractAgreement/index.vue
@@ -0,0 +1,215 @@
+<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 >
+ <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button>
+ <el-button v-if="isAdmin" 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="supplierName" align="center"/>
+ <el-table-column label="合同质量协议" align="center">
+ <template #default="scope">
+ <el-link type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName !== '' ?scope.row.fileName + scope.row.format : '合同质量协议'}}</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.filePath)">下载</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 Cookies from "js-cookie";
+import editDialog from './components/editDialog.vue'
+import useUserStore from "@/store/modules/user";
+import {
+ delOutsourcedCommon,
+ delOutsourcedProductNameList, getOutsourcedCommonList,
+ getOutsourcedProductNameList
+} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {renderAsync} from "docx-preview";
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ osType: 2
+ },
+ total: 0,
+ dataList: [],
+ companyList: [],
+ isAdmin: false
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = toRefs(data);
+const userInfo = ref()
+onMounted(async ()=>{
+ userInfo.value = JSON.parse(Cookies.get('userInfo'))
+ if(userStore.roles.includes('admin')){
+ data.isAdmin = true
+ await getCompanyList()
+ }else{
+ data.isAdmin = false
+ data.queryParams.companyId = userStore.companyId
+ }
+ await getList()
+})
+
+onUnmounted(()=>{
+
+})
+
+const getList = async () => {
+ loading.value = true
+ const res = await getOutsourcedCommonList(data.queryParams)
+ if(res.code == 200){
+ data.dataList = res.data.list || []
+ 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 = (path)=>{
+ window.open(import.meta.env.VITE_APP_BASE_API + '/' + path)
+}
+
+const openFile = async(path)=>{
+ const ext = path.split('.').pop().toLowerCase();
+ if (ext === 'doc' || ext === 'pptx' || ext === 'ppt') {
+ ElMessageBox.confirm(`暂不支持线上预览.${ext}文件,是否下载查看?`, '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => {
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }).catch(() => {
+ console.log('取消预览')
+ });
+ return
+ }else if(ext === 'pdf' || ext === 'jpg' || ext === 'jpeg' || ext === 'png' || ext === 'cad'){
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }else{
+ 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}`);
+ }
+ }
+}
+
+const openDialog = (type, value) => {
+ dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList );
+}
+
+/** 重置新增的表单以及其他数据 */
+const reset= async()=> {
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ osType: 2
+ }
+ await getCompanyList()
+ await getList()
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delOutsourcedCommon({id: val.id})
+ if(res.code == 200){
+ ElMessage.success('数据删除成功')
+ await getList()
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/components/editDialog.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/components/editDialog.vue
new file mode 100644
index 0000000..6521278
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/components/editDialog.vue
@@ -0,0 +1,257 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="700px"
+ :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="请选择" :disabled="state.title =='查看'" 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="supplierId">
+ <el-select v-model="state.form.supplierId" placeholder="请选择" :disabled="state.title =='查看'" clearable style="width: 100%">
+ <el-option
+ v-for="item in state.supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="文件名称:" prop="fileName">
+ <el-input v-model.trim="state.form.fileName" :readonly="state.title =='查看'" placeholder="文件名称"></el-input>
+ </el-form-item>
+ <el-form-item label="文件:" prop="filePath">
+ <el-upload :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 {updateInfoPlatforms} from "@/api/staffManage/staff";
+import {getSupplierPage} from "@/api/supplier/supplierList";
+import {updateOutsourcedCommon, updateOutsourcedProductNameList} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {delPic} from "@/api/onlineEducation/banner";
+import {getToken} from "@/utils/auth";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const checkFiles = (rule, value, callback) => {
+ if (state.fileList.length == 0) {
+ callback(new Error('请上传文件'))
+ } else {
+ callback()
+ }
+}
+const superRef = ref()
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ fileName: '',
+ filePath: '',
+ format: '',
+ osType: 1
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ supplierId: [{ required: true, message: '请选择供应商', trigger: 'blur' }],
+ filePath: [{ required: true, validator: checkFiles, trigger: 'blur' }]
+ },
+ isAdmin: false,
+ companyList: [],
+ supplierList: [],
+ 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
+ }
+ await getSupplierList()
+ 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: '工艺流程图'
+ }
+ state.fileList = [obj]
+ }
+ }
+ dialogVisible.value = true
+}
+
+const getSupplierList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getSupplierPage(queryParams)
+ if (res.code == 200) {
+ state.supplierList = res.data.list?res.data.list:[]
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ let data = {}
+ if(state.title == '新增'){
+ data = {
+ companyId: state.form.companyId,
+ fileName: state.form.fileName,
+ supplierId: state.form.supplierId,
+ supplierName: state.supplierList.find(i=>i.id == state.form.supplierId)?.supplierName,
+ filePath: state.form.filePath,
+ format: state.form.format,
+ osType: 1
+ }
+ }else{
+ data = state.form
+ }
+ const res = await updateOutsourcedCommon(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+
+ }
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ fileName: '',
+ filePath: '',
+ format: '',
+ osType: 1
+ }
+ state.fileList = []
+ superRef.value.clearValidate();
+ superRef.value.resetFields()
+ dialogVisible.value = false;
+}
+
+const handleAvatarSuccess = (res, uploadFile) => {
+ if(res.code == 200){
+ state.form.filePath = res.data.path
+ state.form.format = '.' + res.data.filename.split('.')[1]
+ }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){
+ // ElMessage({
+ // type: 'success',
+ // message: '文件已删除'
+ // })
+ state.form.filePath = ''
+ state.form.format = ''
+ }else{
+ ElMessage({
+ type: 'warning',
+ message: res.message
+ })
+ }
+ }).catch(() => {
+ state.form.imgUrl = ''
+ });
+}
+
+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/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue
new file mode 100644
index 0000000..1579d17
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessFlow/index.vue
@@ -0,0 +1,215 @@
+<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 >
+ <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button>
+ <el-button v-if="isAdmin" 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="supplierName" align="center"/>
+ <el-table-column label="工艺流程图" align="center">
+ <template #default="scope">
+ <el-link type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName !== '' ?scope.row.fileName + scope.row.format : '工艺流程图'}}</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.filePath)">下载</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 Cookies from "js-cookie";
+import editDialog from './components/editDialog.vue'
+import useUserStore from "@/store/modules/user";
+import {
+ delOutsourcedCommon,
+ delOutsourcedProductNameList, getOutsourcedCommonList,
+ getOutsourcedProductNameList
+} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {renderAsync} from "docx-preview";
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ osType: 1
+ },
+ total: 0,
+ dataList: [],
+ companyList: [],
+ isAdmin: false
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = toRefs(data);
+const userInfo = ref()
+onMounted(async ()=>{
+ userInfo.value = JSON.parse(Cookies.get('userInfo'))
+ if(userStore.roles.includes('admin')){
+ data.isAdmin = true
+ await getCompanyList()
+ }else{
+ data.isAdmin = false
+ data.queryParams.companyId = userStore.companyId
+ }
+ await getList()
+})
+
+onUnmounted(()=>{
+
+})
+
+const getList = async () => {
+ loading.value = true
+ const res = await getOutsourcedCommonList(data.queryParams)
+ if(res.code == 200){
+ data.dataList = res.data.list || []
+ 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 = (path)=>{
+ window.open(import.meta.env.VITE_APP_BASE_API + '/' + path)
+}
+
+const openFile = async(path)=>{
+ const ext = path.split('.').pop().toLowerCase();
+ if (ext === 'doc' || ext === 'pptx' || ext === 'ppt') {
+ ElMessageBox.confirm(`暂不支持线上预览.${ext}文件,是否下载查看?`, '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => {
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }).catch(() => {
+ console.log('取消预览')
+ });
+ return
+ }else if(ext === 'pdf' || ext === 'jpg' || ext === 'jpeg' || ext === 'png' || ext === 'cad'){
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }else{
+ 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}`);
+ }
+ }
+}
+
+const openDialog = (type, value) => {
+ dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList );
+}
+
+/** 重置新增的表单以及其他数据 */
+const reset= async()=> {
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ osType: 1
+ }
+ await getCompanyList()
+ await getList()
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delOutsourcedCommon({id: val.id})
+ if(res.code == 200){
+ ElMessage.success('数据删除成功')
+ await getList()
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/components/editDialog.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/components/editDialog.vue
new file mode 100644
index 0000000..26f5958
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/components/editDialog.vue
@@ -0,0 +1,603 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="50%"
+ :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="180px" >
+ <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId">
+ <el-select v-model="state.form.companyId" placeholder="请选择" :disabled="state.title =='查看'" clearable @change="getDeptList">
+ <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="reviewName">
+ <el-input v-model.trim="state.form.reviewName" :readonly="state.title =='查看'"></el-input>
+ </el-form-item>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="产品名称:" prop="productName">
+ <el-input v-model.trim="state.form.productName" :readonly="state.title =='查看'"></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="申请部门:" prop="deptId">
+ <el-select
+ clearable
+ v-model="state.form.deptId"
+ :disabled="state.title =='查看'"
+ filterable
+ placeholder="选择部门"
+ style="width: 100%"
+ >
+ <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-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="外包过程名称:" prop="outsourcedProcess">
+ <el-input v-model.trim="state.form.outsourcedProcess" :readonly="state.title =='查看'"></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="部门负责人:" prop="deptLeaderId">
+ <el-select clearable v-model="state.form.deptLeaderId" :disabled="state.title =='查看'" filterable placeholder="部门负责人" style="width: 100%">
+ <el-option
+ v-for="item in state.userList"
+ :key="item.userId"
+ :label="item.name"
+ :value="item.userId"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="是否为关键件、重要件:" prop="pieceType" >
+ <el-radio-group v-model="state.form.pieceType" :disabled="state.title === '查看'">
+ <el-radio :label="1">关键件</el-radio>
+ <el-radio :label="2">重要件</el-radio>
+ <el-radio :label="3">普通件</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="过程重要性:" prop="processType" >
+ <el-radio-group v-model="state.form.processType" :disabled="state.title === '查看'">
+ <el-radio :label="1">关键</el-radio>
+ <el-radio :label="2">一般</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="过程外包的必要性:" prop="necessity" >
+ <el-checkbox-group v-model="state.form.necessity">
+ <el-checkbox label="1">本单位没有能力满足产品实现需求</el-checkbox>
+ <el-checkbox label="2">生产急需,利用外部资源实现产品</el-checkbox>
+ <el-checkbox label="3">其他</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="过程外包的可行性:" prop="feasibility" >
+ <el-checkbox-group v-model="state.form.feasibility">
+ <el-checkbox label="1" value="1">本单位可提供现成的图纸、技术资料</el-checkbox>
+ <el-checkbox label="2" value="2">本单位可提供合格的原材料</el-checkbox>
+ <el-checkbox label="3" value="3">本单位有能力对供方产品实现过程实施控制</el-checkbox>
+ <el-checkbox label="4" value="4">其他</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="风险识别:" prop="riskRecognition" >
+ <el-checkbox-group v-model="state.form.riskRecognition">
+ <el-checkbox label="1" value="1">外包过程对我所产品质量有很大影响</el-checkbox>
+ <el-checkbox label="2" value="2">外包产品供货影响我所生产进度</el-checkbox>
+ <el-checkbox label="3" value="3">实施外包对我所经济效益有影响</el-checkbox>
+ <el-checkbox label="4" value="4">其他</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="控制措施:"></el-form-item>
+ <el-form-item label="控制质量影响的措施:" prop="qualityMeasures" >
+ <el-checkbox-group v-model="state.form.qualityMeasures">
+ <el-checkbox label="1" value="1">进货检验</el-checkbox>
+ <el-checkbox label="2" value="2">我司到供方现场验证</el-checkbox>
+ <el-checkbox label="3" value="3">顾客到供方现场验证</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="控制影响进度的措施:" prop="progressMeasures" >
+ <el-checkbox-group v-model="state.form.progressMeasures">
+ <el-checkbox label="1" value="1">与供方及时沟通</el-checkbox>
+ <el-checkbox label="2" value="2">要求供方列出进度计划</el-checkbox>
+ <el-checkbox label="3" value="3">纳入协同合作采取经济制约</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="控制经济影响的措施:" prop="economicMeasure" >
+ <el-checkbox-group v-model="state.form.economicMeasure">
+ <el-checkbox label="1" value="1">我司财务预算</el-checkbox>
+ <el-checkbox label="2" value="2">在预算范围内外包</el-checkbox>
+ <el-checkbox label="3" value="3">与供方协商解决</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="拟协作单位:" prop="outsourcedReviewSubsidiaryList">
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="addLine"
+ style="margin-bottom: 10px"
+ v-if="state.title !=='查看'"
+ >新增</el-button>
+ </el-form-item>
+
+ <el-table :data="state.form.outsourcedReviewSubsidiaryList" class="customedTable" :border="true">
+ <el-table-column label="序号" type="index" width="80" align="center"></el-table-column>
+ <el-table-column label="拟协作单位名称" prop="assistName" align="center">
+ <template #default="scope">
+ <el-input
+ v-model.trim="scope.row.assistName"
+ size="large"
+ type="textarea"
+ style="width: 100%;"
+ clearable
+ :readonly="state.title =='查看'"
+ >
+ </el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="拟协作单位地址" prop="assistAddress" align="center">
+ <template #default="scope">
+ <el-input
+ v-model.trim="scope.row.assistAddress"
+ size="large"
+ type="textarea"
+ style="width: 100%;"
+ clearable
+ :readonly="state.title =='查看'"
+ >
+ </el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="电话" prop="phone" align="center">
+ <template #default="scope">
+ <el-input
+ v-model.trim="scope.row.phone"
+ size="large"
+ type="textarea"
+ style="width: 100%;"
+ clearable
+ :readonly="state.title =='查看'"
+ >
+ </el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" align="center" width="70" v-if="state.title !=='查看'">
+ <template #default="scope">
+ <el-button link type="danger" @click="handleDelete(scope.$index)">删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <el-form-item label="评审意见及签署:" prop="outsourceType" >
+ <el-radio-group v-model="state.form.outsourceType" :disabled="state.title === '查看'">
+ <el-radio :label="1">可以外包</el-radio>
+ <el-radio :label="2">不可以外包,由部门采取措施解决。措施内容:</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item prop="measure" v-if="state.form.outsourceType == 2">
+ <el-input
+ v-model.trim="state.form.measure"
+ size="large"
+ type="textarea"
+ style="width: 100%;"
+ clearable
+ :readonly="state.title =='查看'"
+ >
+ </el-input>
+ </el-form-item>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="申请部门:" prop="applyDept">
+ <el-input v-model.trim="state.form.applyDept" :readonly="state.title =='查看'"></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item prop="applyDeptDate">
+ <el-date-picker
+ v-model="state.form.applyDeptDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="请选择日期"
+ :disabled="state.title =='查看'"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="质检部:" prop="qualityInspection">
+ <el-input v-model.trim="state.form.qualityInspection" :readonly="state.title =='查看'"></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item prop="qualityInspectionDate">
+ <el-date-picker
+ v-model="state.form.qualityInspectionDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="请选择日期"
+ :disabled="state.title =='查看'"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="管理者代表:" prop="managementRepresentative">
+ <el-input v-model.trim="state.form.managementRepresentative" :readonly="state.title =='查看'"></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item prop="managementRepresentativeDate">
+ <el-date-picker
+ v-model="state.form.managementRepresentativeDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="请选择日期"
+ :disabled="state.title =='查看'"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="批准意见:" prop="approvalOpinions">
+ <el-input
+ v-model.trim="state.form.approvalOpinions"
+ size="large"
+ type="textarea"
+ style="width: 100%"
+ :autosize="{minRows: 3}"
+ :readonly="state.title =='查看'"
+ >
+ </el-input>
+ </el-form-item>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="主管领导:" prop="executive">
+ <el-input v-model.trim="state.form.executive" :readonly="state.title =='查看'"></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item prop="executiveDate">
+ <el-date-picker
+ v-model="state.form.executiveDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="请选择日期"
+ :disabled="state.title =='查看'"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </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 {getToken} from "@/utils/auth";
+import {
+ updateMaintenanceEvaluate,
+ getMaintenanceEvaluateDetail
+} from "@/api/infrastructureMng/ledger";
+
+import {listUser} from "@/api/system/user";
+import {getOutsourcedReviewDetail, updateOutsourcedReview} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {getDepart} from "@/api/orgStructure/depart";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const checkList = (rule, value, callback) => {
+ if (state.form.outsourcedReviewSubsidiaryList.length == 0) {
+ callback(new Error('协作单位数据不可为空'))
+ } else if(state.form.outsourcedReviewSubsidiaryList.length > 0 && state.form.outsourcedReviewSubsidiaryList.find(item=>item.assistName == '' || item.assistAddress == '' ||item.phone == '')){
+ callback(new Error('协作单位数据未完善'))
+ } else {
+ callback()
+ }
+}
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ companyId: null,
+ reviewName: '',
+ productName: '',
+ deptId: null,
+ outsourcedProcess: '',
+ deptLeaderId: null,
+ deptName: '',
+ deptLeaderName: '',
+ pieceType: null,
+ processType: null,
+ necessity: [],
+ feasibility: [],
+ riskRecognition: [],
+ qualityMeasures: [],
+ progressMeasures: [],
+ economicMeasure: [],
+ outsourcedReviewSubsidiaryList: [],
+ delOutsourcedReviewSubsidiaryIds: [],
+ outsourceType: null,
+ measure: '',
+ applyDept: '',
+ applyDeptDate: '',
+ qualityInspection: '',
+ qualityInspectionDate: '',
+ managementRepresentative: '',
+ managementRepresentativeDate: '',
+ approvalOpinions: '',
+ executive: '',
+ executiveDate: '',
+ },
+ oldDeviceList: [],
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ reviewName: [{ required: true, message: '请填写评审表名称', trigger: 'blur' }],
+ deptId: [{ required: true, message: '请选择申请部门', trigger: 'blur' }],
+ productName: [{ required: true, message: '请填写产品名称', trigger: 'blur' }],
+ outsourcedProcess: [{ required: true, message: '请填写外包过程名称', trigger: 'blur' }],
+ deptLeaderId: [{ required: true, message: '请选择部门负责人', trigger: 'blur' }],
+ pieceType: [{ required: true, message: '请选择是否为关键件、重要件', trigger: 'blur' }],
+ processType: [{ required: true, message: '请选择过程重要性', trigger: 'blur' }],
+ necessity: [{ required: true, message: '请选择过程外包必要性', trigger: 'blur' }],
+ feasibility: [{ required: true, message: '请选择过程外包可行性', trigger: 'blur' }],
+ riskRecognition: [{ required: true, message: '请选择风险识别', trigger: 'blur' }],
+ qualityMeasures: [{ required: true, message: '请选择控制措施', trigger: 'blur' }],
+ progressMeasures: [{ required: true, message: '请选择控制措施', trigger: 'blur' }],
+ economicMeasure: [{ required: true, message: '请选择控制措施', trigger: 'blur' }],
+ outsourcedReviewSubsidiaryList: [{ required: true, validator: checkList, trigger: 'blur' }],
+ outsourceType: [{ required: true, message: '请选择评审意见', trigger: 'blur' }],
+ measure: [{ required: true, message: '请填写措施内容', trigger: 'blur' }],
+ applyDept: [{ required: true, message: '请填写申请部门', trigger: 'blur' }],
+ applyDeptDate: [{ required: true, message: '请选择日期', trigger: 'blur' }],
+ qualityInspection: [{ required: true, message: '请填写质检部', trigger: 'blur' }],
+ qualityInspectionDate: [{ required: true, message: '请选择日期', trigger: 'blur' }],
+ managementRepresentative: [{ required: true, message: '请填写管理者代表', trigger: 'blur' }],
+ managementRepresentativeDate: [{ required: true, message: '请选择日期', trigger: 'blur' }],
+ executive: [{ required: true, message: '请填写主管领导', trigger: 'blur' }],
+ executiveDate: [{ required: true, message: '请选择日期', trigger: 'blur' }]
+ },
+ isAdmin: false,
+ companyList: [],
+ deptList: [],
+ userList: []
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+ state.isAdmin = isAdmin
+ if(isAdmin){
+ state.companyList = companyList
+ }
+ await getDepartList(companyId)
+ await getUserList(companyId)
+ state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+ state.form.companyId = companyId
+ if(state.title == '编辑'||state.title == '查看'){
+ await getInfo(value.id)
+ }
+ dialogVisible.value = true
+}
+
+const addLine = () => {
+ const obj = {
+ id: null,
+ reviewId: null,
+ assistName: '',
+ assistAddress: '',
+ phone: ''
+ }
+ state.form.outsourcedReviewSubsidiaryList.push(obj);
+}
+
+const handleDelete = (i) =>{
+ state.form.outsourcedReviewSubsidiaryList = state.form.outsourcedReviewSubsidiaryList.filter((item,index) => index != i)
+}
+
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ const data = JSON.parse(JSON.stringify(state.form))
+ console.log(data,'data')
+ data.delOutsourcedReviewSubsidiaryIds = state.oldDeviceList.filter(i =>!data.outsourcedReviewSubsidiaryList.some(item=>item.id == i.id)).map(i=>i.id)
+ data.necessity = data.necessity.join(',')
+ data.feasibility = data.feasibility.join(',')
+ data.riskRecognition = data.riskRecognition.join(',')
+ data.qualityMeasures = data.qualityMeasures.join(',')
+ data.progressMeasures = data.progressMeasures.join(',')
+ data.economicMeasure = data.economicMeasure.join(',')
+ data.deptName = state.deptList.find(i=>i.deptId == data.deptId)?.deptName
+ data.deptLeaderName = state.userList.find(i=>i.userId == data.deptLeaderId)?.name
+ if(data.outsourceType == 1){
+ data.measure = ''
+ }
+ if(state.title == '新增'){
+ delete data.id
+ const res = await updateOutsourcedReview(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+ }else{
+ const res = await updateOutsourcedReview(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+ }
+ }
+}
+
+const getInfo = async (id)=> {
+ const res = await getOutsourcedReviewDetail({id: id})
+ if(res.code == 200){
+ Object.keys(state.form).forEach(key => {
+ if (key in res.data) {
+ state.form[key] = res.data[key]
+ }
+ })
+ state.form.outsourcedReviewSubsidiaryList = res.data.outsourcedReviewSubsidiaryList?.map(item=>{
+ return {
+ id: item.id,
+ reviewId: item.reviewId,
+ assistName: item.assistName,
+ assistAddress: item.assistAddress,
+ phone: item.phone
+ }
+ })
+ state.oldDeviceList = state.form.outsourcedReviewSubsidiaryList
+ state.form.necessity = state.form.necessity.split(',')
+ state.form.feasibility = state.form.feasibility.split(',')
+ state.form.riskRecognition = state.form.riskRecognition.split(',')
+ state.form.qualityMeasures = state.form.qualityMeasures.split(',')
+ state.form.progressMeasures =state.form.progressMeasures.split(',')
+ state.form.economicMeasure = state.form.economicMeasure.split(',')
+ // state.form.applyDeptDate = state.form.applyDeptDate.substring(0,10)
+ // state.form.qualityInspectionDate = state.form.qualityInspectionDate.substring(0,10)
+ // state.form.managementRepresentativeDate = state.form.managementRepresentativeDate.substring(0,10)
+ // state.form.executiveDate = state.form.executiveDate.substring(0,10)
+ }else{
+ ElMessage.warning(res.message)
+ }
+}
+
+const getDeptList = async ()=>{
+ state.form.deptId = null
+ state.form.deptLeaderId = null
+ await getDepartList(state.form.companyId)
+ await getUserList(state.form.companyId)
+}
+
+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 getUserList = async (companyId)=> {
+ const res = await listUser({pageIndex: 1,pageSize: 999,companyId: companyId})
+ if(res.code == 200){
+ state.userList = res.data.list?res.data.list.map(item=>{
+ const user = item.id
+ const {id, ...data} = item
+ return {
+ ...data,
+ userId: user
+ }
+ }):[]
+ }else{
+ ElMessage.warning(res.message)
+ }
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ companyId: null,
+ reviewName: '',
+ productName: '',
+ deptId: '',
+ outsourcedProcess: '',
+ deptLeaderId: '',
+ deptName: '',
+ deptLeaderName: '',
+ pieceType: null,
+ processType: null,
+ necessity: [],
+ feasibility: [],
+ riskRecognition: [],
+ qualityMeasures: [],
+ progressMeasures: [],
+ economicMeasure: [],
+ outsourcedReviewSubsidiaryList: [],
+ delOutsourcedReviewSubsidiaryIds: [],
+ outsourceType: null,
+ measure: '',
+ applyDept: '',
+ applyDeptDate: '',
+ qualityInspection: '',
+ qualityInspectionDate: '',
+ managementRepresentative: '',
+ managementRepresentativeDate: '',
+ approvalOpinions: '',
+ executive: '',
+ executiveDate: '',
+ }
+ 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>
+<style lang="scss">
+.customedTable{
+ width: calc(100% - 150px);
+ margin-left: 150px;
+ margin-bottom: 30px;
+ .el-table__cell{
+ padding: 2px 0 !important;
+ font-size: 14px !important;
+ }
+ .cell{
+ padding: 0 2px !important;
+ font-size: 14px !important;
+ }
+}
+</style>
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/index.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/index.vue
new file mode 100644
index 0000000..e59ab28
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProcessReview/index.vue
@@ -0,0 +1,299 @@
+<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 >
+ <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button>
+ <el-button v-if="isAdmin" type="primary" plain @click="reset">重置</el-button>
+<!-- <el-button type="primary">导出</el-button>-->
+ </el-form-item>
+ </el-form>
+ </div>
+ <!-- 表格数据 -->
+ <el-table v-loading="loading" :data="dataList" :border="true">
+ <el-table-column type="index" label="序号"></el-table-column>
+ <el-table-column prop="reviewName" align="center" label="评审表名称">
+ <template #default="scope">
+ {{scope.row.reviewName}}
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" align="center">
+ <template #default="scope">
+ <el-button link type="primary" @click="openDialog('view',scope.row)">查看</el-button>
+ <el-button link type="primary" @click="openDialog('edit',scope.row)">编辑</el-button>
+ <el-button link type="primary" @click="downloadFile(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 Cookies from "js-cookie";
+import editDialog from './components/editDialog.vue'
+import useUserStore from "@/store/modules/user";
+import {generateWordDocument} from "@/utils/exportWord";
+import {
+ delMaintenanceEvaluate,
+ getMaintenanceEvaluateDetail,
+ getMaintenanceEvaluateList
+} from "@/api/infrastructureMng/ledger";
+import {
+ delOutsourcedReview,
+ getOutsourcedReviewDetail,
+ getOutsourcedReviewList
+} from "@/api/outsourcingCooperate/outsourcingCooperate";
+
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null
+ },
+ total: 0,
+ dataList: [],
+ companyList: [],
+ isAdmin: false,
+ keyList: [
+ {id: 1, label: '关键件'},
+ {id: 2, label: '重要件'},
+ {id: 3, label: '普通件'}
+ ],
+ vitalList: [
+ {id: 1, label: '关键'},
+ {id: 2, label: '一般'}
+ ],
+ necessaryList: [
+ {id: '1', label: '本单位没有能力满足产品实现需求'},
+ {id: '2', label: '生产急需,利用外部资源实现产品'},
+ {id: '3', label: '其他'}
+ ],
+ workList: [
+ {id: '1', label: '本单位可提供现成的图纸、技术资料'},
+ {id: '2', label: '本单位可提供合格的原材料'},
+ {id: '3', label: '本单位有能力对供方产品实现过程实施控制'},
+ {id: '4', label: '其他'}
+ ],
+ riskList: [
+ {id: '1', label: '外包过程对我所产品质量有很大影响'},
+ {id: '2', label: '外包产品供货影响我所生产进度'},
+ {id: '3', label: '实施外包对我所经济效益有影响'},
+ {id: '4', label: '其他'}
+ ],
+ qualityList: [
+ {id: '1', label: '进货检验'},
+ {id: '2', label: '我司到供方现场验证'},
+ {id: '3', label: '顾客到供方现场验证'}
+ ],
+ processList: [
+ {id: '1', label: '与供方及时沟通'},
+ {id: '2', label: '要求供方列出进度计划'},
+ {id: '3', label: '纳入协同合作采取经济制约'}
+ ],
+ economyList: [
+ {id: '1', label: '我司财务预算'},
+ {id: '2', label: '在预算范围内外包'},
+ {id: '3', label: '与供方协商解决'}
+ ],
+ signList: [
+ {id: 1, label: '可以外包'},
+ {id: 2, label: '不可以外包,由部门采取措施解决。措施内容:'},
+ ]
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = toRefs(data);
+const userInfo = ref()
+onMounted(async ()=>{
+ if(userStore.roles.includes('admin')){
+ data.isAdmin = true
+ await getCompanyList()
+ }else{
+ data.isAdmin = false
+ data.queryParams.companyId = userStore.companyId
+ }
+ await getList()
+})
+
+onUnmounted(()=>{
+
+})
+
+const getList = async () => {
+ loading.value = true
+ const res = await getOutsourcedReviewList(data.queryParams)
+ if(res.code == 200){
+ data.dataList = res.data.list || []
+ 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 = async (val)=>{
+ const res = await getOutsourcedReviewDetail({id: val.id})
+ if(res.code == 200){
+ if(res.data){
+ let tableData = res.data
+ tableData.reviewList = res.data.outsourcedReviewSubsidiaryList
+ tableData.keyList = data.keyList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.pieceType == item.id ? false: true
+ }
+ })
+ tableData.vitalList = data.vitalList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.processType == item.id ? false: true
+ }
+ })
+ tableData.necessaryList = data.necessaryList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.necessity.split(',').includes(item.id) ? false: true
+ }
+ })
+ tableData.workList = data.workList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.feasibility.split(',').includes(item.id) ? false: true
+ }
+ })
+ tableData.riskList = data.riskList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.riskRecognition.split(',').includes(item.id) ? false: true
+ }
+ })
+ tableData.qualityList = data.qualityList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.qualityMeasures.split(',').includes(item.id) ? false: true
+ }
+ })
+ tableData.processList = data.processList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.progressMeasures.split(',').includes(item.id) ? false: true
+ }
+ })
+ tableData.economyList = data.economyList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.economicMeasure.split(',').includes(item.id) ? false: true
+ }
+ })
+ tableData.signList = data.signList.map(item=>{
+ return {
+ ...item,
+ checked: tableData.outsourceType == item.id ? false: true
+ }
+ })
+ tableData.applyDeptDate = tableData.applyDeptDate.replace(/^(\d{4})-(\d{1,2})-(\d{1,2}).*$/, (match, year, month, day) => `${year}年${parseInt(month)}月${parseInt(day)}日`)
+ tableData.qualityInspectionDate = tableData.qualityInspectionDate.replace(/^(\d{4})-(\d{1,2})-(\d{1,2}).*$/, (match, year, month, day) => `${year}年${parseInt(month)}月${parseInt(day)}日`)
+ tableData.managementRepresentativeDate = tableData.managementRepresentativeDate.replace(/^(\d{4})-(\d{1,2})-(\d{1,2}).*$/, (match, year, month, day) => `${year}年${parseInt(month)}月${parseInt(day)}日`)
+ tableData.executiveDate = tableData.executiveDate.replace(/^(\d{4})-(\d{1,2})-(\d{1,2}).*$/, (match, year, month, day) => `${year}年${parseInt(month)}月${parseInt(day)}日`)
+ tableData.reviewList = res.data.outsourcedReviewSubsidiaryList
+ try {
+ generateWordDocument('/outsourceProcessReview.docx', tableData, tableData.reviewName +'.docx');
+ } catch (error){
+ ElMessage({
+ type: 'warning',
+ message: '导出失败'
+ });
+ }
+ }else{
+ ElMessage.warning('暂无数据')
+ }
+ }else{
+ ElMessage.warning(res.message)
+ }
+}
+
+const openDialog = (type, value) => {
+ dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList);
+}
+
+/** 重置新增的表单以及其他数据 */
+const reset= async()=> {
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null
+ }
+ await getCompanyList()
+ await getList()
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delOutsourcedReview({id: val.id})
+ if(res.code == 200){
+ ElMessage.success('数据删除成功')
+ await getList()
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProductName/components/editDialog.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProductName/components/editDialog.vue
new file mode 100644
index 0000000..4edab53
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProductName/components/editDialog.vue
@@ -0,0 +1,168 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="700px"
+ :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="请选择" :disabled="state.title =='查看'" 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="supplierId">
+ <el-select v-model="state.form.supplierId" placeholder="请选择" :disabled="state.title =='查看'" clearable style="width: 100%">
+ <el-option
+ v-for="item in state.supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="产品名称:" prop="productName">
+ <el-input v-model.trim="state.form.productName" :readonly="state.title =='查看'" placeholder="产品名称"></el-input>
+ </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 {updateInfoPlatforms} from "@/api/staffManage/staff";
+import {getSupplierPage} from "@/api/supplier/supplierList";
+import {updateOutsourcedProductNameList} from "@/api/outsourcingCooperate/outsourcingCooperate";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ companyId: null,
+ productName: '',
+ supplierId: null,
+ supplierName: ''
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ productName: [{ required: true, message: '请输入外包产品名称', trigger: 'blur' }],
+ supplierId: [{ required: true, message: '请选择供应商', trigger: 'blur' }]
+ },
+ isAdmin: false,
+ companyList: [],
+ supplierList: []
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+ state.isAdmin = isAdmin
+ if(isAdmin){
+ state.companyList = companyList
+ }
+ await getSupplierList()
+ 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]
+ }
+ })
+ }
+ dialogVisible.value = true
+}
+
+const getSupplierList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getSupplierPage(queryParams)
+ if (res.code == 200) {
+ state.supplierList = res.data.list?res.data.list:[]
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ let data = {}
+ if(state.title == '新增'){
+ data = {
+ companyId: state.form.companyId,
+ productName: state.form.productName,
+ supplierId: state.form.supplierId,
+ supplierName: state.supplierList.find(i=>i.id == state.form.supplierId)?.supplierName
+ }
+ }else{
+ data = state.form
+ }
+ const res = await updateOutsourcedProductNameList(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+
+ }
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ companyId: null,
+ productName: '',
+ supplierId: null,
+ supplierName: ''
+ }
+ 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/qualityInfo/outsourcingCooperate/outsourcedProductName/index.vue b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProductName/index.vue
new file mode 100644
index 0000000..f67a308
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/outsourcedProductName/index.vue
@@ -0,0 +1,160 @@
+<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 >
+ <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button>
+ <el-button v-if="isAdmin" 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="supplierName" align="center"/>
+ <el-table-column label="产品名称" prop="productName" align="center"/>
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+ <template #default="scope">
+ <el-button link type="primary" @click="openDialog('view',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 Cookies from "js-cookie";
+import editDialog from './components/editDialog.vue'
+import useUserStore from "@/store/modules/user";
+import {
+ delOutsourcedProductNameList,
+ getOutsourcedProductNameList
+} from "@/api/outsourcingCooperate/outsourcingCooperate";
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null
+ },
+ total: 0,
+ dataList: [],
+ companyList: [],
+ isAdmin: false
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = toRefs(data);
+const userInfo = ref()
+onMounted(async ()=>{
+ userInfo.value = JSON.parse(Cookies.get('userInfo'))
+ if(userStore.roles.includes('admin')){
+ data.isAdmin = true
+ await getCompanyList()
+ }else{
+ data.isAdmin = false
+ data.queryParams.companyId = userStore.companyId
+ }
+ await getList()
+})
+
+onUnmounted(()=>{
+
+})
+
+const getList = async () => {
+ loading.value = true
+ const res = await getOutsourcedProductNameList(data.queryParams)
+ if(res.code == 200){
+ data.dataList = res.data.list || []
+ 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 openDialog = (type, value) => {
+ dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList );
+}
+
+/** 重置新增的表单以及其他数据 */
+const reset= async()=> {
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null
+ }
+ await getCompanyList()
+ await getList()
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delOutsourcedProductNameList({id: val.id})
+ if(res.code == 200){
+ ElMessage.success('数据删除成功')
+ await getList()
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/outsourcingCooperate/unqualifiedHandle/components/editDialog.vue b/src/views/work/qualityInfo/outsourcingCooperate/unqualifiedHandle/components/editDialog.vue
new file mode 100644
index 0000000..1428041
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/unqualifiedHandle/components/editDialog.vue
@@ -0,0 +1,265 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="700px"
+ :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="请选择" :disabled="state.title =='查看'" 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="supplierId">
+ <el-select v-model="state.form.supplierId" placeholder="请选择" :disabled="state.title =='查看'" clearable style="width: 100%">
+ <el-option
+ v-for="item in state.supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="不合格品名称:" prop="unqualifiedProductName">
+ <el-input v-model.trim="state.form.unqualifiedProductName" :readonly="state.title =='查看'" placeholder="不合格品名称"></el-input>
+ </el-form-item>
+ <el-form-item label="文件名称:" prop="fileName">
+ <el-input v-model.trim="state.form.fileName" :readonly="state.title =='查看'" placeholder="文件名称"></el-input>
+ </el-form-item>
+ <el-form-item label="文件:" prop="filePath">
+ <el-upload :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 {updateInfoPlatforms} from "@/api/staffManage/staff";
+import {getSupplierPage} from "@/api/supplier/supplierList";
+import {
+ updateOutsourcedCommon,
+ updateOutsourcedProductNameList,
+ updateOutsourcedUnqualified
+} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {delPic} from "@/api/onlineEducation/banner";
+import {getToken} from "@/utils/auth";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const checkFiles = (rule, value, callback) => {
+ if (state.fileList.length == 0) {
+ callback(new Error('请上传文件'))
+ } else {
+ callback()
+ }
+}
+const superRef = ref()
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ unqualifiedProductName: '',
+ fileName: '',
+ filePath: '',
+ format: ''
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ supplierId: [{ required: true, message: '请选择供应商', trigger: 'blur' }],
+ unqualifiedProductName: [{ required: true, message: '请填写不合格品名称', trigger: 'blur' }],
+ filePath: [{ required: true, validator: checkFiles, trigger: 'blur' }]
+ },
+ isAdmin: false,
+ companyList: [],
+ supplierList: [],
+ 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
+ }
+ await getSupplierList()
+ 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: '工艺流程图'
+ }
+ state.fileList = [obj]
+ }
+ }
+ dialogVisible.value = true
+}
+
+const getSupplierList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getSupplierPage(queryParams)
+ if (res.code == 200) {
+ state.supplierList = res.data.list?res.data.list:[]
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ let data = {}
+ if(state.title == '新增'){
+ data = {
+ companyId: state.form.companyId,
+ fileName: state.form.fileName,
+ unqualifiedProductName: state.form.unqualifiedProductName,
+ supplierId: state.form.supplierId,
+ supplierName: state.supplierList.find(i=>i.id == state.form.supplierId)?.supplierName,
+ filePath: state.form.filePath,
+ format: state.form.format
+ }
+ }else{
+ data = state.form
+ }
+ const res = await updateOutsourcedUnqualified(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+
+ }
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ companyId: null,
+ supplierId: null,
+ supplierName: '',
+ unqualifiedProductName: '',
+ fileName: '',
+ filePath: '',
+ format: ''
+ }
+ state.fileList = []
+ superRef.value.clearValidate();
+ superRef.value.resetFields()
+ dialogVisible.value = false;
+}
+
+const handleAvatarSuccess = (res, uploadFile) => {
+ if(res.code == 200){
+ state.form.filePath = res.data.path
+ state.form.format = '.' + res.data.filename.split('.')[1]
+ }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){
+ // ElMessage({
+ // type: 'success',
+ // message: '文件已删除'
+ // })
+ state.form.filePath = ''
+ state.form.format = ''
+ }else{
+ ElMessage({
+ type: 'warning',
+ message: res.message
+ })
+ }
+ }).catch(() => {
+ state.form.imgUrl = ''
+ });
+}
+
+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/qualityInfo/outsourcingCooperate/unqualifiedHandle/index.vue b/src/views/work/qualityInfo/outsourcingCooperate/unqualifiedHandle/index.vue
new file mode 100644
index 0000000..7455709
--- /dev/null
+++ b/src/views/work/qualityInfo/outsourcingCooperate/unqualifiedHandle/index.vue
@@ -0,0 +1,214 @@
+<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 >
+ <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button>
+ <el-button v-if="isAdmin" 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="supplierName" align="center"/>
+ <el-table-column label="不合格品名称" prop="supplierName" align="center"/>
+ <el-table-column label="纠正措施记录" align="center">
+ <template #default="scope">
+ <el-link type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName !== '' ?scope.row.fileName + scope.row.format : '纠正措施记录'}}</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.filePath)">下载</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 Cookies from "js-cookie";
+import editDialog from './components/editDialog.vue'
+import useUserStore from "@/store/modules/user";
+import {
+ delOutsourcedCommon,
+ delOutsourcedProductNameList, delOutsourcedUnqualified, getOutsourcedCommonList,
+ getOutsourcedProductNameList, getOutsourcedUnqualifiedList
+} from "@/api/outsourcingCooperate/outsourcingCooperate";
+import {renderAsync} from "docx-preview";
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null
+ },
+ total: 0,
+ dataList: [],
+ companyList: [],
+ isAdmin: false
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = toRefs(data);
+const userInfo = ref()
+onMounted(async ()=>{
+ userInfo.value = JSON.parse(Cookies.get('userInfo'))
+ if(userStore.roles.includes('admin')){
+ data.isAdmin = true
+ await getCompanyList()
+ }else{
+ data.isAdmin = false
+ data.queryParams.companyId = userStore.companyId
+ }
+ await getList()
+})
+
+onUnmounted(()=>{
+
+})
+
+const getList = async () => {
+ loading.value = true
+ const res = await getOutsourcedUnqualifiedList(data.queryParams)
+ if(res.code == 200){
+ data.dataList = res.data.list || []
+ 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 = (path)=>{
+ window.open(import.meta.env.VITE_APP_BASE_API + '/' + path)
+}
+
+const openFile = async(path)=>{
+ const ext = path.split('.').pop().toLowerCase();
+ if (ext === 'doc' || ext === 'pptx' || ext === 'ppt') {
+ ElMessageBox.confirm(`暂不支持线上预览.${ext}文件,是否下载查看?`, '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => {
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }).catch(() => {
+ console.log('取消预览')
+ });
+ return
+ }else if(ext === 'pdf' || ext === 'jpg' || ext === 'jpeg' || ext === 'png' || ext === 'cad'){
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }else{
+ 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}`);
+ }
+ }
+}
+
+const openDialog = (type, value) => {
+ dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList );
+}
+
+/** 重置新增的表单以及其他数据 */
+const reset= async()=> {
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null
+ }
+ await getCompanyList()
+ await getList()
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delOutsourcedUnqualified({id: val.id})
+ if(res.code == 200){
+ ElMessage.success('数据删除成功')
+ await getList()
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
--
Gitblit v1.9.2