多体系建设信息化条统-前端
zhouwx
2025-09-29 b1fa82e418973b910f9fe04f9afde02d14ea043e
修改
12 files modified
18 files added
4223 ■■■■■ changed files
package.json 8 ●●●● patch | view | raw | blame | history
public/continuousImprovementExample.docx patch | view | raw | blame | history
public/externalExample.docx patch | view | raw | blame | history
public/internalExample.docx patch | view | raw | blame | history
public/performanceAppraisalExample.docx patch | view | raw | blame | history
public/qualityFinancialAnalysisExample.docx patch | view | raw | blame | history
src/api/external/index.js 34 ●●●●● patch | view | raw | blame | history
src/api/internal/need.js 34 ●●●●● patch | view | raw | blame | history
src/api/performanceAppraisal/index.js 34 ●●●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/environment/controlFactors/components/editDialog.vue 2 ●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/environment/environmentalFactors/components/editDialog.vue 2 ●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/need/evaluate/components/editDialog.vue 2 ●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/need/needIdentify/components/editDialog.vue 2 ●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/qualityObjectives/objective/components/objectiveDialog.vue 2 ●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/qualityObjectives/table/components/tableCompanyDialog.vue 2 ●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/qualityObjectives/table/components/tableDeptDialog.vue 2 ●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/riskManage/control/components/editDialog.vue 4 ●●●● patch | view | raw | blame | history
src/views/build/conpanyFunctionConsult/riskManage/record/components/editDialog.vue 4 ●●●● patch | view | raw | blame | history
src/views/work/financialMng/qualityFinancialAnalysis/components/editDialog.vue 474 ●●●●● patch | view | raw | blame | history
src/views/work/financialMng/qualityFinancialAnalysis/index.vue 587 ●●●●● patch | view | raw | blame | history
src/views/work/marketingManagement/customerList/need/components/editDialog.vue 14 ●●●● patch | view | raw | blame | history
src/views/work/procurementPlatform/warehouseManagement/monthlyInspectionRecord/components/editDialog.vue 20 ●●●● patch | view | raw | blame | history
src/views/work/qualityManage/continuousImprovement/components/editDialog.vue 449 ●●●●● patch | view | raw | blame | history
src/views/work/qualityManage/continuousImprovement/index.vue 297 ●●●●● patch | view | raw | blame | history
src/views/work/qualityManage/performanceAppraisal/components/editDialog.vue 594 ●●●●● patch | view | raw | blame | history
src/views/work/qualityManage/performanceAppraisal/index.vue 281 ●●●●● patch | view | raw | blame | history
src/views/work/qualityManage/qualityInformationPage/external/components/editDialog.vue 364 ●●●●● patch | view | raw | blame | history
src/views/work/qualityManage/qualityInformationPage/external/index.vue 235 ●●●●● patch | view | raw | blame | history
src/views/work/qualityManage/qualityInformationPage/internal/components/editDialog.vue 541 ●●●●● patch | view | raw | blame | history
src/views/work/qualityManage/qualityInformationPage/internal/index.vue 235 ●●●●● patch | view | raw | blame | history
package.json
@@ -24,16 +24,22 @@
    "@wangeditor/plugin-upload-attachment": "^1.1.0",
    "angular-expressions": "^1.5.0",
    "axios": "0.27.2",
    "buffer": "^6.0.3",
    "docx": "^9.5.1",
    "docx-preview": "^0.3.5",
    "docx-templates": "^4.14.1",
    "docxtemplater": "^3.65.1",
    "docxtemplater-image-module-free": "^1.1.1",
    "echarts": "5.4.0",
    "element-plus": "2.2.27",
    "file-saver": "2.0.5",
    "file-saver": "^2.0.5",
    "fs-extra": "^11.3.0",
    "fuse.js": "6.6.2",
    "html-docx-js": "^0.3.1",
    "html2canvas": "^1.4.1",
    "js-base64": "^3.7.5",
    "js-cookie": "3.0.1",
    "jsdom": "^27.0.0",
    "jsencrypt": "3.3.1",
    "jspdf": "^3.0.1",
    "jszip-utils": "^0.1.0",
public/continuousImprovementExample.docx
Binary files differ
public/externalExample.docx
Binary files differ
public/internalExample.docx
Binary files differ
public/performanceAppraisalExample.docx
Binary files differ
public/qualityFinancialAnalysisExample.docx
Binary files differ
src/api/external/index.js
New file
@@ -0,0 +1,34 @@
import request from "@/utils/request";
export function getEnternal(params) {
    return request({
        url: '/quality/information/exterior/list',
        method: 'get',
        params: params
    })
}
export function addEnternal(data) {
    return request({
        url: '/quality/information/exterior/insert',
        method: 'post',
        data: data
    })
}
export function editEnternal(params) {
    return request({
        url: `/quality/information/exterior/update`,
        method: 'post',
        data: params
    })
}
export function delEnternal(data) {
    return request({
        url: `/quality/information/exterior/deleted?exteriorId=${data}`,
        method: 'get'
    })
}
src/api/internal/need.js
New file
@@ -0,0 +1,34 @@
import request from "@/utils/request";
export function getInternal(params) {
    return request({
        url: '/quality/information/inside/list',
        method: 'get',
        params: params
    })
}
export function addInternal(data) {
    return request({
        url: '/quality/information/inside/insert',
        method: 'post',
        data: data
    })
}
export function editInternal(params) {
    return request({
        url: `/quality/information/inside/update`,
        method: 'post',
        data: params
    })
}
export function delInternal(data) {
    return request({
        url: `/quality/information/inside/deleted?insideId=${data}`,
        method: 'get'
    })
}
src/api/performanceAppraisal/index.js
New file
@@ -0,0 +1,34 @@
import request from "@/utils/request";
export function getEvaluation(params) {
    return request({
        url: '/performance/evaluation/list',
        method: 'get',
        params: params
    })
}
export function addEvaluation(data) {
    return request({
        url: '/performance/evaluation/insert',
        method: 'post',
        data: data
    })
}
export function editEvaluation(params) {
    return request({
        url: `/performance/evaluation/update`,
        method: 'post',
        data: params
    })
}
export function delEvaluation(data) {
    return request({
        url: `/performance/evaluation/deleted?evaluationId=${data}`,
        method: 'get'
    })
}
src/views/build/conpanyFunctionConsult/environment/controlFactors/components/editDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
src/views/build/conpanyFunctionConsult/environment/environmentalFactors/components/editDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
src/views/build/conpanyFunctionConsult/need/evaluate/components/editDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
src/views/build/conpanyFunctionConsult/need/needIdentify/components/editDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
src/views/build/conpanyFunctionConsult/qualityObjectives/objective/components/objectiveDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
src/views/build/conpanyFunctionConsult/qualityObjectives/table/components/tableCompanyDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
src/views/build/conpanyFunctionConsult/qualityObjectives/table/components/tableDeptDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
src/views/build/conpanyFunctionConsult/riskManage/control/components/editDialog.vue
@@ -3,12 +3,12 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="1220px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules"  label-position="right" label-width="130">
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules"  label-position="top" label-width="130">
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
src/views/build/conpanyFunctionConsult/riskManage/record/components/editDialog.vue
@@ -3,12 +3,12 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="50%"
        width="1250px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules"  label-position="right" label-width="130">
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules"  label-position="top" label-width="130">
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
src/views/work/financialMng/qualityFinancialAnalysis/components/editDialog.vue
New file
@@ -0,0 +1,474 @@
<template>
  <div class="notice">
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="750px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules" label-position="top" label-width="120px" >
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
              <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom">
                <el-option
                    v-for="item in state.companyList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="年份:" prop="year" >
              <el-select
                  :disabled="title === '查看'"
                  v-model="state.form.year"
                  filterable
                  allow-create
                  default-first-option
                  :reserve-keyword="false"
                  placeholder="请选择年份"
                  @change="handleChangeNum"
                  style="width: 100%"
              >
                <el-option
                    v-for="item in state.yearList"
                    :key="item.value"
                    :label="item.label"
                    :value="item.label"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="一 、基本情况:" prop="method" >
              <el-input :disabled="title === '查看'" v-model="state.form.method" :rows="4" type="textarea" placeholder=""/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="二 、综合分析:" v-if="showEditor"  required>
              <t-editor style="width: 800px" ref="myEditor" :toolbar="toolbar" :value="state.form.policy" ></t-editor>
            </el-form-item>
            <el-form-item label="二 、综合分析:" v-else>
              <div class="ql-container ql-snow" style="height: 500px;width: 100%;margin-top: 10px;" >
                <div class="ql-editor">
                  <div class="reviewTable" v-html="state.form.policy"  @click="showFile($event)"></div>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="三 、内外部损失:" prop="method" >
              <el-input :disabled="title === '查看'" v-model="state.form.method" :rows="4" type="textarea" placeholder=""/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="四 、纠正措施:" prop="method" >
              <el-input :disabled="title === '查看'" v-model="state.form.method" :rows="4" type="textarea" placeholder=""/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="五 、分析的结果:" prop="method" >
              <el-input :disabled="title === '查看'" v-model="state.form.method" :rows="4" type="textarea" placeholder=""/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="六 、改进建议:" prop="method" >
              <el-input :disabled="title === '查看'" v-model="state.form.method" :rows="4" type="textarea" placeholder=""/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="部门:" prop="leadId" >
              <el-select clearable v-model="state.form.leadId" :disabled="title =='查看'" filterable  style="width: 100%">
                <el-option
                    v-for="item in state.userList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="leadTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.leadTime"
                  type="date"
                  placeholder="请选择日期"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer v-if="title !== '查看'">
        <span class="dialog-footer">
            <el-button @click="handleClose" size="default">取 消</el-button>
            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {onMounted, reactive, ref, toRefs} from 'vue'
import Cookies from "js-cookie";
import {getCompany} from "@/api/onlineEducation/company";
import {ElMessage} from "element-plus";
import {getUser} from "@/api/onlineEducation/user";
import {addObjective, editObject, getDept} from "@/api/qualityObjectives/object";
import {listUser} from "@/api/system/user";
import TEditor from "@/components/Tinymce/Tinymce.vue";
import axios from "axios";
import {getToken} from "@/utils/auth";
const dialogVisible = ref(false);
const title = ref("");
const busRef = ref();
const length = ref()
const emit = defineEmits(["getList"]);
const dataRef = ref();
const toolbar = ref('  undo redo | table')
const myEditor = ref();
const showEditor = ref(true);
const state = reactive({
  form: {
    id: '',
    year: '',
    num: '',
    type: '',
    departId: '',
    method: '',
    compilationId:'',
    compilationTime:'',
    qualityId: '',
    qualityTime:'',
    leadId:'',
    leadTime: '',
    qualityTargets:[],
  },
  rules: {
    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
    year: [{ required: true, message: '请输入年份', trigger: 'blur' }],
    num: [{ required: true, message: '请输入序号', trigger: 'blur' }],
    type: [{ required: true, message: '请选择级别', trigger: 'blur' }],
    method: [{ required: true, message: '请输入目标测量方法', trigger: 'blur' }],
    compilationId: [{ required: true, message: '请选择编制人员', trigger: 'blur' }],
    compilationTime: [{ required: true, message: '请选择日期', trigger: 'blur' }],
    qualityId: [{ required: true, message: '请选择质量管理部人员', trigger: 'blur' }],
    qualityTime: [{ required: true, message: '请选择日期', trigger: 'blur' }],
    leadId: [{ required: true, message: '请选择公司分管领导', trigger: 'blur' }],
    leadTime: [{ required: true, message: '请选择日期', trigger: 'blur' }],
    departId: [{ required: true, message: '请选择部门', trigger: 'blur' }],
    objName: [{required: true, message: "质量目标不能为空", trigger: "blur"}],
  },
  isAdmin: false,
  companyList: [],
  deptList: [],
  peopleList: [],
  yearList: [
    {
      value: 1,
      label: '2025'
    },
    {
      value: 2,
      label: '2024'
    },
    {
      value: 3,
      label: '2023'
    },
    {
      value: 4,
      label: '2022'
    },
    {
      value: 5,
      label: '2021'
    },
  ],
  levelList: [
    {
      value: 1,
      label: '公司级'
    },
    {
      value: 2,
      label: '部门级'
    },
  ]
})
const openDialog = async (type, value,companyList) => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  state.isAdmin = userInfo.userType === 0;
  state.form.companyName = userInfo.companyName
  state.form.companyId = userInfo.companyId
  if(state.isAdmin){
    state.companyList = companyList
    state.form.companyId = null
  }
  showEditor.value = false
  title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
  if(type === 'edit' || type === 'review') {
    state.form = JSON.parse(JSON.stringify(value));
    state.form.compilationBy = state.form.compilationId
    state.form.leadBy = state.form.leadId
    state.form.qualityBy = state.form.qualityId
    if(state.isAdmin){
      state.form.companyId = value.companyId
      state.form.companyName = value.companyName
    }
  }
  if(type === 'review') {
    showEditor.value = false
  }
  if(type === 'edit' || type === 'add') {
    showEditor.value = true;
  }
  await getDeptList()
  await   getPeopleList()
  dialogVisible.value = true;
}
const addObject = () => {
  state.form.qualityTargets.push({})
}
const getDeptList = async () => {
  const param = {
    pageNum: 1,
    pageSize: 999,
    companyId: state.form.companyId
  }
  const res = await getDept(param)
  if(res.code === 200){
    state.deptList = res.data
  }
}
const onSubmit = async () => {
  state.form.policy = tinyMCE.activeEditor.getContent();
console.log('1',state.form.policy)
  const valid = await busRef.value.validate()
  if(valid){
    // if(title.value === '新增'){
    //   console.log('sta',state.form)
    //   const {id, ...data} = JSON.parse(JSON.stringify(state.form))
    //   const res = await addObjective(data)
    //   if(res.code === 200){
    //     ElMessage({
    //       type: 'success',
    //       message: '新增成功'
    //     });
    //   }else{
    //     ElMessage.warning(res.message)
    //   }
    //   emit("getList")
    //   busRef.value.clearValidate();
    //   reset();
    //   dialogVisible.value = false;
    // }else if(title.value === '编辑'){
    //   const {...data} = JSON.parse(JSON.stringify(state.form))
    //   if(data.qualityTargets && data.qualityTargets.length == 0){
    //     ElMessage.warning('请填写质量目标')
    //     return
    //   }
    //   const res = await editObject(data)
    //   if(res.code === 200){
    //     ElMessage({
    //       type: 'success',
    //       message: '编辑成功'
    //     });
    //   }else{
    //     ElMessage.warning(res.message)
    //   }
    //   emit("getList")
    //   busRef.value.clearValidate();
    //   reset();
    //   dialogVisible.value = false;
    // }
  }
}
const handleClose = () => {
  busRef.value.clearValidate();
  reset();
  dialogVisible.value = false;
  emit("getList")
}
const reset = () => {
  state.form = {
    id: '',
    year: '',
    num: '',
    type: '',
    departId: '',
    method: '',
    compilationBy:'',
    compilationTime:'',
    qualityBy: '',
    qualityTime:'',
    leadBy:'',
    leadTime: '',
    qualityTargets:[],
  }
  state.peopleList = []
  state.companyList = []
}
const handleDelete = (val) => {
  state.form.qualityTargets = state.form.qualityTargets.filter(item=> item != val)
}
const getPeopleList = async ()=> {
  if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){
    return
  }
  const queryParams = {
    pageNum: 1,
    pageSize: 9999,
    companyId: state.form.companyId
  }
  const res = await getUser(queryParams)
  if(res.code == 200){
    state.userList = res.data.list?res.data.list:[]
  }else{
    ElMessage.warning(res.message)
  }
};
const selectValue = (val) => {
  state.peopleList.forEach(item => {
    if(item.name === val){
      state.form.compilationBy = item.id
    }
  })
}
const handleChangeNum = (value) => {
  if (!/^\d+$/.test(value)) { // 验证是否为数字
    ElMessage.warning('只能输入数字')
    state.form.year = '' // 重置选择,避免非法值被添加到options中
  } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项
    state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
  }
}
const selectValueCom = (val) => {
  state.form.leadId = null
  state.form.qualityId = null
  state.form.compilationId = null
  state.form.leadName = null
  state.form.qualityName = null
  state.form.compilationName = null
  state.form.departId = null
  state.companyList.forEach(item => {
    if(item.id === val){
      state.form.companyName = item.name
    }
  })
  getDeptList()
  getPeopleList()
}
const changeLevel = () => {
  // state.form.companyName = ''
  state.form.departId = null
}
const getCompanyList = async (val)=>{
  if(val){
    const queryParams = {
      name: val
    }
    const res = await getCompany(queryParams)
    if (res.code == 200) {
      state.companyList = res.data.list
    } else {
      ElMessage.warning(res.message)
    }
  }else {
    const queryParams = {
      pageSize: 999,
      pageNum: 1,
    }
    const res = await getCompany(queryParams)
    if (res.code == 200) {
      state.companyList = res.data.list
    } else {
      ElMessage.warning(res.message)
    }
  }
}
const showFile = (e) => {
  if(e.target.nodeName === 'A'){
    console.log("e",e)
    e.preventDefault();
    const file = {
      fileUrl: e.target.href,
      fileName: e.target.innerHTML
    }
    axios.get( file.fileUrl,{
          headers:
              {
                'Content-Type': 'application/json',
                'Authorization':getToken(),
              },
          responseType: 'blob'
        }
    ).then(res=>{
      if (res) {
        const link = document.createElement('a')
        let blob = new Blob([res.data],{type: res.data.type})
        link.style.display = "none";
        link.href = URL.createObjectURL(blob); // 创建URL
        link.setAttribute("download", file.fileName);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      } else {
        this.$message.error('获取文件失败')
      }
      // handleClose();
    })
  }
}
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>
src/views/work/financialMng/qualityFinancialAnalysis/index.vue
New file
@@ -0,0 +1,587 @@
<template>
  <div class="app-container">
    <div style="margin-bottom: 10px">
      <el-form style="display: flex;flex-wrap: wrap;">
        <el-form-item>
          <el-button
              type="primary"
              plain
              icon="Plus"
              @click="openDialog('add',{})"
          >新增</el-button>
        </el-form-item>
        <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
          <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable>
            <el-option
                v-for="item in data.companyList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="年份:" style="margin-left: 20px">
          <!--            <el-input v-model="data.queryParams.year" placeholder="请输入年份"></el-input>-->
          <el-select
              v-model="data.queryParams.year"
              placeholder="请选择年份"
              style="width: 240px"
              filterable
              allow-create
              default-first-option
              :reserve-keyword="false"
              @change="handleChangeNum"
          >
            <el-option
                v-for="item in data.yearList"
                :key="item.value"
                :label="item.label"
                :value="item.label"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
          <el-button plain @click="reset">重置</el-button>
        </el-form-item>
        <el-form-item style="margin-left: 15px">
          <el-button
              type="primary"
              @click="exportData"
          >导出</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true"  @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
      <el-table-column label="名称" prop="year" align="center"  >
        <template #default="scope">
          <span>年质量经济性分析报告</span>
        </template>
      </el-table-column>
      <el-table-column label="目标测量方法" prop="method" align="center"  />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160" >
        <template #default="scope">
          <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
          <el-button link type="primary"  @click="openDialog('edit',scope.row)" >编辑</el-button>
          <el-button link type="danger"  @click="handleDelete(scope.row)" >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="pag-container">
      <el-pagination
          v-model:current-page="data.queryParams.pageNum"
          v-model:page-size="data.queryParams.pageSize"
          :page-sizes="[10,15,20,25]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </div>
    <editDialog ref="noticeRef" @getList = "getList"></editDialog>
  </div>
</template>
<script setup>
import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
import editDialog from "./components/editDialog.vue"
import {ElMessage, ElMessageBox} from "element-plus";
import {getCompany} from "@/api/onlineEducation/company";
import Cookies from "js-cookie";
import {generateWordDocument} from "@/utils/exportWord";
import {delObject, getObjectPage} from "@/api/qualityObjectives/object";
import { Document, Paragraph, TextRun, Table, TableRow, TableCell,BorderStyle , Packer, AlignmentType, HeadingLevel } from "docx";
import { saveAs } from "file-saver";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const noticeRef = ref();
const loadingCompany = ref(false)
const choosedData = ref([])
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    companyId: null,
    year: '',
    type: ''
  },
  companyList: [],
  isAdmin: false,
  yearList: [
    {
      value: 1,
      label: '2025'
    },
    {
      value: 2,
      label: '2024'
    },
    {
      value: 3,
      label: '2023'
    },
    {
      value: 4,
      label: '2022'
    },
    {
      value: 5,
      label: '2021'
    },
  ],
  levelList: [
    {
      value: 1,
      label: '公司级'
    },
    {
      value: 2,
      label: '部门级'
    },
  ]
});
const dataList = ref([]);
const total = ref(0);
const { queryParams } = toRefs(data);
onMounted(() => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  console.log("userInfo",userInfo)
  data.isAdmin = userInfo.userType === 0;
  if(data.isAdmin){
    data.queryParams.companyId = null
  }else {
    data.queryParams.companyId = userInfo.companyId
  }
  getList();
  if(data.isAdmin){
    getCompanyList()
  }
});
const getList = async () => {
  // loading.value = true;
  // const res = await getObjectPage(data.queryParams);
  // if(res.code === 200){
  //   dataList.value = res.data.list
  //   total.value = res.data.total
  // }else{
  //   ElMessage.warning(res.message)
  // }
  // loading.value = false;
  dataList.value = [{}]
}
const searchClick = () => {
  getList();
}
const openDialog = (type, value) => {
  noticeRef.value.openDialog(type, value,data.companyList);
}
const selectValue = (val) => {
  data.companyList.forEach(item => {
    if(item.name === val){
      data.queryParams.companyId = item.id
    }
  })
}
const getCompanyList = async ()=>{
  const queryParams = {
    pageNum: 1,
    pageSize: 999
  }
  const res = await getCompany(queryParams)
  if (res.code == 200) {
    data.companyList = res.data.list?res.data.list:[]
    // data.queryParams.companyId = data.companyList[0].id
  } else {
    ElMessage.warning(res.message)
  }
}
const handleSizeChange = (val) => {
  data.queryParams.pageSize = val
  getList()
}
const handleCurrentChange = (val) => {
  data.queryParams.pageNum = val
  getList()
}
/** 重置新增的表单以及其他数据  */
function reset() {
  if(data.isAdmin){
    data.queryParams = {
      companyId: '',
      pageNum: 1,
      pageSize: 10,
      year: '',
      type: ''
    }
    choosedData.value = []
    data.companyList = [];
    getCompanyList()
  }else {
    data.queryParams = {
      companyId: data.queryParams.companyId,
      pageNum: 1,
      pageSize: 10,
      year: '',
      type: ''
    }
  }
  getList();
}
const exportData = () => {
  if(choosedData.value && choosedData.value.length === 0){
    ElMessage.warning('请选择需要导出的数据')
  }else {
    startGeneration()
  }
}
const templatePath = ref('/qualityFinancialAnalysisExample.docx')
const startGeneration = async () => {
  let name = ''
  choosedData.value.forEach(item => {
    // 执行导出
    createQualityEconomicReport(item).catch(console.error);
  })
}
const handleSelectionChange = (val) => {
  choosedData.value = val
}
const handleDelete = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delObject(val.id);
        if(res.code === 200){
          ElMessage({
            type: 'success',
            message: '删除成功'
          });
          getList();
        }else{
          ElMessage.warning(res.message)
        }
      })
}
const handleChangeNum = (value) => {
  if (!/^\d+$/.test(value)) { // 验证是否为数字
    ElMessage.warning('只能输入数字')
    data.queryParams.year = '' // 重置选择,避免非法值被添加到options中
  } else if (!data.yearList.some(option => option.label == value)) { // 确保不是已存在的选项
    data.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
  }
}
function processHtmlTable(htmlTable) {
  const docxRows = [];
  htmlTable.querySelectorAll("tr").forEach(htmlRow => {
    const cells = [];
    let colIndex = 0;
    htmlRow.querySelectorAll("th, td").forEach(htmlCell => {
      // 处理合并单元格
      const colspan = parseInt(htmlCell.getAttribute('colspan')) || 1;
      const rowspan = parseInt(htmlCell.getAttribute('rowspan')) || 1;
      // 处理单元格内容(包括空格的转换)
      const cellText = htmlCell.innerHTML === '&nbsp;' ? ' ' : htmlCell.textContent;
      // 创建Word表格单元格
      cells.push(
          new TableCell({
            children: [
              new Paragraph({
                children: [new TextRun(cellText)],
              })
            ],
            columnSpan: colspan,
            rowSpan: rowspan,
            margins: { top: 100, bottom: 100, left: 100, right: 100 },
            borders: {
              top: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
              bottom: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
              left: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
              right: { style: BorderStyle.SINGLE, size: 4, color: "000000" }
            }
          })
      );
      colIndex += colspan;
    });
    docxRows.push(new TableRow({ children: cells }));
  });
  return docxRows;
}
function convertHtmlToDocx(htmlString) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlString, "text/html");
  const elements = [];
  Array.from(doc.body.childNodes).forEach(node => {
    if (node.nodeType === Node.ELEMENT_NODE) {
      const tagName = node.tagName.toUpperCase();
      if (tagName === 'TABLE') {
        elements.push(new Table({
          rows: processHtmlTable(node),
          width: { size: 100, type: "pct" },  // 宽度100%
          margins: { top: 400, bottom: 400 },
          layout: "fixed",  // 固定布局
          borders: {
            top: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
            bottom: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
            left: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
            right: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
            insideHorizontal: { style: BorderStyle.SINGLE, size: 4, color: "000000" },
            insideVertical: { style: BorderStyle.SINGLE, size: 4, color: "000000" }
          }
        }));
      } else if (tagName === 'P') {
        elements.push(new Paragraph({
          text: node.textContent,
          spacing: { after: 200 }
        }));
      }
    }
  });
  return elements;
}
// 2. 示例HTML表格数据
const sampleTableHTML = `
b
`;
// 3. 创建完整报告文档
async function createQualityEconomicReport(data) {
  data = {
    time: 'xx',
    basicInfo: 'x'
  }
  const doc = new Document({
    sections: [{
      properties: {},
      children: [
        // 报告标题
        new Paragraph({
          children: [
            new TextRun({
              text: "质量经济性分析报告",
              font: "宋体",
              size: 26,
              bold: true,
              color: "000000"
            })
          ],
          heading: HeadingLevel.HEADING_1,
          alignment: AlignmentType.CENTER,
          spacing: { after: 300 }
        }),
        // 报告时间范围
        new Paragraph({
          text: data.time,
          alignment: AlignmentType.CENTER,
          indent: { left: 3700 },
          spacing: { after: 500 }
        }),
        // 1. 基本情况
        new Paragraph({
          children: [
            new TextRun({
              text: "一、基本情况",
              font: "宋体",
              size: 22,
              bold: true,
              color: "000000"
            })
          ],
          heading: HeadingLevel.HEADING_1,
          alignment: AlignmentType.LEFT,
          spacing: { after: 100 }
        }),
        //基本情况内容
        new Paragraph({
          children: [
            new TextRun({
              text: data.basicInfo, // 替换为实际内容
              font: "宋体", // 与标题一致
              size: 20, // 小四号(20 half-points)
              bold: false, // 常规
              color: "000000" // 纯黑
            })
          ],
          alignment: AlignmentType.LEFT,
          spacing: { after: 300 } // 和下一段的间距
        }),
        // 二、综合分析
        new Paragraph({
          children: [
            new TextRun({
              text: "二、综合分析",
              font: "宋体",
              size: 22,
              bold: true,
              color: "000000"
            })
          ],
          heading: HeadingLevel.HEADING_1,
          alignment: AlignmentType.LEFT,
          spacing: { after: 100 }
        }),
        // 二、综合分析内容
        ...convertHtmlToDocx(data.sampleTableHTML),
        new Paragraph({
          children: [
          ],
          heading: HeadingLevel.HEADING_1,
          alignment: AlignmentType.LEFT,
          spacing: { after: 100 }
        }),
        // 三、内外部损失
        new Paragraph({
          children: [
            new TextRun({
              text: "三、内外部损失",
              font: "宋体",
              size: 22,
              bold: true,
              color: "000000"
            })
          ],
          heading: HeadingLevel.HEADING_1,
          alignment: AlignmentType.LEFT,
          spacing: { after: 100 }
        }),
        //内外部损失内容
        new Paragraph({
          children: [
            new TextRun({
              text: data.lose, // 替换为实际内容
              font: "宋体", // 与标题一致
              size: 20, // 小四号(20 half-points)
              bold: false, // 常规
              color: "000000" // 纯黑
            })
          ],
          alignment: AlignmentType.LEFT,
          spacing: { after: 300 } // 和下一段的间距
        }),
        // 四、纠正措施
        new Paragraph({
          children: [
            new TextRun({
              text: "四、纠正措施",
              font: "宋体",
              size: 22,
              bold: true,
              color: "000000"
            })
          ],
          heading: HeadingLevel.HEADING_1,
          alignment: AlignmentType.LEFT,
          spacing: { after: 100 }
        }),
        //纠正措施内容
        new Paragraph({
          children: [
            new TextRun({
              text: data.action, // 替换为实际内容
              font: "宋体", // 与标题一致
              size: 20, // 小四号(20 half-points)
              bold: false, // 常规
              color: "000000" // 纯黑
            })
          ],
          alignment: AlignmentType.LEFT,
          spacing: { after: 300 } // 和下一段的间距
        }),
        // 二、改进建议
        new Paragraph({
          children: [
            new TextRun({
              text: "五、改进建议",
              font: "宋体",
              size: 22,
              bold: true,
              color: "000000"
            })
          ],
          heading: HeadingLevel.HEADING_1,
          alignment: AlignmentType.LEFT,
          spacing: { after: 100 }
        }),
        //改进建议内容
        new Paragraph({
          children: [
            new TextRun({
              text: data.suggest, // 替换为实际内容
              font: "宋体", // 与标题一致
              size: 20, // 小四号(20 half-points)
              bold: false, // 常规
              color: "000000" // 纯黑
            })
          ],
          alignment: AlignmentType.LEFT,
          spacing: { after: 300 } // 和下一段的间距
        }),
        // 10. 综合部落款
        new Paragraph({
          text: data.deptName,
          alignment: AlignmentType.RIGHT,
          spacing: { before: 1200 }
        }),
        // 11. 日期落款
        new Paragraph({
          text: data.lastTime,
          alignment: AlignmentType.RIGHT,
          spacing: { before: 200 }
        })
      ]
    }]
  });
  // 导出文件
  const blob = await Packer.toBlob(doc);
  saveAs(blob, "质量经济性分析报告.docx");
}
</script>
<style lang="scss">
.pag-container{
  float: right;
  margin-top: 10px;
}
</style>
src/views/work/marketingManagement/customerList/need/components/editDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="800px"
        width="1150px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
@@ -42,14 +42,14 @@
              <div style="display: flex;width: 100%;">
                <el-table :data="state.form.customerRecordNeeds" :border="true" >
                  <el-table-column type="index" label="序号"  align="center"></el-table-column>
                  <el-table-column label="顾客名称" prop="customerName" align="center" width="150">
                  <el-table-column label="顾客名称" prop="customerName" align="center" >
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + ']' + 'customerName'" :rules="state.rules.customerName">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="row.customerName" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="顾客需求" prop="customerNeed" align="center" width="150">
                  <el-table-column label="顾客需求" prop="customerNeed" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.expectContentMesses" :key="index">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + '].' +'expectContentMesses.' + '[' + index + ']' + '.customerNeed'" :rules="state.rules.customerNeed">
@@ -71,7 +71,7 @@
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="登记人" prop="registrantId" align="center" width="150">
                  <el-table-column label="登记人" prop="registrantId" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.expectContentMesses" :key="index">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + '].' +'expectContentMesses.' + '[' + index + ']' + '.registrantId'" :rules="state.rules.registrantId">
@@ -87,7 +87,7 @@
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="处理部门" prop="disposeId" align="center" width="150">
                  <el-table-column label="处理部门" prop="disposeId" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.expectContentMesses" :key="index">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + '].' +'expectContentMesses.' + '[' + index + ']' + '.disposeId'" :rules="state.rules.disposeId">
@@ -108,7 +108,7 @@
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="处理结果" prop="disposeMess" align="center" width="150">
                  <el-table-column label="处理结果" prop="disposeMess" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.expectContentMesses" :key="index">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + '].' +'expectContentMesses.' + '[' + index + ']' + '.disposeMess'" :rules="state.rules.disposeMess">
@@ -117,7 +117,7 @@
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="备注" prop="remark" align="center" width="150">
                  <el-table-column label="备注" prop="remark" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.expectContentMesses" :key="index">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + '].' +'expectContentMesses.' + '[' + index + ']' + '.remark'" :rules="state.rules.remark">
src/views/work/procurementPlatform/warehouseManagement/monthlyInspectionRecord/components/editDialog.vue
@@ -3,7 +3,7 @@
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="850px"
        width="1200px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
@@ -42,7 +42,7 @@
              <div style="display: flex;width: 100%;">
                <el-table :data="state.form.inspectionMesses" :border="true" >
                  <el-table-column type="index" label="序号"  align="center"></el-table-column>
                  <el-table-column label="时间" prop="monthlyTime" align="center" width="150">
                  <el-table-column label="时间" prop="monthlyTime" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'monthlyTime'" :rules="state.rules.monthlyTime">
                        <el-date-picker
@@ -56,56 +56,56 @@
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="检查人" prop="checkUser" align="center" width="150">
                  <el-table-column label="检查人" prop="checkUser" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'checkUser'" :rules="state.rules.checkUser">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.checkUser" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="防护" prop="entrench" align="center" width="150">
                  <el-table-column label="防护" prop="entrench" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'entrench'" :rules="state.rules.entrench">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.entrench" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="标识" prop="identification" align="center" width="150">
                  <el-table-column label="标识" prop="identification" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'identification'" :rules="state.rules.identification">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.identification" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="摆放" prop="place" align="center" width="150">
                  <el-table-column label="摆放" prop="place" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'place'" :rules="state.rules.place">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.place" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="清洁" prop="clean" align="center" width="150">
                  <el-table-column label="清洁" prop="clean" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'clean'" :rules="state.rules.clean">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.clean" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="安全" prop="safety" align="center" width="150">
                  <el-table-column label="安全" prop="safety" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'safety'" :rules="state.rules.safety">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.safety" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="环境" prop="environment" align="center" width="150">
                  <el-table-column label="环境" prop="environment" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'environment'" :rules="state.rules.environment">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.environment" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="帐务卡一致性" prop="consistency" align="center" width="150">
                  <el-table-column label="帐务卡一致性" prop="consistency" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'inspectionMesses.' + '[' + $index + ']' + 'consistency'" :rules="state.rules.consistency">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="2" v-model="row.consistency" placeholder="请输入"></el-input>
src/views/work/qualityManage/continuousImprovement/components/editDialog.vue
New file
@@ -0,0 +1,449 @@
<template>
  <div class="notice">
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="900px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules"  label-position="right" label-width="130">
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
              <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom">
                <el-option
                    v-for="item in state.companyList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="年份:" prop="year" >
              <el-select
                  :disabled="title === '查看'"
                  v-model="state.form.year"
                  filterable
                  allow-create
                  default-first-option
                  :reserve-keyword="false"
                  placeholder="请选择年份"
                  @change="handleChangeNum"
                  style="width: 100%"
              >
                <el-option
                    v-for="item in state.yearList"
                    :key="item.value"
                    :label="item.label"
                    :value="item.label"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="年度质量体系改进计划:" prop="customerRecordNeeds" >
              <el-button
                  :disabled="title === '查看'"
                  type="primary"
                  @click="addTableData"
                  style="margin-left: 10px;margin-bottom: 10px"
              >新增</el-button>
              <div style="display: flex;width: 100%;">
                <el-table :data="state.form.customerRecordNeeds" :border="true" >
                  <el-table-column type="index" label="序号"  align="center"></el-table-column>
                  <el-table-column label="改 进 项" prop="customerName" align="center" width="120">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + ']' + 'customerName'" :rules="state.rules.customerName">
                        <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="row.customerName" placeholder="请输入"></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="具体措施" prop="customerNeed" align="center" width="120">
                    <template #default="{row,$index}">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + ']' + 'customerName'" :rules="state.rules.customerNeed">
                          <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="row.customerNeed" placeholder="请输入"></el-input>
                        </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="责任部门" prop="disposeId" align="center" width="120">
                    <template #default="{row,$index}">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + ']' + 'customerName'" :rules="state.rules.disposeId">
                          <el-select
                              :disabled="title === '查看'"
                              v-model="row.disposeId"
                              placeholder="请选择部门"
                              style="width: 240px;margin-bottom: 5px"
                          >
                            <el-option
                                v-for="item in state.deptList"
                                :key="item.deptId"
                                :label="item.deptName"
                                :value="item.deptId"
                            />'customerRecordNeeds.' + '[' + $index + ']' + 'customerName'
                          </el-select>
                        </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="完成时间" prop="disposeMess" align="center" width="120">
                    <template #default="{row,$index}">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + ']' + 'customerName'" :rules="state.rules.disposeMess">
                          <el-date-picker
                              v-model="row.calibrationTime"
                              type="date"
                              value-format="YYYY-MM-DD"
                              placeholder="完成时间"
                              :disabled="state.title =='查看'"
                              style="width: 100%"
                          />
                        </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="跟踪验证" prop="remark" align="center" width="120">
                    <template #default="{row,$index}">
                        <el-form-item :prop="'customerRecordNeeds.' + '[' + $index + ']' + 'customerName'" :rules="state.rules.remark">
                          <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="row.remark" placeholder="请输入"></el-input>
                        </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="操作" align="center"  v-if="title !== '查看'" >
                    <template #default="scope">
<!--                      <el-button link type="primary"  @click="addObject(scope.row,scope.$index)" >添加</el-button>-->
                      <el-button link type="danger"  @click="delObject(scope.row,scope.$index)" >删除</el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="编制:" prop="compilationId" >
              <el-select clearable v-model="state.form.compilationId" :disabled="title =='查看'" filterable  style="width: 200px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="审核:" prop="compilationId" >
              <el-select clearable v-model="state.form.compilationId" :disabled="title =='查看'" filterable  style="width: 200px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="批准:" prop="compilationId" >
              <el-select clearable v-model="state.form.compilationId" :disabled="title =='查看'" filterable  style="width: 200px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer v-if="title !== '查看'">
        <span class="dialog-footer">
            <el-button @click="handleClose" size="default">取 消</el-button>
            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {onMounted, reactive, ref, toRefs} from 'vue'
import Cookies from "js-cookie";
import {getCompany} from "@/api/onlineEducation/company";
import {ElMessage} from "element-plus";
import {getUser} from "@/api/onlineEducation/user";
import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object";
import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table";
import {addNeedDiscren, editNeedDiscren} from "@/api/need/need";
import {addCustomerNeed, editCustomerNeed} from "@/api/customerNeed";
const dialogVisible = ref(false);
const title = ref("");
const busRef = ref();
const length = ref()
const selectPopperClass = "max-width-select";
const emit = defineEmits(["getList"]);
const dataRef = ref();
const state = reactive({
  form: {
    id: '',
    companyId: null,
    recordName: null,
    customerRecordNeeds:[],
  },
  rules: {
    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
    recordName: [{ required: true, message: '请输入记录名称', trigger: 'blur' }],
    customerName: [{required: true, message: "", trigger: "blur"}],
    customerNeed: [{required: true, message: "", trigger: "blur"}],
    needSource: [{required: true, message: "", trigger: "blur"}],
    registrantId: [{required: true, message: "", trigger: "blur"}],
    disposeId: [{required: true, message: "", trigger: "blur"}],
    disposeMess: [{required: true, message: "", trigger: "blur"}],
    customerRecordNeeds:[{ required: true, message: '请填写需求登记列表', trigger: 'blur' }],
  },
  peopleList: [],
  isAdmin: false,
  companyList: [],
  deptList: [],
  yearList: [
    {
      value: 1,
      label: '2025'
    },
    {
      value: 2,
      label: '2024'
    },
    {
      value: 3,
      label: '2023'
    },
    {
      value: 4,
      label: '2022'
    },
    {
      value: 5,
      label: '2021'
    },
  ],
})
onMounted(() => {
});
const openDialog = async (type, value,companyList) => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  state.isAdmin = userInfo.userType === 0;
  state.form.companyName = userInfo.companyName
  state.form.companyId = userInfo.companyId
  if(state.isAdmin){
    state.form.companyId = value.companyId
    state.form.companyName = value.companyName
    state.companyList = companyList
  }
  title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
  if(type === 'edit' || type === 'review') {
    state.form = JSON.parse(JSON.stringify(value));
    if(state.isAdmin){
      state.form.companyId = value.companyId
      state.form.companyName = value.companyName
    }
    state.form.customerRecordNeeds.forEach(item => {
      item.customerName =  item.customerName
      const obj = {
        recordId: state.form.id,
        customerNeed: item.customerNeed,
        disposeId: item.disposeId,
        disposeMess: item.disposeMess,
        needSource: item.needSource?.split(','),
        registrantId: item.registrantId,
        remark: item.remark,
      }
      item.expectContentMesses=[obj]
    })
    console.log('xx',state.form)
  }
  await getDeptList()
  await getPeopleList()
  dialogVisible.value = true;
}
const onSubmit = async () => {
  let dataDemo = JSON.parse(JSON.stringify(state.form))
  let flag = false
  for (const i of dataDemo.customerRecordNeeds) {
    if(!i.expectContentMesses[0].needSource || i.expectContentMesses[0].needSource.length ==0){
      ElMessage.warning('请完善需求来源')
      flag = true
      return
    }
  }
  if(flag) return
  let dataArr = []
  dataArr = dataDemo.customerRecordNeeds.map(item => {
    return {
      customerName: item.customerName,
      customerNeed: item.expectContentMesses[0].customerNeed,
      disposeId: item.expectContentMesses[0].disposeId,
      disposeMess: item.expectContentMesses[0].disposeMess,
      needSource: item.expectContentMesses[0].needSource?.join(','),
      registrantId: item.expectContentMesses[0].registrantId,
      remark: item.expectContentMesses[0].remark,
    }
  })
  dataDemo.customerRecordNeeds = dataArr
  const valid = await busRef.value.validate();
  if(valid){
    if(title.value === '新增'){
      const {id, ...data} = dataDemo
      const res = await addCustomerNeed(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '新增成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }else if(title.value === '编辑'){
      const {...data} = dataDemo
      data.customerRecordNeeds.forEach(i => {
        i.recordId = data.id
      })
      const res = await editCustomerNeed(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '编辑成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }
  }
}
const getDeptList = async () => {
  if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){
    return
  }
  const param = {
    pageNum: 1,
    pageSize: 999,
    companyId: state.form.companyId
  }
  const res = await getDept(param)
  if(res.code === 200){
    state.deptList = res.data
  }
}
const getPeopleList = async ()=> {
  if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){
    return
  }
  const queryParams = {
    pageNum: 1,
    pageSize: 9999,
    companyId: state.form.companyId
  }
  const res = await getUser(queryParams)
  if(res.code == 200){
    state.peopleList = res.data.list?res.data.list:[]
  }else{
    ElMessage.warning(res.message)
  }
};
const handleClose = () => {
  busRef.value.clearValidate();
  reset();
  dialogVisible.value = false;
  emit("getList")
}
const reset = () => {
  state.form = {
    id: '',
    companyId: null,
    recordName: null,
    customerRecordNeeds:[],
  }
  state.companyList = []
}
const selectValueCom = (val) => {
  state.companyList.forEach(item => {
    if(item.name === val){
      state.form.companyId = item.id
    }
  })
  getDeptList()
  getPeopleList()
}
const addTableData = () => {
  state.form.customerRecordNeeds.push({})
}
const addObject = (val,itemIndex) => {
  state.form.customerRecordNeeds.forEach((item,index) => {
    if(index == itemIndex){
      item.expectContentMesses.push({})
    }
  })
}
const delObject = (val,itemIndex) => {
  state.form.customerRecordNeeds = state.form.customerRecordNeeds.filter(item=> item != val)
}
const handleChangeNum = (value) => {
  if (!/^\d+$/.test(value)) { // 验证是否为数字
    ElMessage.warning('只能输入数字')
    state.form.year = '' // 重置选择,避免非法值被添加到options中
  } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项
    state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
  }
}
defineExpose({
  openDialog
});
</script>
<style scoped lang="scss">
.notice{
  :deep(.el-form .el-form-item__label) {
    font-size: 15px;
  }
  .file {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
  }
}
</style>
src/views/work/qualityManage/continuousImprovement/index.vue
New file
@@ -0,0 +1,297 @@
<template>
  <div class="app-container">
    <div style="margin-bottom: 10px">
      <el-form style="display: flex;flex-wrap: wrap;">
        <el-form-item>
          <el-button
              type="primary"
              plain
              icon="Plus"
              @click="openDialog('add',{})"
          >新增</el-button>
        </el-form-item>
        <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
          <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable>
            <el-option
                v-for="item in data.companyList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="年份:" style="margin-left: 20px">
          <el-select
              v-model="data.queryParams.year"
              placeholder="请选择年份"
              style="width: 240px"
              filterable
              allow-create
              default-first-option
              :reserve-keyword="false"
              @change="handleChangeNum"
          >
            <el-option
                v-for="item in data.yearList"
                :key="item.value"
                :label="item.label"
                :value="item.label"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
          <el-button plain @click="reset">重置</el-button>
        </el-form-item>
        <el-form-item style="margin-left: 15px">
          <el-button
              type="primary"
              @click="exportData"
          >导出</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true"  @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
      <el-table-column label="企业名称" prop="companyName" align="center" v-if="data.isAdmin" />
      <el-table-column label="名称"  align="center">
        <template #default="scope">
          <span>{{scope.row.recordName}}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
        <template #default="scope">
          <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
          <el-button link type="primary"  @click="openDialog('edit',scope.row)" >编辑</el-button>
          <el-button link type="danger"  @click="handleDelete(scope.row)" >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="pag-container">
      <el-pagination
          v-model:current-page="data.queryParams.pageNum"
          v-model:page-size="data.queryParams.pageSize"
          :page-sizes="[10,15,20,25]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </div>
    <editDialog ref="noticeRef" @getList = "getList"></editDialog>
  </div>
</template>
<script setup>
import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
import editDialog from "./components/editDialog.vue"
import {ElMessage, ElMessageBox} from "element-plus";
import {getCompany} from "@/api/onlineEducation/company";
import Cookies from "js-cookie";
import {generateWordDocument} from "@/utils/exportWord";
import {delTable, getTable} from "@/api/qualityObjectives/table";
import {delNeedDiscren, getNeedDiscren} from "@/api/need/need";
import {delCustomerNeed, getCustomerNeed} from "@/api/customerNeed";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const noticeRef = ref();
const deptRef = ref()
const loadingCompany = ref(false)
const choosedData = ref([])
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    companyId: null,
  },
  companyList: [],
  isAdmin: false,
  dialogVisible: false,
  yearList: [
    {
      value: 1,
      label: '2025'
    },
    {
      value: 2,
      label: '2024'
    },
    {
      value: 3,
      label: '2023'
    },
    {
      value: 4,
      label: '2022'
    },
    {
      value: 5,
      label: '2021'
    },
  ],
});
const dataList = ref([]);
const total = ref(0);
const { queryParams } = toRefs(data);
onMounted(() => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  console.log("userInfo",userInfo)
  data.isAdmin = userInfo.userType === 0;
  if(data.isAdmin){
    data.queryParams.companyId = null
  }else {
    data.queryParams.companyId = userInfo.companyId
  }
  getList();
  if(data.isAdmin){
    getCompanyList()
  }
});
const getList = async () => {
  // loading.value = true;
  // const res = await getCustomerNeed(data.queryParams);
  // if(res.code === 200){
  //   dataList.value = res.data.list
  //   total.value = res.data.total
  // }else{
  //   ElMessage.warning(res.message)
  // }
  // loading.value = false;
  dataList.value = [{}]
}
const searchClick = () => {
  getList();
}
const openDialog = (type, value) => {
  noticeRef.value.openDialog(type, value,data.companyList);
}
const getCompanyList = async ()=>{
  const queryParams = {
    pageNum: 1,
    pageSize: 999
  }
  const res = await getCompany(queryParams)
  if (res.code == 200) {
    data.companyList = res.data.list?res.data.list:[]
  } else {
    ElMessage.warning(res.message)
  }
}
const handleSizeChange = (val) => {
  data.queryParams.pageSize = val
  getList()
}
const handleCurrentChange = (val) => {
  data.queryParams.pageNum = val
  getList()
}
const handleClose = () => {
  data.dialogVisible = false
}
/** 重置新增的表单以及其他数据  */
function reset() {
  if(data.isAdmin){
    data.queryParams = {
      companyId: '',
      pageNum: 1,
      pageSize: 10,
    }
    choosedData.value = []
    data.companyList = [];
    getCompanyList()
  }else {
    data.queryParams = {
      companyId: data.queryParams.companyId,
      pageNum: 1,
      pageSize: 10,
    }
  }
  getList();
}
const exportData = () => {
  if(choosedData.value && choosedData.value.length === 0){
    ElMessage.warning('请选择需要导出的数据')
  }else {
    startGeneration()
  }
}
const templatePath = ref('/continuousImprovementExample.docx')
const startGeneration = async () => {
  const data = JSON.parse(JSON.stringify(choosedData.value))
  data.forEach(item => {
    // item.tableData = item.customerRecordNeeds.map((i,index) => {
    //   return{
    //     ...i,
    //     expectContentMesses: i.expectContentMesses.map((q,qindex) => {
    //       return{
    //         ...q,
    //         first: qindex == 0,
    //         num: index+1,
    //       }
    //     })
    //   }
    // })
    console.log('xxx',item.tableData)
    try {
      generateWordDocument(templatePath.value, item, item.companyName + `_顾客需求登记表.docx`);
    } catch (error){
      ElMessage({
        type: 'warning',
        message: '导出失败'
      });
    }
  })
}
const handleSelectionChange = (val) => {
  choosedData.value = val
}
const handleDelete = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delCustomerNeed(val.id);
        if(res.code === 200){
          ElMessage({
            type: 'success',
            message: '删除成功'
          });
          await getList();
        }else{
          ElMessage.warning(res.message)
        }
      })
}
const handleChangeNum = (value) => {
  if (!/^\d+$/.test(value)) { // 验证是否为数字
    ElMessage.warning('只能输入数字')
    state.form.year = '' // 重置选择,避免非法值被添加到options中
  } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项
    state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
  }
}
</script>
<style lang="scss">
.pag-container{
  float: right;
  margin-top: 10px;
}
</style>
src/views/work/qualityManage/performanceAppraisal/components/editDialog.vue
New file
@@ -0,0 +1,594 @@
<template>
  <div class="notice">
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="1000px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.rules"  label-position="top" >
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
              <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin" @change="selectValueCom">
                <el-option
                    v-for="item in state.companyList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="绩效评价表名称:" prop="evaluateName" >
              <el-input style="margin-bottom: 15px" :disabled="title === '查看'" placeholder="绩效评价表名称" v-model="state.form.evaluateName"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="表单编号:" prop="number" >
              <el-input style="margin-bottom: 15px" :disabled="title === '查看'" placeholder="表单编号" v-model="state.form.number"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="绩效监测及分析评价表:" prop="types" >
              <el-button
                  :disabled="title === '查看'"
                  type="primary"
                  @click="addContentTable"
                  style="margin-bottom: 10px;display: flex;align-items: flex-end"
              >新增</el-button>
              <div style="display: flex;width: 100%;">
                <el-table :data="state.form.types" :border="true" >
                  <el-table-column type="index" label="序号"  align="center"></el-table-column>
                  <el-table-column label="内部/外部" prop="type" align="center" width="100">
                    <template  #default="{row,$index}">
                      <el-form-item :prop="'types.' + '[' + $index + ']' + 'type'" :rules="state.rules.type">
                        <el-select v-model="row.type" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看'">
                          <el-option
                              v-for="item in state.inOrOutList"
                              :key="item.id"
                              :label="item.name"
                              :value="item.id">
                          </el-option>
                        </el-select>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="需交流的事项和内容" prop="content" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.analyses" :key="index">
                        <el-form-item :prop="'types.' + '[' + $index + '].' +'analyses.' + '[' + index + ']' + '.content'" :rules="state.rules.content">
                          <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="i.content" placeholder="请输入"></el-input>
                        </el-form-item>
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="交流和监测目的" prop="purpose" align="center" width="140">
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.analyses" :key="index">
                        <el-form-item :prop="'types.' + '[' + $index + '].' +'analyses.' + '[' + index + ']' + '.purpose'" :rules="state.rules.purpose">
                          <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="i.purpose" placeholder="请输入"></el-input>
                        </el-form-item>
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="交流监测时机" prop="opportunity" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.analyses" :key="index">
                        <el-form-item :prop="'types.' + '[' + $index + '].' +'analyses.' + '[' + index + ']' + '.opportunity'" :rules="state.rules.opportunity">
                          <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="i.opportunity" placeholder="请输入"></el-input>
                        </el-form-item>
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="交流监测范围/对象" prop="scope" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.analyses" :key="index">
                        <el-form-item :prop="'types.' + '[' + $index + '].' +'analyses.' + '[' + index + ']' + '.scope'" :rules="state.rules.scope">
                          <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="i.scope" placeholder="请输入"></el-input>
                        </el-form-item>
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="交流方式及取得绩效" prop="score" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.analyses" :key="index">
                        <el-form-item :prop="'types.' + '[' + $index + '].' +'analyses.' + '[' + index + ']' + '.score'" :rules="state.rules.score">
                          <el-input style="margin-top: 10px" :disabled="title === '查看'" type="textarea" :rows="4" v-model="i.score" placeholder="请输入"></el-input>
                        </el-form-item>
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="责任部门" prop="deptId" align="center" >
                    <template #default="{row,$index}">
                      <div v-for="(i,index) in row.analyses" :key="index">
                        <el-form-item :prop="'types.' + '[' + $index + '].' +'analyses.' + '[' + index + ']' + '.deptId'">
                          <el-select
                              clearable
                              :disabled="title === '查看'"
                              v-model="i.deptId"
                              placeholder="请选择部门"
                              style="width: 240px;margin-bottom: 5px"
                          >
                            <el-option
                                v-for="item in state.deptList"
                                :key="item.deptId"
                                :label="item.deptName"
                                :value="item.deptId"
                            />
                          </el-select>
                        </el-form-item>
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column label="操作" align="center"  v-if="title !== '查看'" >
                    <template #default="scope">
                      <el-button link type="primary"  @click="addObject(scope.row,scope.$index)" >添加</el-button>
                      <el-button link type="danger"  @click="delContent(scope.row,scope.$index)" >删除</el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="内容:" prop="content" >
              <el-input style="margin-bottom: 15px" :disabled="title === '查看'" type="textarea" :rows="10" placeholder="内容" v-model="state.form.content"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="编制:" prop="fictionId" >
              <el-select clearable v-model="state.form.fictionId" :disabled="title =='查看'" filterable  style="width: 240px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="fictionTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.fictionTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="审批:" prop="checkId" >
              <el-select clearable v-model="state.form.checkId" :disabled="title =='查看'" filterable  style="width: 240px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="checkTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.checkTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer v-if="title !== '查看'">
        <span class="dialog-footer">
            <el-button @click="handleClose" size="default">取 消</el-button>
            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {onMounted, reactive, ref, toRefs} from 'vue'
import Cookies from "js-cookie";
import {getCompany} from "@/api/onlineEducation/company";
import {ElMessage} from "element-plus";
import {getUser} from "@/api/onlineEducation/user";
import {getDept, getObject, getObjectPage} from "@/api/qualityObjectives/object";
import {addTable, editTable, getTargetById} from "@/api/qualityObjectives/table";
import {addNeedEvaluate, editNeedEvaluate, getNeedEvaluateAll} from "@/api/need/need";
import {addEvaluation, editEvaluation} from "@/api/performanceAppraisal";
const dialogVisible = ref(false);
const title = ref("");
const busRef = ref();
const length = ref()
const selectPopperClass = "max-width-select";
const emit = defineEmits(["getList"]);
const dataRef = ref();
const state = reactive({
  form: {
    id: '',
    companyId: null,
    evaluateName: "",
    number: "",
    fictionId: null,
    fictionTime: "",
    checkId: null,
    checkTime: "",
    content:
        '一、主要问题:\n' +
        '1、按GJB9001C-2017标准建立体系\t\n' +
        '2、提高人员质量意识\n' +
        '3、减少不合格品\n' +
        '4、提高维修人员能力\n' +
        '\n' +
        '二、主要绩效:\n' +
        '1、2023年内取得军标证书\n' +
        '2、提高人员质量意识,保证工作质量\n' +
        '3、通过质量管理,不断减少不合格品,减少内外部故障\n' +
        '4、通过技能培训,提高维修人员能力\n' +
        '\n' +
        '三、改进项目:\n' +
        '1、邀请资深老师对GJB9001C-2017标准进行培训,并建立、运行质量管理体系;\n' +
        '2、质量意识是体现在基层每一个员工身上,但更集中在组织的管理层的工作岗位中。 质量意识是自上而下的,上行下效才能齐头并进;因此要不断培训,告诉员工应该怎么做,更应该告诉自己应该如何做,以身做责来提高质量意识。\n' +
        '3、不合格品是生产的产品中不符合质量标准的产品,它包括废品、返修品和超差利用品三类产品。 加强不合格品管理,一方面能降低生产成本,提高企业的经济效益;另一方面,对保证产品质量,生产用户满意的产品。\n' +
        '4、通过技能培训不断提高员工技能,并提高职工对自身价值的认识,对工作目标有了更好的理解,为公司创造更大价值。\n',
    types:[
      {
        type: 2,
        analyses: [
          {
            content: "按GJB9001C-2017标准建立体系",
            purpose: "2023年内取得军标证书",
            opportunity: "取得证书后",
            scope: "顾客及用船部队",
            score: "面谈、走访,获得认可",
            deptId: null
          }
        ]
      },
      {
        type: 1,
        analyses: [
          {
            content: "不断提高人员质量意识",
            purpose: "提高人员质量意识,保证工作质量",
            opportunity: "每季度",
            scope: "全体员工",
            score: "培训",
            deptId: null
          },
          {
            content: "加强管理,减少不合格品",
            purpose: "通过质量管理,不断减少不合格品,减少内外部故障",
            opportunity: "每季度",
            scope: "生产操作岗",
            score: "培训、实操",
            deptId: null
          },
          {
            content: "提高维修人员能力",
            purpose: "通过技能培训,提高维修人员能力",
            opportunity: "每半年",
            scope: "生产操作岗",
            score: "培训、实操",
            deptId: null
          },
        ]
      },
    ]
  },
  rules: {
    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
    evaluateName: [{ required: true, message: '请输入绩效评价表名称', trigger: 'blur' }],
    number: [{ required: true, message: '请输入编号', trigger: 'blur' }],
    content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
    fictionId: [{ required: true, message: '请选择编制人', trigger: 'blur' }],
    fictionTime: [{ required: true, message: '请选择编制日期', trigger: 'blur' }],
    checkId: [{ required: true, message: '请选择审核人', trigger: 'blur' }],
    checkTime: [{ required: true, message: '请选择审核人日期', trigger: 'blur' }],
    types: [{ required: true, message: '请填写绩效评价表', trigger: 'blur' }],
    purpose: [{ required: true, message: '', trigger: 'blur' }],
    opportunity: [{ required: true, message: '', trigger: 'blur' }],
    scope: [{ required: true, message: '', trigger: 'blur' }],
    score: [{ required: true, message: '', trigger: 'blur' }],
  },
  peopleList: [],
  isAdmin: false,
  companyList: [],
  needList: [],
  inOrOutList: [
    {
      id: 1,
      name: '内部'
    },
    {
      id: 2,
      name: '外部'
    },
  ]
})
onMounted(() => {
});
const openDialog = async (type, value,companyList) => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  state.isAdmin = userInfo.userType === 0;
  state.form.companyName = userInfo.companyName
  state.form.companyId = userInfo.companyId
  if(state.isAdmin){
    state.form.companyId = value.companyId
    state.form.companyName = value.companyName
    state.companyList = companyList
  }
  title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
  if(type === 'edit' || type === 'review') {
    state.form = JSON.parse(JSON.stringify(value));
    state.form.confirmId = Number(state.form.confirmId)
    if(state.isAdmin){
      state.form.companyId = value.companyId
      state.form.companyName = value.companyName
    }
  }
  await getDeptList()
  await getPeopleList()
  dialogVisible.value = true;
}
const getDeptList = async () => {
  if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){
    return
  }
  const param = {
    pageNum: 1,
    pageSize: 999,
    companyId: state.form.companyId
  }
  const res = await getDept(param)
  if(res.code === 200){
    state.deptList = res.data
  }
}
const onSubmit = async () => {
  const valid = await busRef.value.validate();
  if(valid){
    if(title.value === '新增'){
      console.log('sta',state.form)
      const {id, ...data} = JSON.parse(JSON.stringify(state.form))
      const res = await addEvaluation(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '新增成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }else if(title.value === '编辑'){
      const {...data} = JSON.parse(JSON.stringify(state.form))
      const res = await editEvaluation(data)
      data.types.forEach(item => {
        item.evaluationId = state.form.id
      })
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '编辑成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }
  }
}
const handleClose = () => {
  busRef.value.clearValidate();
  reset();
  dialogVisible.value = false;
  emit("getList")
}
const reset = () => {
  state.form = {
    id: '',
    companyId: null,
    evaluateName: "",
    number: "",
    fictionId: null,
    fictionTime: "",
    checkId: null,
    checkTime: "",
    content:
        '一、主要问题:\n' +
        '1、按GJB9001C-2017标准建立体系\t\n' +
        '2、提高人员质量意识\n' +
        '3、减少不合格品\n' +
        '4、提高维修人员能力\n' +
        '\n' +
        '二、主要绩效:\n' +
        '1、2023年内取得军标证书\n' +
        '2、提高人员质量意识,保证工作质量\n' +
        '3、通过质量管理,不断减少不合格品,减少内外部故障\n' +
        '4、通过技能培训,提高维修人员能力\n' +
        '\n' +
        '三、改进项目:\n' +
        '1、邀请资深老师对GJB9001C-2017标准进行培训,并建立、运行质量管理体系;\n' +
        '2、质量意识是体现在基层每一个员工身上,但更集中在组织的管理层的工作岗位中。 质量意识是自上而下的,上行下效才能齐头并进;因此要不断培训,告诉员工应该怎么做,更应该告诉自己应该如何做,以身做责来提高质量意识。\n' +
        '3、不合格品是生产的产品中不符合质量标准的产品,它包括废品、返修品和超差利用品三类产品。 加强不合格品管理,一方面能降低生产成本,提高企业的经济效益;另一方面,对保证产品质量,生产用户满意的产品。\n' +
        '4、通过技能培训不断提高员工技能,并提高职工对自身价值的认识,对工作目标有了更好的理解,为公司创造更大价值。\n',
    types:[
      {
        type: 2,
        analyses: [
          {
            content: "按GJB9001C-2017标准建立体系",
            purpose: "2023年内取得军标证书",
            opportunity: "取得证书后",
            scope: "顾客及用船部队",
            score: "面谈、走访,获得认可",
            deptId: null
          }
        ]
      },
      {
        type: 1,
        analyses: [
          {
            content: "不断提高人员质量意识",
            purpose: "提高人员质量意识,保证工作质量",
            opportunity: "每季度",
            scope: "全体员工",
            score: "培训",
            deptId: null
          },
          {
            content: "加强管理,减少不合格品",
            purpose: "通过质量管理,不断减少不合格品,减少内外部故障",
            opportunity: "每季度",
            scope: "生产操作岗",
            score: "培训、实操",
            deptId: null
          },
          {
            content: "提高维修人员能力",
            purpose: "通过技能培训,提高维修人员能力",
            opportunity: "每半年",
            scope: "生产操作岗",
            score: "培训、实操",
            deptId: null
          },
        ]
      },
    ]
  }
  state.peopleList = []
  state.companyList = []
  state.needList = []
}
const getPeopleList = async ()=> {
  if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){
    return
  }
  const queryParams = {
    pageNum: 1,
    pageSize: 9999,
    companyId: state.form.companyId
  }
  const res = await getUser(queryParams)
  if(res.code == 200){
    state.peopleList = res.data.list?res.data.list:[]
  }else{
    ElMessage.warning(res.message)
  }
};
const changeDiscren = (val) => {
  state.needList.forEach(item => {
    if(item.id == val){
      state.form.expectContents = item.expectContents
    }
  })
}
const addContentTable = () => {
  state.form.types.push({analyses: [{}]})
}
const addObject = (val,itemIndex) => {
  state.form.types.forEach((item,index) => {
    if(index == itemIndex){
      item.analyses.push({})
    }
  })
}
const delContent = (val,itemIndex) => {
  state.form.types.forEach((item,index) => {
    if(index == itemIndex){
      if(item.analyses.length == 1){
        state.form.types.splice(index,1)
      }else {
        item.analyses.pop()
      }
    }
  })
}
const selectValueCom = (val) => {
  state.form.fictionId = null
  state.form.checkId = null
  state.form.types.forEach(item => {
    item.analyses.forEach(i =>{
      i.deptId = null
    })
  })
  state.companyList.forEach(item => {
    if(item.name === val){
      state.form.companyId = item.id
    }
  })
  getDeptList()
  getPeopleList()
}
const addTableData = () => {
    state.form.outEnvironment.push({})
}
const delTable = (val) => {
  state.form.outEnvironment = state.form.outEnvironment.filter(item=> item != val)
}
defineExpose({
  openDialog
});
</script>
<style scoped lang="scss">
.notice{
  :deep(.el-form .el-form-item__label) {
    font-size: 15px;
  }
  .file {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
  }
}
</style>
src/views/work/qualityManage/performanceAppraisal/index.vue
New file
@@ -0,0 +1,281 @@
<template>
  <div class="app-container">
    <div style="margin-bottom: 10px">
      <el-form style="display: flex;flex-wrap: wrap;">
        <el-form-item>
          <el-button
              type="primary"
              plain
              icon="Plus"
              @click="openDialog('add',{})"
          >新增</el-button>
        </el-form-item>
        <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
          <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable>
            <el-option
                v-for="item in data.companyList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item  v-if="data.isAdmin">
          <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
          <el-button plain @click="reset">重置</el-button>
        </el-form-item>
        <el-form-item style="margin-left: 15px">
          <el-button
              type="primary"
              @click="exportData"
          >导出</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true"  @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
      <el-table-column label="企业名称" prop="companyName" align="center" width="250"  v-if="data.isAdmin" />
      <el-table-column label="绩效评价表"  prop="evaluateName" align="center"></el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
        <template #default="scope">
          <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
          <el-button link type="primary"  @click="openDialog('edit',scope.row)" >编辑</el-button>
          <el-button link type="danger"  @click="handleDelete(scope.row)" >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="pag-container">
      <el-pagination
          v-model:current-page="data.queryParams.pageNum"
          v-model:page-size="data.queryParams.pageSize"
          :page-sizes="[10,15,20,25]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </div>
    <editDialog ref="noticeRef" @getList = "getList"></editDialog>
  </div>
</template>
<script setup>
import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
import editDialog from "./components/editDialog.vue"
import {ElMessage, ElMessageBox} from "element-plus";
import {getCompany} from "@/api/onlineEducation/company";
import Cookies from "js-cookie";
import {generateWordDocument} from "@/utils/exportWord";
import {delTable, getTable} from "@/api/qualityObjectives/table";
import {delNeedEvaluate, getNeedEvaluate} from "@/api/need/need";
import {delEvaluation, getEvaluation} from "@/api/performanceAppraisal";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const noticeRef = ref();
const deptRef = ref()
const loadingCompany = ref(false)
const choosedData = ref([])
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    companyId: null,
    year: '',
    type: ''
  },
  companyList: [],
  isAdmin: false,
  dialogVisible: false,
});
const dataList = ref([]);
const total = ref(0);
const { queryParams } = toRefs(data);
onMounted(() => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  console.log("userInfo",userInfo)
  data.isAdmin = userInfo.userType === 0;
  if(data.isAdmin){
    data.queryParams.companyId = null
  }else {
    data.queryParams.companyId = userInfo.companyId
  }
  getList();
  if(data.isAdmin){
    getCompanyList()
  }
});
const getList = async () => {
  loading.value = true;
  const res = await getEvaluation(data.queryParams);
  if(res.code === 200){
    dataList.value = res.data.list.map(item => {
      return {
        ...item,
        types: item.types.map(i => {
          return {
            ...i,
            analyses: i.analyses.map(x => {
              return {
                ...x,
                deptId: x.deptId ? x.deptId : null
              }
            })
          }
        })
      }
    })
    total.value = res.data.total
  }else{
    ElMessage.warning(res.message)
  }
  loading.value = false;
}
const searchClick = () => {
  getList();
}
const openDialog = (type, value) => {
  noticeRef.value.openDialog(type, value,data.companyList);
}
const selectValue = (val) => {
  data.companyList.forEach(item => {
    if(item.name === val){
      data.queryParams.companyId = item.id
    }
  })
}
const getCompanyList = async ()=>{
  const queryParams = {
    pageNum: 1,
    pageSize: 999
  }
  const res = await getCompany(queryParams)
  if (res.code == 200) {
    data.companyList = res.data.list?res.data.list:[]
  } else {
    ElMessage.warning(res.message)
  }
}
const handleSizeChange = (val) => {
  data.queryParams.pageSize = val
  getList()
}
const handleCurrentChange = (val) => {
  data.queryParams.pageNum = val
  getList()
}
const handleClose = () => {
  data.dialogVisible = false
}
/** 重置新增的表单以及其他数据  */
function reset() {
  if(data.isAdmin){
    data.queryParams = {
      companyId: '',
      pageNum: 1,
      pageSize: 10,
      year: '',
      type: ''
    }
    choosedData.value = []
    data.companyList = [];
    getCompanyList()
  }else {
    data.queryParams = {
      companyId: data.queryParams.companyId,
      pageNum: 1,
      pageSize: 10,
      year: '',
      type: ''
    }
  }
  getList();
}
const exportData = () => {
  if(choosedData.value && choosedData.value.length === 0){
    ElMessage.warning('请选择需要导出的数据')
  }else {
    startGeneration()
  }
}
const templatePath = ref('/performanceAppraisalExample.docx')
const startGeneration = async () => {
  const data = JSON.parse(JSON.stringify(choosedData.value))
  data.forEach(item => {
    item.tableList = item.types.map((i,index) => {
      return{
        ...i,
        analyses: i.analyses.map((q,qindex) => {
          return{
            ...q,
            typeName: i.type == 1? '内部':'外部',
            first: qindex == 0,
          }
        })
      }
    })
    try {
      generateWordDocument(templatePath.value, item, item.companyName +`_${item.evaluateName}.docx`);
    } catch (error){
      ElMessage({
        type: 'warning',
        message: '导出失败'
      });
    }
  })
}
function idGroupToTree(data) {
  const groups = data.reduce((map, item) => {
    map.has(item.type) || map.set(item.type, []);
    map.get(item.type).push(item);
    return map;
  }, new Map());
  return Array.from(groups).map(([type, items]) => ({
    type,
    children: items
  }));
}
const handleSelectionChange = (val) => {
  choosedData.value = val
}
const handleDelete = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delEvaluation(val.id);
        if(res.code === 200){
          ElMessage({
            type: 'success',
            message: '删除成功'
          });
          await getList();
        }else{
          ElMessage.warning(res.message)
        }
      })
}
</script>
<style lang="scss">
.pag-container{
  float: right;
  margin-top: 10px;
}
</style>
src/views/work/qualityManage/qualityInformationPage/external/components/editDialog.vue
New file
@@ -0,0 +1,364 @@
<template>
  <div class="notice">
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="850px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules"  >
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
              <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin">
                <el-option
                    v-for="item in state.companyList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="反馈单名称:" prop="feedFrom" >
              <el-input  :disabled="title === '查看'" v-model="state.form.feedFrom" placeholder="反馈单名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="编号:" prop="number" >
              <el-input  :disabled="title === '查看'" v-model="state.form.number" placeholder="编号"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="产品名称:" prop="productName" >
              <el-input  :disabled="title === '查看'" v-model="state.form.productName" placeholder="产品名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="制造号:" prop="makeNum" >
              <el-input  :disabled="title === '查看'" v-model="state.form.makeNum" placeholder="制造号"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="8">
            <el-form-item label="提供单位:" prop="offerUnit" >
              <el-input  :disabled="title === '查看'" v-model="state.form.offerUnit" placeholder="提供单位"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="型号:" prop="model" >
              <el-input  :disabled="title === '查看'" v-model="state.form.model" placeholder="型号"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="提供方式:" prop="offerMethod" >
                <el-checkbox-group v-model="state.form.offerMethod" style="display: flex" :disabled="title === '查看'">
                  <el-checkbox label="1" value="1" style="width: 25px;" >信函</el-checkbox>
                  <el-checkbox label="2" value="2" style="width: 25px;">电话</el-checkbox>
                  <el-checkbox label="3" value="3" style="width: 20px;">走访</el-checkbox>
                </el-checkbox-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="提供日期:" prop="offerTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.offerTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="公司编号:" prop="comNum" >
              <el-input  :disabled="title === '查看'" v-model="state.form.comNum" placeholder="公司编号"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="反馈质量问题概述:" prop="feedInformation" >
              <el-input  :disabled="title === '查看'" type="textarea" :rows="4" v-model="state.form.feedInformation" placeholder=""></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="责任单位拟办意见:" prop="dutyMess" >
              <el-input  :disabled="title === '查看'" type="textarea" :rows="4" v-model="state.form.dutyMess" placeholder=""></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="综合办公室签名:" prop="generalSign" >
              <el-input  :disabled="title === '查看'"  v-model="state.form.generalSign" placeholder="综合办公室签名"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="generalTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.generalTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="计划处意见:" prop="planMess" >
              <el-input  :disabled="title === '查看'" type="textarea" :rows="4" v-model="state.form.planMess" placeholder=""></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="生产技术部签名:" prop="productSign" >
              <el-input  :disabled="title === '查看'"  v-model="state.form.productSign" placeholder="生产技术部签名"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="productTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.productTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="处置结果:" prop="disposeMess" >
              <el-input  :disabled="title === '查看'" type="textarea" :rows="4" v-model="state.form.disposeMess" placeholder=""></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="处置人签名:" prop="disposeSign" >
              <el-input  :disabled="title === '查看'"  v-model="state.form.disposeSign" placeholder="处置人签名"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="disposeTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.disposeTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer v-if="title !== '查看'">
        <span class="dialog-footer">
            <el-button @click="handleClose" size="default">取 消</el-button>
            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {reactive, ref, toRefs} from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import {verifyPhone} from "@/utils/validate";
import Cookies from "js-cookie";
import {addCustomer, editCustomer} from "@/api/customerList";
import {getDept} from "@/api/qualityObjectives/object";
import {getUser} from "@/api/onlineEducation/user";
import {addEnternal, editEnternal} from "@/api/external";
const dialogVisible = ref(false);
const title = ref("");
const busRef = ref();
const length = ref()
const emit = defineEmits(["getList"]);
const state = reactive({
  form: {
    id: '',
    feedFrom: "",
    number: "",
    productName: "",
    makeNum: "",
    offerUnit: "",
    offerTime: "",
    offerMethod:[],
    model: "",
    comNum: "",
    feedInformation: "",
    dutyMess: "",
    generalSign: "",
    generalTime: "",
    planMess: "",
    productSign: "",
    productTime: "",
    disposeMess: "",
    disposeSign: "",
    disposeTime: ""
  },
  formRules:{
    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
    feedFrom: [{ required: true, message: '请输入反馈单名称', trigger: 'blur' }],
    number: [{ required: true, message: '请输入编号', trigger: 'blur' }],
    productName: [{ required: true, message: '请输入产品名称', trigger: 'blur' }],
    makeNum: [{ required: true, message: '请输入制造号', trigger: 'blur' }],
    offerUnit: [{ required: true, message: '请输入提供单位', trigger: 'blur' }],
    offerTime: [{ required: true, message: '请输入提供日期', trigger: 'blur' }],
    offerMethod: [{ required: true, message: '请输入提供方式', trigger: 'blur' }],
    model: [{ required: true, message: '请输入型号', trigger: 'blur' }],
    comNum: [{ required: true, message: '请输入公司编号', trigger: 'blur' }],
    feedInformation: [{ required: true, message: '请输入反馈信息描述', trigger: 'blur' }],
    dutyMess: [{ required: true, message: '请输入责任单位意见', trigger: 'blur' }],
    generalSign: [{ required: true, message: '请输入综合办公室签名', trigger: 'blur' }],
    generalTime: [{ required: true, message: '请选择签名日期', trigger: 'blur' }],
    planMess: [{ required: true, message: '请输入计划意见', trigger: 'blur' }],
    productSign: [{ required: true, message: '请输入生产技术部签名', trigger: 'blur' }],
    productTime: [{ required: true, message: '请选择生产技术部签名日期', trigger: 'blur' }],
    disposeMess:[{ required: true, message: '请输入处置结果', trigger: 'blur' }],
    disposeSign: [{ required: true, message: '请输入处置人签名', trigger: 'blur' }],
    disposeTime: [{ required: true, message: '请选择处置人签名日期', trigger: 'blur' }]
  },
  companyList: [],
  isAdmin: false,
  deptList: [],
  peopleList: [],
})
const openDialog = async (type, value,companyList) => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  state.isAdmin = userInfo.userType === 0;
  state.form.companyName = userInfo.companyName
  state.form.companyId = userInfo.companyId
  if(state.isAdmin){
    state.form.companyId = value.companyId
    state.form.companyName = value.companyName
    state.companyList = companyList
  }
  title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
  if(type === 'edit' || type === 'review') {
    state.form = JSON.parse(JSON.stringify(value));
    state.form.offerMethod = state.form.offerMethod.split(',')
    if(state.isAdmin){
      state.form.companyId = value.companyId
      state.form.companyName = value.companyName
    }
  }
  dialogVisible.value = true;
}
const onSubmit = async () => {
  const valid = await busRef.value.validate();
  if(!state.isAdmin){
    const userInfo = JSON.parse(Cookies.get('userInfo'))
    state.form.companyId = userInfo.companyId
  }
  if(valid){
    state.form.offerMethod = state.form.offerMethod.join(',')
    if(title.value === '新增'){
      const {id, ...data} = JSON.parse(JSON.stringify(state.form))
      const res = await addEnternal(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '新增成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }else if(title.value === '编辑'){
      const {...data} = JSON.parse(JSON.stringify(state.form))
      const res = await editEnternal(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '编辑成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }
  }
}
const handleClose = () => {
  busRef.value.clearValidate();
  reset();
  dialogVisible.value = false;
  emit("getList")
}
const reset = () => {
  state.form = {
    id: '',
    feedFrom: "",
    number: "",
    productName: "",
    makeNum: "",
    offerUnit: "",
    offerTime: "",
    offerMethod: [],
    model: "",
    comNum: "",
    feedInformation: "",
    dutyMess: "",
    generalSign: "",
    generalTime: "",
    planMess: "",
    productSign: "",
    productTime: "",
    disposeMess: "",
    disposeSign: "",
    disposeTime: ""
  }
  state.companyList = []
}
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>
src/views/work/qualityManage/qualityInformationPage/external/index.vue
New file
@@ -0,0 +1,235 @@
<template>
  <div class="app-container">
    <div style="margin-bottom: 10px">
      <el-form style="display: flex;flex-wrap: wrap;">
        <el-form-item>
          <el-button
              type="primary"
              plain
              icon="Plus"
              @click="openDialog('add',{})"
          >新增</el-button>
        </el-form-item>
        <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
          <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable>
            <el-option
                v-for="item in data.companyList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item v-if="data.isAdmin">
          <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
          <el-button plain @click="reset">重置</el-button>
        </el-form-item>
        <el-form-item style="margin-left: 15px">
          <el-button
              type="primary"
              @click="exportData"
          >导出</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true"  @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
      <el-table-column label="企业名称" prop="companyName" align="center" v-if="data.isAdmin" />
      <el-table-column label="反馈单名称"  align="center">
        <template #default="scope">
          <span>{{scope.row.feedFrom}}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
        <template #default="scope">
          <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
          <el-button link type="primary"  @click="openDialog('edit',scope.row)" >编辑</el-button>
          <el-button link type="danger"  @click="handleDelete(scope.row)" >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="pag-container">
      <el-pagination
          v-model:current-page="data.queryParams.pageNum"
          v-model:page-size="data.queryParams.pageSize"
          :page-sizes="[10,15,20,25]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </div>
    <editDialog ref="noticeRef" @getList = "getList"></editDialog>
  </div>
</template>
<script setup>
import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
import editDialog from "./components/editDialog.vue"
import {ElMessage, ElMessageBox} from "element-plus";
import {getCompany} from "@/api/onlineEducation/company";
import Cookies from "js-cookie";
import {generateWordDocument} from "@/utils/exportWord";
import {delEnternal, getEnternal} from "@/api/external";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const noticeRef = ref();
const deptRef = ref()
const loadingCompany = ref(false)
const choosedData = ref([])
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    companyId: null,
  },
  companyList: [],
  isAdmin: false,
  dialogVisible: false,
});
const dataList = ref([]);
const total = ref(0);
const { queryParams } = toRefs(data);
onMounted(() => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  console.log("userInfo",userInfo)
  data.isAdmin = userInfo.userType === 0;
  if(data.isAdmin){
    data.queryParams.companyId = null
  }else {
    data.queryParams.companyId = userInfo.companyId
  }
  getList();
  if(data.isAdmin){
    getCompanyList()
  }
});
const getList = async () => {
  loading.value = true;
  const res = await getEnternal(data.queryParams);
  if(res.code === 200){
    dataList.value = res.data.list
    total.value = res.data.total
  }else{
    ElMessage.warning(res.message)
  }
  loading.value = false;
}
const searchClick = () => {
  getList();
}
const openDialog = (type, value) => {
  noticeRef.value.openDialog(type, value,data.companyList);
}
const getCompanyList = async ()=>{
  const queryParams = {
    pageNum: 1,
    pageSize: 999
  }
  const res = await getCompany(queryParams)
  if (res.code == 200) {
    data.companyList = res.data.list?res.data.list:[]
  } else {
    ElMessage.warning(res.message)
  }
}
const handleSizeChange = (val) => {
  data.queryParams.pageSize = val
  getList()
}
const handleCurrentChange = (val) => {
  data.queryParams.pageNum = val
  getList()
}
const handleClose = () => {
  data.dialogVisible = false
}
/** 重置新增的表单以及其他数据  */
function reset() {
  if(data.isAdmin){
    data.queryParams = {
      companyId: '',
      pageNum: 1,
      pageSize: 10,
    }
    choosedData.value = []
    data.companyList = [];
    getCompanyList()
  }else {
    data.queryParams = {
      companyId: data.queryParams.companyId,
      pageNum: 1,
      pageSize: 10,
    }
  }
  getList();
}
const exportData = () => {
  if(choosedData.value && choosedData.value.length === 0){
    ElMessage.warning('请选择需要导出的数据')
  }else {
    startGeneration()
  }
}
const templatePath = ref('/externalExample.docx')
const startGeneration = async () => {
  const data = JSON.parse(JSON.stringify(choosedData.value))
  data.forEach(item => {
    try {
      item.isLetter = item.offerMethod?.split(',').includes('1')
      item.isPhone = item.offerMethod?.split(',').includes('2')
      item.isVisit = item.offerMethod?.split(',').includes('3')
      generateWordDocument(templatePath.value, item, item.companyName + `_质量信息反馈单(公司外).docx`);
    } catch (error){
      ElMessage({
        type: 'warning',
        message: '导出失败'
      });
    }
  })
}
const handleSelectionChange = (val) => {
  choosedData.value = val
}
const handleDelete = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delEnternal(val.id);
        if(res.code === 200){
          ElMessage({
            type: 'success',
            message: '删除成功'
          });
          await getList();
        }else{
          ElMessage.warning(res.message)
        }
      })
}
</script>
<style lang="scss">
.pag-container{
  float: right;
  margin-top: 10px;
}
</style>
src/views/work/qualityManage/qualityInformationPage/internal/components/editDialog.vue
New file
@@ -0,0 +1,541 @@
<template>
  <div class="notice">
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="850px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules"  >
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
              <el-select v-model="state.form.companyId" placeholder="请选择" filterable clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin"  @change="selectValueCom" >
                <el-option
                    v-for="item in state.companyList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="反馈单名称:" prop="feedForm" >
              <el-input  :disabled="title === '查看'" v-model="state.form.feedForm" placeholder="反馈单名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="编号:" prop="number" >
              <el-input  :disabled="title === '查看'" v-model="state.form.number" placeholder="编号"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="8">
            <el-form-item label="产品名称:" prop="productName" >
              <el-input  :disabled="title === '查看'" v-model="state.form.productName" placeholder="产品名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="产品型号:" prop="productModel" >
              <el-input  :disabled="title === '查看'" v-model="state.form.productModel" placeholder="产品型号"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="产品公司编号:" prop="productNumber" >
              <el-input  :disabled="title === '查看'" v-model="state.form.productNumber" placeholder="产品公司编号"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="责任单位:" prop="dutyUnitId" >
              <el-select
                  :disabled="title === '查看'"
                  v-model="state.form.dutyUnitId"
                  placeholder="请选择部门"
                  style="width: 240px;margin-bottom: 5px"
              >
                <el-option
                    v-for="item in state.deptList"
                    :key="item.deptId"
                    :label="item.deptName"
                    :value="item.deptId"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="产品件号:" prop="partNum" >
              <el-input  :disabled="title === '查看'" v-model="state.form.partNum" placeholder="产品件号"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="8">
            <el-form-item label="反馈单位:" prop="feedUnitId" >
              <el-select
                  :disabled="title === '查看'"
                  v-model="state.form.feedUnitId"
                  placeholder="请选择部门"
                  style="width: 240px;margin-bottom: 5px"
              >
                <el-option
                    v-for="item in state.deptList"
                    :key="item.deptId"
                    :label="item.deptName"
                    :value="item.deptId"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="反馈人:" prop="feedUserId" >
              <el-select clearable v-model="state.form.feedUserId" :disabled="title =='查看'" filterable  style="width: 240px;margin-bottom: 5px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="反馈日期:" prop="feedTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.feedTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="反馈质量问题概述:" prop="feedQuestion" >
              <el-input  :disabled="title === '查看'" type="textarea" :rows="4" v-model="state.form.feedQuestion" placeholder=""></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="处置情况概述:" prop="dispose" >
              <el-input  :disabled="title === '查看'" type="textarea" :rows="4" v-model="state.form.dispose" placeholder=""></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="处置人:" prop="disposeId" >
              <el-select clearable v-model="state.form.disposeId" :disabled="title =='查看'" filterable  style="width: 240px;margin-bottom: 5px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="disposeTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.disposeTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkOutId" >
              <el-select clearable v-model="state.form.checkOutId" :disabled="title =='查看'" filterable  style="width: 240px;margin-bottom: 5px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="checkOutTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.checkOutTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="反馈单位复查人:" prop="reviewId" >
              <el-select clearable v-model="state.form.reviewId" :disabled="title =='查看'" filterable  style="width: 240px;margin-bottom: 5px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="reviewTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.reviewTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="返工工时:" prop="rework" >
              <el-input  :disabled="title === '查看'" @input="state.form.rework= state.form.rework.replace(/[^\d.]/g, '') .replace(/\.+/g, '.').replace(/^\./, '0.').replace(/^(\d*\.?\d{0,2}).*/, '$1')" v-model="state.form.rework" placeholder="返工工时"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="器材消耗:" prop="equipment" >
              <el-input  :disabled="title === '查看'" v-model="state.form.equipment" placeholder="器材消耗"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="延误生产工时:" prop="delay" >
              <el-input  :disabled="title === '查看'" @input="state.form.delay= state.form.delay.replace(/[^\d.]/g, '') .replace(/\.+/g, '.').replace(/^\./, '0.').replace(/^(\d*\.?\d{0,2}).*/, '$1')" v-model="state.form.delay" placeholder="延误生产工时"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="其他质量损伤:" prop="damage" >
              <el-input  :disabled="title === '查看'" v-model="state.form.damage" placeholder="其他质量损伤"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="检验组长:" prop="teamId" >
              <el-select clearable v-model="state.form.teamId" :disabled="title =='查看'" filterable  style="width: 240px;margin-bottom: 5px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="teamTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.teamTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="责任单位领导:" prop="dutyLeaderId" >
              <el-select clearable v-model="state.form.dutyLeaderId" :disabled="title =='查看'" filterable  style="width: 240px;margin-bottom: 5px">
                <el-option
                    v-for="item in state.peopleList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期:" prop="dutyLeaderTime" >
              <el-date-picker
                  :disabled="title === '查看'"
                  v-model="state.form.dutyLeaderTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer v-if="title !== '查看'">
        <span class="dialog-footer">
            <el-button @click="handleClose" size="default">取 消</el-button>
            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {reactive, ref, toRefs} from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import {verifyPhone} from "@/utils/validate";
import Cookies from "js-cookie";
import {addCustomer, editCustomer} from "@/api/customerList";
import {getDept} from "@/api/qualityObjectives/object";
import {getUser} from "@/api/onlineEducation/user";
import {addInternal, editInternal} from "@/api/internal/need";
const dialogVisible = ref(false);
const title = ref("");
const busRef = ref();
const length = ref()
const emit = defineEmits(["getList"]);
const state = reactive({
  form: {
    id: '',
    companyId: '',
    feedForm: "",
    number: "",
    productName: "",
    productModel: "",
    productNumber: "",
    dutyUnitId: null,
    partNum: "",
    feedUnitId: null,
    feedUserId: null,
    feedTime: "",
    feedQuestion: "",
    disposeId: null,
    disposeTime: "",
    checkOutId: null,
    checkOutTime: "",
    reviewId: null,
    reviewTime: "",
    rework: "",
    equipment: "",
    delay: "",
    damage: "",
    teamId: null,
    teamTime: "",
    dutyLeaderId: null,
    dutyLeaderTime: ""
  },
  formRules:{
    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
    feedForm: [{ required: true, message: '请输入反馈单名称', trigger: 'blur' }],
    number: [{ required: true, message: '请输入编号', trigger: 'blur' }],
    productName: [{ required: true, message: '请输入产品名称', trigger: 'blur' }],
    productModel:[{ required: true, message: '请输入产品型号', trigger: 'blur' }],
    productNumber: [{ required: true, message: '请输入产品公司编号', trigger: 'blur' }],
    dutyUnitId: [{ required: true, message: '请输入责任单位', trigger: 'blur' }],
    partNum: [{ required: true, message: '请输入产品件号', trigger: 'blur' }],
    feedUnitId: [{ required: true, message: '请输入反馈单位', trigger: 'blur' }],
    feedUserId: [{ required: true, message: '请选择反馈人', trigger: 'blur' }],
    feedTime: [{ required: true, message: '请选择反馈日期', trigger: 'blur' }],
    feedQuestion: [{ required: true, message: '请输入反馈问题描述', trigger: 'blur' }],
    disposeId: [{ required: true, message: '请选择处置人', trigger: 'blur' }],
    disposeTime: [{ required: true, message: '请选择处置人日期', trigger: 'blur' }],
    checkOutId: [{ required: true, message: '请选择检验人', trigger: 'blur' }],
    checkOutTime: [{ required: true, message: '请选择检验人日期', trigger: 'blur' }],
    reviewId: [{ required: true, message: '请选择反馈单位复查人', trigger: 'blur' }],
    reviewTime: [{ required: true, message: '请选择反馈单位复查人日期', trigger: 'blur' }],
    rework: [{ required: true, message: '请输入返工工时', trigger: 'blur' }],
    equipment: [{ required: true, message: '请输入器材消耗', trigger: 'blur' }],
    delay: [{ required: true, message: '请输入延误工时', trigger: 'blur' }],
    damage: [{ required: true, message: '请输入其他质量损伤', trigger: 'blur' }],
    teamId: [{ required: true, message: '请选择检验组长', trigger: 'blur' }],
    teamTime: [{ required: true, message: '请选择检验组长日期', trigger: 'blur' }],
    dutyLeaderId: [{ required: true, message: '请选择责任单位领导', trigger: 'blur' }],
    dutyLeaderTime: [{ required: true, message: '请选择责任单位领导日期', trigger: 'blur' }]
  },
  companyList: [],
  isAdmin: false,
  deptList: [],
  peopleList: [],
})
const openDialog = async (type, value,companyList) => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  state.isAdmin = userInfo.userType === 0;
  state.form.companyName = userInfo.companyName
  state.form.companyId = userInfo.companyId
  if(state.isAdmin){
    state.form.companyId = value.companyId
    state.form.companyName = value.companyName
    state.companyList = companyList
  }
  title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
  if(type === 'edit' || type === 'review') {
    state.form = JSON.parse(JSON.stringify(value));
    if(state.isAdmin){
      state.form.companyId = value.companyId
      state.form.companyName = value.companyName
    }
  }
  await getDeptList()
  await getPeopleList()
  dialogVisible.value = true;
}
const getDeptList = async () => {
  if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){
    return
  }
  const param = {
    pageNum: 1,
    pageSize: 999,
    companyId: state.form.companyId
  }
  const res = await getDept(param)
  if(res.code === 200){
    state.deptList = res.data
  }
}
const getPeopleList = async ()=> {
  if(state.isAdmin && (state.form.companyId == 0 || state.form.companyId == null)){
    return
  }
  const queryParams = {
    pageNum: 1,
    pageSize: 9999,
    companyId: state.form.companyId
  }
  const res = await getUser(queryParams)
  if(res.code == 200){
    state.peopleList = res.data.list?res.data.list:[]
  }else{
    ElMessage.warning(res.message)
  }
};
const onSubmit = async () => {
  const valid = await busRef.value.validate();
  if(!state.isAdmin){
    const userInfo = JSON.parse(Cookies.get('userInfo'))
    state.form.companyId = userInfo.companyId
  }
  if(valid){
    if(title.value === '新增'){
      const {id, ...data} = JSON.parse(JSON.stringify(state.form))
      const res = await addInternal(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '新增成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }else if(title.value === '编辑'){
      const {...data} = JSON.parse(JSON.stringify(state.form))
      const res = await editInternal(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '编辑成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }
  }
}
const handleClose = () => {
  busRef.value.clearValidate();
  reset();
  dialogVisible.value = false;
  emit("getList")
}
const selectValueCom = (val) => {
  state.form.dutyUnitId = null
  state.form.feedUnitId = null
  state.form.feedUserId = null
  state.form.disposeId = null
  state.form.checkOutId = null
  state.form.reviewId = null
  state.form.dutyLeaderId = null
  state.form.teamId = null
  state.companyList.forEach(item => {
    if(item.name === val){
      state.form.companyId = item.id
    }
  })
  getPeopleList()
  getDeptList()
}
const reset = () => {
  state.form = {
    id: '',
    companyId: '',
    feedForm: "",
    number: "",
    productName: "",
    productModel: "",
    productNumber: "",
    dutyUnitId: null,
    partNum: "",
    feedUnitId: null,
    feedUserId: null,
    feedTime: "",
    feedQuestion: "",
    disposeId: null,
    disposeTime: "",
    checkOutId: null,
    checkOutTime: "",
    reviewId: null,
    reviewTime: "",
    rework: "",
    equipment: "",
    delay: "",
    damage: "",
    teamId: null,
    teamTime: "",
    dutyLeaderId: null,
    dutyLeaderTime: ""
  }
  state.companyList = []
}
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>
src/views/work/qualityManage/qualityInformationPage/internal/index.vue
New file
@@ -0,0 +1,235 @@
<template>
  <div class="app-container">
    <div style="margin-bottom: 10px">
      <el-form style="display: flex;flex-wrap: wrap;">
        <el-form-item>
          <el-button
              type="primary"
              plain
              icon="Plus"
              @click="openDialog('add',{})"
          >新增</el-button>
        </el-form-item>
        <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
          <el-select v-model="data.queryParams.companyId" placeholder="请选择" filterable clearable>
            <el-option
                v-for="item in data.companyList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item v-if="data.isAdmin">
          <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
          <el-button plain @click="reset">重置</el-button>
        </el-form-item>
        <el-form-item style="margin-left: 15px">
          <el-button
              type="primary"
              @click="exportData"
          >导出</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true"  @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
      <el-table-column label="企业名称" prop="companyName" align="center" v-if="data.isAdmin" />
      <el-table-column label="反馈单名称"  align="center">
        <template #default="scope">
          <span>{{scope.row.feedForm}}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
        <template #default="scope">
          <el-button link type="primary"  @click="openDialog('review',scope.row)" >查看</el-button>
          <el-button link type="primary"  @click="openDialog('edit',scope.row)" >编辑</el-button>
          <el-button link type="danger"  @click="handleDelete(scope.row)" >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="pag-container">
      <el-pagination
          v-model:current-page="data.queryParams.pageNum"
          v-model:page-size="data.queryParams.pageSize"
          :page-sizes="[10,15,20,25]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </div>
    <editDialog ref="noticeRef" @getList = "getList"></editDialog>
  </div>
</template>
<script setup>
import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
import editDialog from "./components/editDialog.vue"
import {ElMessage, ElMessageBox} from "element-plus";
import {getCompany} from "@/api/onlineEducation/company";
import Cookies from "js-cookie";
import {generateWordDocument} from "@/utils/exportWord";
import {delTable, getTable} from "@/api/qualityObjectives/table";
import {delNeedDiscren, getNeedDiscren} from "@/api/need/need";
import {delCustomerNeed, getCustomerNeed} from "@/api/customerNeed";
import {delInternal, getInternal} from "@/api/internal/need";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const noticeRef = ref();
const deptRef = ref()
const loadingCompany = ref(false)
const choosedData = ref([])
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    companyId: null,
  },
  companyList: [],
  isAdmin: false,
  dialogVisible: false,
});
const dataList = ref([]);
const total = ref(0);
const { queryParams } = toRefs(data);
onMounted(() => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  console.log("userInfo",userInfo)
  data.isAdmin = userInfo.userType === 0;
  if(data.isAdmin){
    data.queryParams.companyId = null
  }else {
    data.queryParams.companyId = userInfo.companyId
  }
  getList();
  if(data.isAdmin){
    getCompanyList()
  }
});
const getList = async () => {
  loading.value = true;
  const res = await getInternal(data.queryParams);
  if(res.code === 200){
    dataList.value = res.data.list
    total.value = res.data.total
  }else{
    ElMessage.warning(res.message)
  }
  loading.value = false;
}
const searchClick = () => {
  getList();
}
const openDialog = (type, value) => {
  noticeRef.value.openDialog(type, value,data.companyList);
}
const getCompanyList = async ()=>{
  const queryParams = {
    pageNum: 1,
    pageSize: 999
  }
  const res = await getCompany(queryParams)
  if (res.code == 200) {
    data.companyList = res.data.list?res.data.list:[]
  } else {
    ElMessage.warning(res.message)
  }
}
const handleSizeChange = (val) => {
  data.queryParams.pageSize = val
  getList()
}
const handleCurrentChange = (val) => {
  data.queryParams.pageNum = val
  getList()
}
const handleClose = () => {
  data.dialogVisible = false
}
/** 重置新增的表单以及其他数据  */
function reset() {
  if(data.isAdmin){
    data.queryParams = {
      companyId: '',
      pageNum: 1,
      pageSize: 10,
    }
    choosedData.value = []
    data.companyList = [];
    getCompanyList()
  }else {
    data.queryParams = {
      companyId: data.queryParams.companyId,
      pageNum: 1,
      pageSize: 10,
    }
  }
  getList();
}
const exportData = () => {
  if(choosedData.value && choosedData.value.length === 0){
    ElMessage.warning('请选择需要导出的数据')
  }else {
    startGeneration()
  }
}
const templatePath = ref('/internalExample.docx')
const startGeneration = async () => {
  const data = JSON.parse(JSON.stringify(choosedData.value))
  data.forEach(item => {
    try {
      generateWordDocument(templatePath.value, item, item.companyName + `_质量信息反馈单(公司内).docx`);
    } catch (error){
      ElMessage({
        type: 'warning',
        message: '导出失败'
      });
    }
  })
}
const handleSelectionChange = (val) => {
  choosedData.value = val
}
const handleDelete = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delInternal(val.id);
        if(res.code === 200){
          ElMessage({
            type: 'success',
            message: '删除成功'
          });
          await getList();
        }else{
          ElMessage.warning(res.message)
        }
      })
}
</script>
<style lang="scss">
.pag-container{
  float: right;
  margin-top: 10px;
}
</style>