gaoluyang
6 天以前 71a9eef518f2f2f1a1eb2fb90f2eb8ab7b155bc8
Merge remote-tracking branch 'origin/dev_天津军泰伟业' into dev_天津军泰伟业
已修改32个文件
15151 ■■■■■ 文件已修改
src/components/QRCodeGenerator/index.vue 419 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/attendanceManagement/index.vue 1509 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/knowledgeBase/index.vue 359 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/notificationManagement/index.vue 716 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue 485 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue 365 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/notificationManagement/summary/index.vue 344 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/officeSupplies/index.vue 609 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/planTemplate/index.vue 665 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/rpaManagement/index.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/rulesRegulationsManagement/index.vue 839 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/sealManagement/index.vue 828 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/defectManagement/index.vue 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/formDia.vue 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/spareParts/index.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/example/DynamicTableExample.vue 340 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fileManagement/bookshelf/index.vue 509 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockWarning/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/components/milestoneList.vue 180 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/components/taskTree.vue 627 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/index.vue 328 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/projectDetail.vue 368 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementPlan/index.vue 627 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productManagement/productIdentifier/index.vue 777 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productStructure/StructureEdit.vue 291 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrder/index.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/customerManagement/index.vue 546 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/orderManagement/index.vue 607 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/paymentShipping/index.vue 596 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesQuotation/index.vue 813 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salespersonManagement/index.vue 461 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tool/gen/importTable.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/QRCodeGenerator/index.vue
@@ -1,70 +1,79 @@
<template>
  <div class="qr-code-generator">
    <!-- 二维码生成表单 -->
    <el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="qr-form">
    <el-form :model="form"
             :rules="rules"
             ref="formRef"
             label-width="120px"
             class="qr-form">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="标识类型" prop="type">
            <el-select v-model="form.type" placeholder="请选择标识类型" style="width: 100%">
              <el-option label="二维码" value="qrcode"></el-option>
              <el-option label="防伪码" value="security"></el-option>
          <el-form-item label="标识类型"
                        prop="type">
            <el-select v-model="form.type"
                       placeholder="请选择标识类型"
                       style="width: 100%">
              <el-option label="二维码"
                         value="qrcode"></el-option>
              <el-option label="防伪码"
                         value="security"></el-option>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="内容" prop="content">
            <el-input
              v-model="form.content"
          <el-form-item label="内容"
                        prop="content">
            <el-input v-model="form.content"
              placeholder="请输入要编码的内容"
              :type="form.type === 'security' ? 'textarea' : 'text'"
              :rows="form.type === 'security' ? 3 : 1"
            ></el-input>
                      :rows="form.type === 'security' ? 3 : 1"></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="尺寸" prop="size">
            <el-input-number
              v-model="form.size"
          <el-form-item label="尺寸"
                        prop="size">
            <el-input-number v-model="form.size"
              :min="100" 
              :max="500" 
              :step="50"
              style="width: 100%"
            ></el-input-number>
                             style="width: 100%"></el-input-number>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="边距" prop="margin">
            <el-input-number
              v-model="form.margin"
          <el-form-item label="边距"
                        prop="margin">
            <el-input-number v-model="form.margin"
              :min="0" 
              :max="10" 
              :step="1"
              style="width: 100%"
            ></el-input-number>
                             style="width: 100%"></el-input-number>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="前景色" prop="foregroundColor">
            <el-color-picker v-model="form.foregroundColor" style="width: 100%"></el-color-picker>
          <el-form-item label="前景色"
                        prop="foregroundColor">
            <el-color-picker v-model="form.foregroundColor"
                             style="width: 100%"></el-color-picker>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="背景色" prop="backgroundColor">
            <el-color-picker v-model="form.backgroundColor" style="width: 100%"></el-color-picker>
          <el-form-item label="背景色"
                        prop="backgroundColor">
            <el-color-picker v-model="form.backgroundColor"
                             style="width: 100%"></el-color-picker>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="24">
          <el-form-item>
            <el-button type="primary" @click="generateCode" :loading="generating">
            <el-button type="primary"
                       @click="generateCode"
                       :loading="generating">
              生成{{ form.type === 'qrcode' ? '二维码' : '防伪码' }}
            </el-button>
            <el-button @click="resetForm">重置</el-button>
@@ -72,18 +81,17 @@
        </el-col>
      </el-row>
    </el-form>
    <!-- 生成的码显示区域 -->
    <div v-if="generatedCodeUrl" class="code-display">
    <div v-if="generatedCodeUrl"
         class="code-display">
      <el-divider content-position="center">
        {{ form.type === 'qrcode' ? '生成的二维码' : '生成的防伪码' }}
      </el-divider>
      <div class="code-container">
        <div class="code-image">
          <img :src="generatedCodeUrl" :alt="form.type === 'qrcode' ? '二维码' : '防伪码'" />
          <img :src="generatedCodeUrl"
               :alt="form.type === 'qrcode' ? '二维码' : '防伪码'" />
        </div>
        <div class="code-info">
          <p><strong>内容:</strong>{{ form.content }}</p>
          <p><strong>类型:</strong>{{ form.type === 'qrcode' ? '二维码' : '防伪码' }}</p>
@@ -91,60 +99,71 @@
          <p><strong>生成时间:</strong>{{ generateTime }}</p>
        </div>
      </div>
      <div class="code-actions">
        <el-button type="success" @click="downloadCode" icon="Download">
        <el-button type="success"
                   @click="downloadCode"
                   icon="Download">
          下载图片
        </el-button>
        <el-button type="primary" @click="copyToClipboard" icon="CopyDocument">
        <el-button type="primary"
                   @click="copyToClipboard"
                   icon="CopyDocument">
          复制内容
        </el-button>
        <el-button @click="printCode" icon="Printer">
        <el-button @click="printCode"
                   icon="Printer">
          打印
        </el-button>
      </div>
    </div>
    <!-- 批量生成对话框 -->
    <el-dialog v-model="batchDialogVisible" title="批量生成" width="600px">
      <el-form :model="batchForm" label-width="120px">
    <el-dialog v-model="batchDialogVisible"
               title="批量生成"
               width="600px">
      <el-form :model="batchForm"
               label-width="120px">
        <el-form-item label="生成数量">
          <el-input-number v-model="batchForm.quantity" :min="1" :max="100" style="width: 100%"></el-input-number>
          <el-input-number v-model="batchForm.quantity"
                           :min="1"
                           :max="100"
                           style="width: 100%"></el-input-number>
        </el-form-item>
        <el-form-item label="前缀">
          <el-input v-model="batchForm.prefix" placeholder="请输入前缀,如:PROD_"></el-input>
          <el-input v-model="batchForm.prefix"
                    placeholder="请输入前缀,如:PROD_"></el-input>
        </el-form-item>
        <el-form-item label="起始编号">
          <el-input-number v-model="batchForm.startNumber" :min="1" style="width: 100%"></el-input-number>
          <el-input-number v-model="batchForm.startNumber"
                           :min="1"
                           style="width: 100%"></el-input-number>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="generateBatchCodes">开始生成</el-button>
          <el-button @click="batchDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="generateBatchCodes">开始生成</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 批量生成结果 -->
    <div v-if="batchCodes.length > 0" class="batch-results">
    <div v-if="batchCodes.length > 0"
         class="batch-results">
      <el-divider content-position="center">批量生成结果</el-divider>
      <div class="batch-grid">
        <div
          v-for="(code, index) in batchCodes"
        <div v-for="(code, index) in batchCodes"
          :key="index" 
          class="batch-item"
        >
          <img :src="code.url" :alt="code.content" />
             class="batch-item">
          <img :src="code.url"
               :alt="code.content" />
          <p class="batch-content">{{ code.content }}</p>
          <el-button size="small" @click="downloadSingleCode(code)">下载</el-button>
          <el-button size="small"
                     @click="downloadSingleCode(code)">下载</el-button>
        </div>
      </div>
      <div class="batch-actions">
        <el-button type="success" @click="downloadAllCodes">下载全部</el-button>
        <el-button type="success"
                   @click="downloadAllCodes">下载全部</el-button>
        <el-button @click="clearBatchCodes">清空结果</el-button>
      </div>
    </div>
@@ -152,145 +171,146 @@
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import QRCode from 'qrcode'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Download, CopyDocument, Printer } from '@element-plus/icons-vue'
  import { ref, reactive, computed, onMounted } from "vue";
  import QRCode from "qrcode";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Download, CopyDocument, Printer } from "@element-plus/icons-vue";
// 定义组件名称
defineOptions({
  name: 'QRCodeGenerator'
})
    name: "QRCodeGenerator",
  });
// 表单数据
const form = reactive({
  type: 'qrcode',
  content: '',
    type: "qrcode",
    content: "",
  size: 200,
  margin: 2,
  foregroundColor: '#000000',
  backgroundColor: '#FFFFFF'
})
    foregroundColor: "#000000",
    backgroundColor: "#FFFFFF",
  });
// 表单验证规则
const rules = {
  type: [{ required: true, message: '请选择标识类型', trigger: 'change' }],
  content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
}
    type: [{ required: true, message: "请选择标识类型", trigger: "change" }],
    content: [{ required: true, message: "请输入内容", trigger: "blur" }],
  };
// 响应式数据
const formRef = ref()
const generating = ref(false)
const generatedCodeUrl = ref('')
const generateTime = ref('')
const batchDialogVisible = ref(false)
  const formRef = ref();
  const generating = ref(false);
  const generatedCodeUrl = ref("");
  const generateTime = ref("");
  const batchDialogVisible = ref(false);
const batchForm = reactive({
  quantity: 10,
  prefix: '',
  startNumber: 1
})
const batchCodes = ref([])
    prefix: "",
    startNumber: 1,
  });
  const batchCodes = ref([]);
// 生成二维码或防伪码
const generateCode = async () => {
  try {
    await formRef.value.validate()
      await formRef.value.validate();
    
    if (!form.content.trim()) {
      ElMessage.warning('请输入要编码的内容')
      return
        ElMessage.warning("请输入要编码的内容");
        return;
    }
    
    generating.value = true
      generating.value = true;
    
    if (form.type === 'qrcode') {
      if (form.type === "qrcode") {
      // 生成二维码
      generatedCodeUrl.value = await QRCode.toDataURL(form.content, {
        width: form.size,
        margin: form.margin,
        color: {
          dark: form.foregroundColor,
          light: form.backgroundColor
            light: form.backgroundColor,
        },
        errorCorrectionLevel: 'M'
      })
          errorCorrectionLevel: "M",
        });
    } else {
      // 生成防伪码(使用二维码技术,但内容格式不同)
      const securityContent = generateSecurityCode(form.content)
        const securityContent = generateSecurityCode(form.content);
      generatedCodeUrl.value = await QRCode.toDataURL(securityContent, {
        width: form.size,
        margin: form.margin,
        color: {
          dark: form.foregroundColor,
          light: form.backgroundColor
            light: form.backgroundColor,
        },
        errorCorrectionLevel: 'H' // 防伪码使用最高纠错级别
      })
          errorCorrectionLevel: "H", // 防伪码使用最高纠错级别
        });
    }
    
    generateTime.value = new Date().toLocaleString()
    ElMessage.success('生成成功!')
      generateTime.value = new Date().toLocaleString();
      ElMessage.success("生成成功!");
  } catch (error) {
    console.error('生成失败:', error)
    ElMessage.error('生成失败:' + error.message)
      console.error("生成失败:", error);
      ElMessage.error("生成失败:" + error.message);
  } finally {
    generating.value = false
      generating.value = false;
  }
}
  };
// 生成防伪码内容
const generateSecurityCode = (content) => {
  const timestamp = Date.now()
  const random = Math.random().toString(36).substr(2, 8)
  return `SEC_${content}_${timestamp}_${random}`
}
  const generateSecurityCode = content => {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substr(2, 8);
    return `SEC_${content}_${timestamp}_${random}`;
  };
// 下载生成的码
const downloadCode = () => {
  if (!generatedCodeUrl.value) {
    ElMessage.warning('请先生成码')
    return
      ElMessage.warning("请先生成码");
      return;
  }
  
  const a = document.createElement('a')
  a.href = generatedCodeUrl.value
  a.download = `${form.type === 'qrcode' ? '二维码' : '防伪码'}_${new Date().getTime()}.png`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  ElMessage.success('下载成功!')
}
    const a = document.createElement("a");
    a.href = generatedCodeUrl.value;
    a.download = `${
      form.type === "qrcode" ? "二维码" : "防伪码"
    }_${new Date().getTime()}.png`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    ElMessage.success("下载成功!");
  };
// 复制内容到剪贴板
const copyToClipboard = async () => {
  try {
    await navigator.clipboard.writeText(form.content)
    ElMessage.success('内容已复制到剪贴板')
      await navigator.clipboard.writeText(form.content);
      ElMessage.success("内容已复制到剪贴板");
  } catch (error) {
    // 降级方案
    const textArea = document.createElement('textarea')
    textArea.value = form.content
    document.body.appendChild(textArea)
    textArea.select()
    document.execCommand('copy')
    document.body.removeChild(textArea)
    ElMessage.success('内容已复制到剪贴板')
      const textArea = document.createElement("textarea");
      textArea.value = form.content;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand("copy");
      document.body.removeChild(textArea);
      ElMessage.success("内容已复制到剪贴板");
  }
}
  };
// 打印码
const printCode = () => {
  if (!generatedCodeUrl.value) {
    ElMessage.warning('请先生成码')
    return
      ElMessage.warning("请先生成码");
      return;
  }
  
  const printWindow = window.open('', '_blank')
    const printWindow = window.open("", "_blank");
  printWindow.document.write(`
    <html>
      <head>
        <title>打印${form.type === 'qrcode' ? '二维码' : '防伪码'}</title>
          <title>打印${form.type === "qrcode" ? "二维码" : "防伪码"}</title>
        <style>
          body { text-align: center; padding: 20px; }
          img { max-width: 100%; height: auto; }
@@ -298,144 +318,149 @@
        </style>
      </head>
      <body>
        <h2>${form.type === 'qrcode' ? '二维码' : '防伪码'}</h2>
        <img src="${generatedCodeUrl.value}" alt="${form.type === 'qrcode' ? '二维码' : '防伪码'}" />
          <h2>${form.type === "qrcode" ? "二维码" : "防伪码"}</h2>
          <img src="${generatedCodeUrl.value}" alt="${
      form.type === "qrcode" ? "二维码" : "防伪码"
    }" />
        <div class="info">
          <p><strong>内容:</strong>${form.content}</p>
          <p><strong>生成时间:</strong>${generateTime.value}</p>
        </div>
      </body>
    </html>
  `)
  printWindow.document.close()
  printWindow.print()
}
    `);
    printWindow.document.close();
    printWindow.print();
  };
// 重置表单
const resetForm = () => {
  formRef.value.resetFields()
  generatedCodeUrl.value = ''
  generateTime.value = ''
  batchCodes.value = []
}
    formRef.value.resetFields();
    generatedCodeUrl.value = "";
    generateTime.value = "";
    batchCodes.value = [];
  };
// 批量生成
const generateBatchCodes = async () => {
  if (!batchForm.prefix.trim()) {
    ElMessage.warning('请输入前缀')
    return
      ElMessage.warning("请输入前缀");
      return;
  }
  
  batchCodes.value = []
  generating.value = true
    batchCodes.value = [];
    generating.value = true;
  
  try {
    for (let i = 0; i < batchForm.quantity; i++) {
      const number = batchForm.startNumber + i
      const content = `${batchForm.prefix}${number.toString().padStart(6, '0')}`
        const number = batchForm.startNumber + i;
        const content = `${batchForm.prefix}${number
          .toString()
          .padStart(6, "0")}`;
      
      let codeUrl
      if (form.type === 'qrcode') {
        let codeUrl;
        if (form.type === "qrcode") {
        codeUrl = await QRCode.toDataURL(content, {
          width: form.size,
          margin: form.margin,
          color: {
            dark: form.foregroundColor,
            light: form.backgroundColor
          }
        })
              light: form.backgroundColor,
            },
          });
      } else {
        const securityContent = generateSecurityCode(content)
          const securityContent = generateSecurityCode(content);
        codeUrl = await QRCode.toDataURL(securityContent, {
          width: form.size,
          margin: form.margin,
          color: {
            dark: form.foregroundColor,
            light: form.backgroundColor
          }
        })
              light: form.backgroundColor,
            },
          });
      }
      
      batchCodes.value.push({
        content,
        url: codeUrl
      })
          url: codeUrl,
        });
    }
    
    ElMessage.success(`批量生成完成,共生成 ${batchForm.quantity} 个码`)
    batchDialogVisible.value = false
      ElMessage.success(`批量生成完成,共生成 ${batchForm.quantity} 个码`);
      batchDialogVisible.value = false;
  } catch (error) {
    console.error('批量生成失败:', error)
    ElMessage.error('批量生成失败:' + error.message)
      console.error("批量生成失败:", error);
      ElMessage.error("批量生成失败:" + error.message);
  } finally {
    generating.value = false
      generating.value = false;
  }
}
  };
// 下载单个批量生成的码
const downloadSingleCode = (code) => {
  const a = document.createElement('a')
  a.href = code.url
  a.download = `${code.content}.png`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}
  const downloadSingleCode = code => {
    const a = document.createElement("a");
    a.href = code.url;
    a.download = `${code.content}.png`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  };
// 下载所有批量生成的码
const downloadAllCodes = async () => {
  if (batchCodes.value.length === 0) {
    ElMessage.warning('没有可下载的码')
    return
      ElMessage.warning("没有可下载的码");
      return;
  }
  
  try {
    // 使用JSZip打包下载
    const JSZip = await import('jszip')
    const zip = new JSZip.default()
      const JSZip = await import("jszip");
      const zip = new JSZip.default();
    
    batchCodes.value.forEach((code, index) => {
      // 将base64转换为blob
      const base64Data = code.url.split(',')[1]
      const byteCharacters = atob(base64Data)
      const byteNumbers = new Array(byteCharacters.length)
        const base64Data = code.url.split(",")[1];
        const byteCharacters = atob(base64Data);
        const byteNumbers = new Array(byteCharacters.length);
      for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i)
          byteNumbers[i] = byteCharacters.charCodeAt(i);
      }
      const byteArray = new Uint8Array(byteNumbers)
        const byteArray = new Uint8Array(byteNumbers);
      
      zip.file(`${code.content}.png`, byteArray)
    })
        zip.file(`${code.content}.png`, byteArray);
      });
    
    const content = await zip.generateAsync({ type: 'blob' })
    const a = document.createElement('a')
    a.href = URL.createObjectURL(content)
    a.download = `批量${form.type === 'qrcode' ? '二维码' : '防伪码'}_${new Date().getTime()}.zip`
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(a.href)
      const content = await zip.generateAsync({ type: "blob" });
      const a = document.createElement("a");
      a.href = URL.createObjectURL(content);
      a.download = `批量${
        form.type === "qrcode" ? "二维码" : "防伪码"
      }_${new Date().getTime()}.zip`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(a.href);
    
    ElMessage.success('批量下载完成!')
      ElMessage.success("批量下载完成!");
  } catch (error) {
    console.error('批量下载失败:', error)
    ElMessage.error('批量下载失败,请逐个下载')
      console.error("批量下载失败:", error);
      ElMessage.error("批量下载失败,请逐个下载");
  }
}
  };
// 清空批量生成结果
const clearBatchCodes = () => {
  batchCodes.value = []
}
    batchCodes.value = [];
  };
// 暴露方法给父组件
defineExpose({
  generateCode,
  downloadCode,
  resetForm,
  form
})
    form,
  });
</script>
<style scoped>
src/views/collaborativeApproval/attendanceManagement/index.vue
@@ -1,310 +1,419 @@
<template>
  <div class="app-container">
    <el-tabs v-model="activeTab" type="border-card">
    <el-tabs v-model="activeTab"
             type="border-card">
      <!-- 假期设置 -->
      <el-tab-pane label="假期设置" name="holiday">
      <el-tab-pane label="假期设置"
                   name="holiday">
        <div class="tab-content">
          <el-button type="primary" @click="openDialog('holiday', 'add')">新增假期</el-button>
          <el-table :data="holidayData" border style="width: 100%; margin-top: 20px;">
            <el-table-column prop="name" label="假期名称" />
            <el-table-column prop="type" label="假期类型">
          <el-button type="primary"
                     @click="openDialog('holiday', 'add')">新增假期</el-button>
          <el-table :data="holidayData"
                    border
                    style="width: 100%; margin-top: 20px;">
            <el-table-column prop="name"
                             label="假期名称" />
            <el-table-column prop="type"
                             label="假期类型">
              <template #default="scope">
                <el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="startDate" label="开始日期"  />
            <el-table-column prop="endDate" label="结束日期"  />
            <el-table-column prop="days" label="天数"  align="center" />
            <el-table-column prop="status" label="状态" >
            <el-table-column prop="startDate"
                             label="开始日期" />
            <el-table-column prop="endDate"
                             label="结束日期" />
            <el-table-column prop="days"
                             label="天数"
                             align="center" />
            <el-table-column prop="status"
                             label="状态">
              <template #default="scope">
                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
                  {{ scope.row.status === 'active' ? '启用' : '停用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" fixed="right">
            <el-table-column label="操作"
                             fixed="right">
              <template #default="scope">
                <el-button type="primary" size="small" @click="openDialog('holiday', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('holiday', scope.row)">删除</el-button>
                <el-button type="primary"
                           size="small"
                           @click="openDialog('holiday', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger"
                           size="small"
                           @click="deleteItem('holiday', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-tab-pane>
      <!-- 年假设置 -->
      <el-tab-pane label="年假设置" name="annual">
      <el-tab-pane label="年假设置"
                   name="annual">
        <div class="tab-content">
          <el-button type="primary" @click="openDialog('annual', 'add')">新增年假规则</el-button>
          <el-table :data="annualData" border style="width: 100%; margin-top: 20px;">
            <el-table-column prop="employeeType" label="员工类型">
          <el-button type="primary"
                     @click="openDialog('annual', 'add')">新增年假规则</el-button>
          <el-table :data="annualData"
                    border
                    style="width: 100%; margin-top: 20px;">
            <el-table-column prop="employeeType"
                             label="员工类型">
              <template #default="scope">
                <el-tag :type="getTagType(scope.row.employeeType)">{{ getTypeLabel(scope.row.employeeType) }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="workYears" label="工作年限" />
            <el-table-column prop="annualDays" label="年假天数" align="center" />
            <el-table-column prop="maxCarryOver" label="最大结转天数" align="center" />
            <el-table-column prop="status" label="状态">
            <el-table-column prop="workYears"
                             label="工作年限" />
            <el-table-column prop="annualDays"
                             label="年假天数"
                             align="center" />
            <el-table-column prop="maxCarryOver"
                             label="最大结转天数"
                             align="center" />
            <el-table-column prop="status"
                             label="状态">
              <template #default="scope">
                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
                  {{ scope.row.status === 'active' ? '启用' : '停用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" fixed="right">
            <el-table-column label="操作"
                             fixed="right">
              <template #default="scope">
                <el-button type="primary" size="small" @click="openDialog('annual', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('annual', scope.row)">删除</el-button>
                <el-button type="primary"
                           size="small"
                           @click="openDialog('annual', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger"
                           size="small"
                           @click="deleteItem('annual', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-tab-pane>
      <!-- 加班设置 -->
      <el-tab-pane label="加班设置" name="overtime">
      <el-tab-pane label="加班设置"
                   name="overtime">
        <div class="tab-content">
          <el-button type="primary" @click="openDialog('overtime', 'add')">新增加班规则</el-button>
          <el-table :data="overtimeData" border style="width: 100%; margin-top: 20px;">
            <el-table-column prop="name" label="规则名称" />
            <el-table-column prop="type" label="加班类型" >
          <el-button type="primary"
                     @click="openDialog('overtime', 'add')">新增加班规则</el-button>
          <el-table :data="overtimeData"
                    border
                    style="width: 100%; margin-top: 20px;">
            <el-table-column prop="name"
                             label="规则名称" />
            <el-table-column prop="type"
                             label="加班类型">
              <template #default="scope">
                <el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="startTime" label="开始时间"  />
            <el-table-column prop="endTime" label="结束时间"  />
            <el-table-column prop="rate" label="倍率" align="center" />
            <el-table-column prop="status" label="状态" >
            <el-table-column prop="startTime"
                             label="开始时间" />
            <el-table-column prop="endTime"
                             label="结束时间" />
            <el-table-column prop="rate"
                             label="倍率"
                             align="center" />
            <el-table-column prop="status"
                             label="状态">
              <template #default="scope">
                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
                  {{ scope.row.status === 'active' ? '启用' : '停用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" fixed="right">
            <el-table-column label="操作"
                             fixed="right">
              <template #default="scope">
                <el-button type="primary" size="small" @click="openDialog('overtime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('overtime', scope.row)">删除</el-button>
                <el-button type="primary"
                           size="small"
                           @click="openDialog('overtime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger"
                           size="small"
                           @click="deleteItem('overtime', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-tab-pane>
      <!-- 上班时间设置 -->
      <el-tab-pane label="上班时间设置" name="worktime">
      <el-tab-pane label="上班时间设置"
                   name="worktime">
        <div class="tab-content">
          <el-button type="primary" @click="openDialog('worktime', 'add')">新增时间段</el-button>
          <el-table :data="worktimeData" border style="width: 100%; margin-top: 20px;">
            <el-table-column prop="name" label="时间段名称"  />
            <el-table-column prop="startTime" label="上班时间"/>
            <el-table-column prop="endTime" label="下班时间" />
            <el-table-column prop="flexibleStart" label="弹性上班">
          <el-button type="primary"
                     @click="openDialog('worktime', 'add')">新增时间段</el-button>
          <el-table :data="worktimeData"
                    border
                    style="width: 100%; margin-top: 20px;">
            <el-table-column prop="name"
                             label="时间段名称" />
            <el-table-column prop="startTime"
                             label="上班时间" />
            <el-table-column prop="endTime"
                             label="下班时间" />
            <el-table-column prop="flexibleStart"
                             label="弹性上班">
              <template #default="scope">
                <el-tag :type="scope.row.flexibleStart === 'true' ? 'success' : 'info'">
                  {{ scope.row.flexibleStart === 'true' ? '是' : '否' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="flexibleMinutes" label="弹性时间(分钟)" width="120" align="center" />
            <el-table-column prop="status" label="状态" >
            <el-table-column prop="flexibleMinutes"
                             label="弹性时间(分钟)"
                             width="120"
                             align="center" />
            <el-table-column prop="status"
                             label="状态">
              <template #default="scope">
                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
                  {{ scope.row.status === 'active' ? '启用' : '停用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" fixed="right">
            <el-table-column label="操作"
                             fixed="right">
              <template #default="scope">
                <el-button type="primary" size="small" @click="openDialog('worktime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('worktime', scope.row)">删除</el-button>
                <el-button type="primary"
                           size="small"
                           @click="openDialog('worktime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger"
                           size="small"
                           @click="deleteItem('worktime', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-tab-pane>
      <!-- 打卡记录 -->
      <el-tab-pane label="打卡记录" name="attendance">
      <el-tab-pane label="打卡记录"
                   name="attendance">
        <div class="tab-content">
          <div style="margin-bottom: 20px;">
            <el-date-picker
              v-model="attendanceDate"
            <el-date-picker v-model="attendanceDate"
              type="date"
              placeholder="选择日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              style="margin-right: 10px;"
              @change="filterAttendanceData"
            />
            <el-select
              v-model="attendanceStatus"
                            @change="filterAttendanceData" />
            <el-select v-model="attendanceStatus"
              placeholder="选择状态"
              style="width: 120px; margin-right: 10px;"
              @change="filterAttendanceData"
            >
              <el-option label="全部" value="" />
              <el-option label="正常" value="normal" />
              <el-option label="迟到" value="late" />
              <el-option label="早退" value="early" />
              <el-option label="缺勤" value="absent" />
                       @change="filterAttendanceData">
              <el-option label="全部"
                         value="" />
              <el-option label="正常"
                         value="normal" />
              <el-option label="迟到"
                         value="late" />
              <el-option label="早退"
                         value="early" />
              <el-option label="缺勤"
                         value="absent" />
            </el-select>
            <el-button type="primary" @click="exportAttendance">导出记录</el-button>
            <el-button type="primary"
                       @click="exportAttendance">导出记录</el-button>
          </div>
          <el-table :data="filteredAttendanceData" border style="width: 100%;">
            <el-table-column prop="employeeName" label="员工姓名" width="120" />
            <el-table-column prop="department" label="部门" width="120" />
            <el-table-column prop="date" label="日期" width="120" />
            <el-table-column prop="clockInTime" label="上班打卡" width="120" />
            <el-table-column prop="clockOutTime" label="下班打卡" width="120" />
            <el-table-column prop="workHours" label="工作时长" width="100" align="center" />
            <el-table-column prop="status" label="状态" width="100" align="center">
          <el-table :data="filteredAttendanceData"
                    border
                    style="width: 100%;">
            <el-table-column prop="employeeName"
                             label="员工姓名"
                             width="120" />
            <el-table-column prop="department"
                             label="部门"
                             width="120" />
            <el-table-column prop="date"
                             label="日期"
                             width="120" />
            <el-table-column prop="clockInTime"
                             label="上班打卡"
                             width="120" />
            <el-table-column prop="clockOutTime"
                             label="下班打卡"
                             width="120" />
            <el-table-column prop="workHours"
                             label="工作时长"
                             width="100"
                             align="center" />
            <el-table-column prop="status"
                             label="状态"
                             width="100"
                             align="center">
              <template #default="scope">
                <el-tag :type="getAttendanceTagType(scope.row.status)">{{ getAttendanceStatusLabel(scope.row.status) }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="location" label="打卡地点" width="150" />
            <el-table-column prop="remark" label="备注" min-width="150" />
            <el-table-column prop="location"
                             label="打卡地点"
                             width="150" />
            <el-table-column prop="remark"
                             label="备注"
                             min-width="150" />
          </el-table>
        </div>
      </el-tab-pane>
    </el-tabs>
    <!-- 通用弹窗 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="名称" prop="name" v-if="currentType !== 'annual'">
          <el-input v-model="form.name" placeholder="请输入名称" />
    <el-dialog v-model="dialogVisible"
               :title="dialogTitle"
               width="600px">
      <el-form ref="formRef"
               :model="form"
               :rules="rules"
               label-width="100px">
        <el-form-item label="名称"
                      prop="name"
                      v-if="currentType !== 'annual'">
          <el-input v-model="form.name"
                    placeholder="请输入名称" />
        </el-form-item>
        <el-form-item label="类型" prop="type" v-if="currentType === 'holiday' || currentType === 'overtime'">
          <el-select v-model="form.type" placeholder="请选择类型" style="width: 100%">
            <el-option
              v-for="option in getTypeOptions()"
        <el-form-item label="类型"
                      prop="type"
                      v-if="currentType === 'holiday' || currentType === 'overtime'">
          <el-select v-model="form.type"
                     placeholder="请选择类型"
                     style="width: 100%">
            <el-option v-for="option in getTypeOptions()"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            />
                       :value="option.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="员工类型" prop="employeeType" v-if="currentType === 'annual'">
          <el-select v-model="form.employeeType" placeholder="请选择员工类型" style="width: 100%">
        <el-form-item label="员工类型"
                      prop="employeeType"
                      v-if="currentType === 'annual'">
          <el-select v-model="form.employeeType"
                     placeholder="请选择员工类型"
                     style="width: 100%">
            <!-- <el-option label="正式员工" value="regular" />
            <el-option label="试用期员工" value="probation" />
            <el-option label="实习生" value="intern" /> -->
            <el-option
              v-for="option in getTypeOptions()"
            <el-option v-for="option in getTypeOptions()"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            />
                       :value="option.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="工作年限" prop="workYears" v-if="currentType === 'annual'">
          <el-input v-model="form.workYears" placeholder="如:1-3年、3-5年等" />
        <el-form-item label="工作年限"
                      prop="workYears"
                      v-if="currentType === 'annual'">
          <el-input v-model="form.workYears"
                    placeholder="如:1-3年、3-5年等" />
        </el-form-item>
        <el-form-item label="年假天数" prop="annualDays" v-if="currentType === 'annual'">
          <el-input-number v-model="form.annualDays" :min="0" :max="365" style="width: 100%" />
        <el-form-item label="年假天数"
                      prop="annualDays"
                      v-if="currentType === 'annual'">
          <el-input-number v-model="form.annualDays"
                           :min="0"
                           :max="365"
                           style="width: 100%" />
        </el-form-item>
        <el-form-item label="最大结转天数" prop="maxCarryOver" v-if="currentType === 'annual'">
          <el-input-number v-model="form.maxCarryOver" :min="0" :max="30" style="width: 100%" />
        <el-form-item label="最大结转天数"
                      prop="maxCarryOver"
                      v-if="currentType === 'annual'">
          <el-input-number v-model="form.maxCarryOver"
                           :min="0"
                           :max="30"
                           style="width: 100%" />
        </el-form-item>
                          <el-form-item label="日期范围" prop="dateRange" v-if="currentType === 'holiday'">
           <el-date-picker
             v-model="form.dateRange"
        <el-form-item label="日期范围"
                      prop="dateRange"
                      v-if="currentType === 'holiday'">
          <el-date-picker v-model="form.dateRange"
             type="daterange"
             range-separator="至"
             start-placeholder="开始日期"
             end-placeholder="结束日期"
             style="width: 100%"
             @change="calculateDays"
           />
                          @change="calculateDays" />
         </el-form-item>
        <el-form-item label="天数" prop="days" v-if="currentType === 'holiday'">
          <el-input-number v-model="form.days" :min="0" style="width: 100%" />
        <el-form-item label="天数"
                      prop="days"
                      v-if="currentType === 'holiday'">
          <el-input-number v-model="form.days"
                           :min="0"
                           style="width: 100%" />
        </el-form-item>
                 <el-form-item label="开始时间" prop="startTime" v-if="currentType === 'overtime'">
           <el-time-picker
             v-model="form.startTime"
        <el-form-item label="开始时间"
                      prop="startTime"
                      v-if="currentType === 'overtime'">
          <el-time-picker v-model="form.startTime"
             placeholder="开始时间"
             format="HH:mm"
             value-format="HH:mm"
             style="width: 100%"
             @change="validateTimeField('startTime')"
           />
                          @change="validateTimeField('startTime')" />
         </el-form-item>
         <el-form-item label="结束时间" prop="endTime" v-if="currentType === 'overtime'">
           <el-time-picker
             v-model="form.endTime"
        <el-form-item label="结束时间"
                      prop="endTime"
                      v-if="currentType === 'overtime'">
          <el-time-picker v-model="form.endTime"
             placeholder="结束时间"
             format="HH:mm"
             value-format="HH:mm"
             style="width: 100%"
             @change="validateTimeField('endTime')"
           />
                          @change="validateTimeField('endTime')" />
         </el-form-item>
        <el-form-item label="倍率" prop="rate" v-if="currentType === 'overtime'">
          <el-input-number v-model="form.rate" :min="1" :max="3" :step="0.5" style="width: 100%" />
        <el-form-item label="倍率"
                      prop="rate"
                      v-if="currentType === 'overtime'">
          <el-input-number v-model="form.rate"
                           :min="1"
                           :max="3"
                           :step="0.5"
                           style="width: 100%" />
        </el-form-item>
                 <el-form-item label="上班时间" prop="workStartTime" v-if="currentType === 'worktime'">
           <el-time-picker
             v-model="form.workStartTime"
        <el-form-item label="上班时间"
                      prop="workStartTime"
                      v-if="currentType === 'worktime'">
          <el-time-picker v-model="form.workStartTime"
             placeholder="上班时间"
             format="HH:mm"
             value-format="HH:mm"
             style="width: 100%"
             @change="validateTimeField('workStartTime')"
           />
                          @change="validateTimeField('workStartTime')" />
         </el-form-item>
         <el-form-item label="下班时间" prop="workEndTime" v-if="currentType === 'worktime'">
           <el-time-picker
             v-model="form.workEndTime"
        <el-form-item label="下班时间"
                      prop="workEndTime"
                      v-if="currentType === 'worktime'">
          <el-time-picker v-model="form.workEndTime"
             placeholder="下班时间"
             format="HH:mm"
             value-format="HH:mm"
             style="width: 100%"
             @change="validateTimeField('workEndTime')"
           />
                          @change="validateTimeField('workEndTime')" />
         </el-form-item>
        <el-form-item label="弹性上班" prop="flexibleStart" v-if="currentType === 'worktime'">
        <el-form-item label="弹性上班"
                      prop="flexibleStart"
                      v-if="currentType === 'worktime'">
          <el-switch v-model="form.flexibleStart" />
        </el-form-item>
        <el-form-item label="弹性时间(分钟)" prop="flexibleMinutes" v-if="currentType === 'worktime' && form.flexibleStart">
          <el-input-number v-model="form.flexibleMinutes" :min="0" :max="120" style="width: 100%" />
        <el-form-item label="弹性时间(分钟)"
                      prop="flexibleMinutes"
                      v-if="currentType === 'worktime' && form.flexibleStart">
          <el-input-number v-model="form.flexibleMinutes"
                           :min="0"
                           :max="120"
                           style="width: 100%" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
        <el-form-item label="状态"
                      prop="status">
           <el-radio-group v-model="form.status">
             <el-radio value="active">启用</el-radio>
             <el-radio value="inactive">停用</el-radio>
           </el-radio-group>
         </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </span>
      </template>
    </el-dialog>
@@ -312,205 +421,255 @@
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { listHolidaySettings, addHolidaySettings, updateHolidaySettings, delHolidaySettings, listAnnualLeaveSettingList, addAnnualLeaveSetting, updateAnnualLeaveSetting, delAnnualLeaveSetting, listOvertimeSettingList, addOvertimeSetting, updateOvertimeSetting, delOvertimeSetting, listWorkingHoursSettingList, addWorkingHoursSetting, updateWorkingHoursSetting, delWorkingHoursSetting } from '@/api/collaborativeApproval/attendanceManagement.js'
  import { ref, reactive, onMounted, onUnmounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import {
    listHolidaySettings,
    addHolidaySettings,
    updateHolidaySettings,
    delHolidaySettings,
    listAnnualLeaveSettingList,
    addAnnualLeaveSetting,
    updateAnnualLeaveSetting,
    delAnnualLeaveSetting,
    listOvertimeSettingList,
    addOvertimeSetting,
    updateOvertimeSetting,
    delOvertimeSetting,
    listWorkingHoursSettingList,
    addWorkingHoursSetting,
    updateWorkingHoursSetting,
    delWorkingHoursSetting,
  } from "@/api/collaborativeApproval/attendanceManagement.js";
// 当前激活的标签页
const activeTab = ref('holiday')
  const activeTab = ref("holiday");
// 弹窗相关
const dialogVisible = ref(false)
const dialogTitle = ref('')
const currentType = ref('')
const currentAction = ref('')
const currentEditId = ref('')
const formRef = ref()
  const dialogVisible = ref(false);
  const dialogTitle = ref("");
  const currentType = ref("");
  const currentAction = ref("");
  const currentEditId = ref("");
  const formRef = ref();
const page = {
    current: 1,
    size: 20,
    total: 0,
  }
const holidayData = ref([])
const annualData = ref([])
const overtimeData = ref([])
const worktimeData = ref([])
  };
  const holidayData = ref([]);
  const annualData = ref([]);
  const overtimeData = ref([]);
  const worktimeData = ref([]);
// 打卡记录相关数据
const attendanceData = ref([])
const filteredAttendanceData = ref([])
const attendanceDate = ref('')
const attendanceStatus = ref('')
  const attendanceData = ref([]);
  const filteredAttendanceData = ref([]);
  const attendanceDate = ref("");
  const attendanceStatus = ref("");
// 表单数据
const form = reactive({
  name: '',
  type: '',
    name: "",
    type: "",
  dateRange: [],
  startDate: '',
  endDate: '',
    startDate: "",
    endDate: "",
  days: 0,
  employeeType: '',
  workYears: '',
    employeeType: "",
    workYears: "",
  annualDays: 0,
  maxCarryOver: 0,
  startTime: '', // 加班开始时间
  endTime: '',   // 加班结束时间
  workStartTime: '', // 上班时间
  workEndTime: '',   // 下班时间
    startTime: "", // 加班开始时间
    endTime: "", // 加班结束时间
    workStartTime: "", // 上班时间
    workEndTime: "", // 下班时间
  rate: 1.5,
  flexibleStart: false,
  flexibleMinutes: 30,
  status: 'active'
})
    status: "active",
  });
// 表单验证规则
const rules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  type: [{ required: true, message: '请选择类型', trigger: 'change' }],
  dateRange: [{ required: true, message: '请选择日期范围', trigger: 'change' }],
  days: [{ required: true, message: '请输入天数', trigger: 'blur' }],
  employeeType: [{ required: true, message: '请选择员工类型', trigger: 'change' }],
  workYears: [{ required: true, message: '请输入工作年限', trigger: 'blur' }],
  annualDays: [{ required: true, message: '请输入年假天数', trigger: 'blur' }],
  maxCarryOver: [{ required: true, message: '请输入最大结转天数', trigger: 'blur' }],
  startTime: [{
    name: [{ required: true, message: "请输入名称", trigger: "blur" }],
    type: [{ required: true, message: "请选择类型", trigger: "change" }],
    dateRange: [{ required: true, message: "请选择日期范围", trigger: "change" }],
    days: [{ required: true, message: "请输入天数", trigger: "blur" }],
    employeeType: [
      { required: true, message: "请选择员工类型", trigger: "change" },
    ],
    workYears: [{ required: true, message: "请输入工作年限", trigger: "blur" }],
    annualDays: [{ required: true, message: "请输入年假天数", trigger: "blur" }],
    maxCarryOver: [
      { required: true, message: "请输入最大结转天数", trigger: "blur" },
    ],
    startTime: [
      {
    required: true,
    message: '请选择开始时间',
    trigger: 'change',
        message: "请选择开始时间",
        trigger: "change",
    validator: (rule, value, callback) => {
      if (!value) {
        callback(new Error('请选择开始时间'))
            callback(new Error("请选择开始时间"));
      } else {
        callback()
            callback();
      }
    }
  }],
  endTime: [{
        },
      },
    ],
    endTime: [
      {
    required: true,
    message: '请选择结束时间',
    trigger: 'change',
        message: "请选择结束时间",
        trigger: "change",
    validator: (rule, value, callback) => {
      if (!value) {
        callback(new Error('请选择结束时间'))
            callback(new Error("请选择结束时间"));
      } else {
        callback()
            callback();
      }
    }
  }],
  workStartTime: [{
        },
      },
    ],
    workStartTime: [
      {
    required: true,
    message: '请选择上班时间',
    trigger: 'change',
        message: "请选择上班时间",
        trigger: "change",
    validator: (rule, value, callback) => {
      if (!value) {
        callback(new Error('请选择上班时间'))
            callback(new Error("请选择上班时间"));
      } else {
        callback()
            callback();
      }
    }
  }],
  workEndTime: [{
        },
      },
    ],
    workEndTime: [
      {
    required: true,
    message: '请选择下班时间',
    trigger: 'change',
        message: "请选择下班时间",
        trigger: "change",
    validator: (rule, value, callback) => {
      if (!value) {
        callback(new Error('请选择下班时间'))
            callback(new Error("请选择下班时间"));
      } else {
        callback()
            callback();
      }
    }
  }],
  rate: [{ required: true, message: '请输入倍率', trigger: 'blur' }]
}
        },
      },
    ],
    rate: [{ required: true, message: "请输入倍率", trigger: "blur" }],
  };
// 工具函数
const getTagType = (type) => {
  const getTagType = type => {
  const tagMap = {
    legal: 'success', adjustment: 'warning', special: 'info', company: 'primary',
    weekday: 'primary', weekend: 'warning', holiday: 'danger', night: 'info',
    regular: 'success', probation: 'info', intern: 'danger'
  }
  return tagMap[type] || 'info'
}
      legal: "success",
      adjustment: "warning",
      special: "info",
      company: "primary",
      weekday: "primary",
      weekend: "warning",
      holiday: "danger",
      night: "info",
      regular: "success",
      probation: "info",
      intern: "danger",
    };
    return tagMap[type] || "info";
  };
const getTypeLabel = (type) => {
  const getTypeLabel = type => {
  const labelMap = {
    legal: '法定节假日', adjustment: '调休日', special: '特殊假期', company: '公司假期',
    weekday: '工作日加班', weekend: '周末加班', holiday: '节假日加班', night: '深夜加班',
    regular: '正式员工', probation: '试用期员工', intern: '实习生'
  }
  return labelMap[type] || type
}
      legal: "法定节假日",
      adjustment: "调休日",
      special: "特殊假期",
      company: "公司假期",
      weekday: "工作日加班",
      weekend: "周末加班",
      holiday: "节假日加班",
      night: "深夜加班",
      regular: "正式员工",
      probation: "试用期员工",
      intern: "实习生",
    };
    return labelMap[type] || type;
  };
// 打卡记录相关工具函数
const getAttendanceTagType = (status) => {
  const getAttendanceTagType = status => {
  const tagMap = {
    normal: 'success',
    late: 'warning',
    early: 'warning',
    absent: 'danger'
  }
  return tagMap[status] || 'info'
}
      normal: "success",
      late: "warning",
      early: "warning",
      absent: "danger",
    };
    return tagMap[status] || "info";
  };
const getAttendanceStatusLabel = (status) => {
  const getAttendanceStatusLabel = status => {
  const labelMap = {
    normal: '正常',
    late: '迟到',
    early: '早退',
    absent: '缺勤'
  }
  return labelMap[status] || status
}
      normal: "正常",
      late: "迟到",
      early: "早退",
      absent: "缺勤",
    };
    return labelMap[status] || status;
  };
const getTypeOptions = () => {
  if (currentType.value === 'holiday') {
    if (currentType.value === "holiday") {
    return [
      { label: '法定节假日', value: 'legal' },
      { label: '调休日', value: 'adjustment' },
      { label: '特殊假期', value: 'special' },
      { label: '公司假期', value: 'company' }
    ]
  } else if (currentType.value === 'overtime') {
        { label: "法定节假日", value: "legal" },
        { label: "调休日", value: "adjustment" },
        { label: "特殊假期", value: "special" },
        { label: "公司假期", value: "company" },
      ];
    } else if (currentType.value === "overtime") {
    return [
      { label: '工作日加班', value: 'weekday' },
      { label: '周末加班', value: 'weekend' },
      { label: '节假日加班', value: 'holiday' },
      { label: '深夜加班', value: 'night' }
    ]
  } else if (currentType.value === 'annual') {
        { label: "工作日加班", value: "weekday" },
        { label: "周末加班", value: "weekend" },
        { label: "节假日加班", value: "holiday" },
        { label: "深夜加班", value: "night" },
      ];
    } else if (currentType.value === "annual") {
    return [
      { label: '正式员工', value: 'regular' },
      { label: '试用期员工', value: 'probation' },
      { label: '实习生', value: 'intern' }
    ]
        { label: "正式员工", value: "regular" },
        { label: "试用期员工", value: "probation" },
        { label: "实习生", value: "intern" },
      ];
  }
  return []
}
    return [];
  };
// 计算假期天数
const calculateDays = () => {
  try {
    if (form.dateRange && form.dateRange.length === 2 && form.dateRange[0] && form.dateRange[1]) {
      const start = new Date(form.dateRange[0])
      const end = new Date(form.dateRange[1])
      form.startDate = start.toISOString().split('T')[0]
      form.endDate = end.toISOString().split('T')[0]
      if (
        form.dateRange &&
        form.dateRange.length === 2 &&
        form.dateRange[0] &&
        form.dateRange[1]
      ) {
        const start = new Date(form.dateRange[0]);
        const end = new Date(form.dateRange[1]);
        form.startDate = start.toISOString().split("T")[0];
        form.endDate = end.toISOString().split("T")[0];
      if (isNaN(start.getTime()) || isNaN(end.getTime())) {
        console.warn('无效的日期格式')
        return
          console.warn("无效的日期格式");
          return;
      }
      const diffTime = Math.abs(end - start)
      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1
      form.days = diffDays
        const diffTime = Math.abs(end - start);
        const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
        form.days = diffDays;
    }
  } catch (error) {
    console.error('计算天数失败:', error)
      console.error("计算天数失败:", error);
  }
}
  };
// 验证时间格式
// const validateTime = (time) => {
@@ -523,79 +682,79 @@
// }
// 验证时间字段
const validateTimeField = (fieldName) => {
  const validateTimeField = fieldName => {
  try {
    const value = form[fieldName]
    if (value && typeof value === 'object' && value.hour !== undefined) {
      const value = form[fieldName];
      if (value && typeof value === "object" && value.hour !== undefined) {
      // 如果是时间对象,转换为字符串格式
      const hours = value.hour.toString().padStart(2, '0')
      const minutes = value.minute.toString().padStart(2, '0')
      form[fieldName] = `${hours}:${minutes}`
        const hours = value.hour.toString().padStart(2, "0");
        const minutes = value.minute.toString().padStart(2, "0");
        form[fieldName] = `${hours}:${minutes}`;
    }
  } catch (error) {
    console.error(`验证时间字段 ${fieldName} 失败:`, error)
    form[fieldName] = ''
      console.error(`验证时间字段 ${fieldName} 失败:`, error);
      form[fieldName] = "";
  }
}
  };
// 打开弹窗
const openDialog = (type, action, row = null) => {
  try {
    currentType.value = type
    currentAction.value = action
      currentType.value = type;
      currentAction.value = action;
    if (action === 'add') {
      dialogTitle.value = `新增${getTypeName(type)}`
      currentEditId.value = ''
      resetForm()
    } else if (action === 'edit' && row) {
      dialogTitle.value = `编辑${getTypeName(type)}`
      currentEditId.value = row.id
      fillForm(row)
      if (action === "add") {
        dialogTitle.value = `新增${getTypeName(type)}`;
        currentEditId.value = "";
        resetForm();
      } else if (action === "edit" && row) {
        dialogTitle.value = `编辑${getTypeName(type)}`;
        currentEditId.value = row.id;
        fillForm(row);
    }
    dialogVisible.value = true
      dialogVisible.value = true;
  } catch (error) {
    console.error('打开弹窗失败:', error)
    ElMessage.error('打开弹窗失败,请重试')
      console.error("打开弹窗失败:", error);
      ElMessage.error("打开弹窗失败,请重试");
  }
}
  };
const getTypeName = (type) => {
  const getTypeName = type => {
  const nameMap = {
    holiday: '假期',
    annual: '年假规则',
    overtime: '加班规则',
    worktime: '时间段'
  }
  return nameMap[type] || ''
}
      holiday: "假期",
      annual: "年假规则",
      overtime: "加班规则",
      worktime: "时间段",
    };
    return nameMap[type] || "";
  };
const resetForm = () => {
  Object.assign(form, {
    name: '',
    type: '',
      name: "",
      type: "",
    dateRange: [],
    startDate: '',
    endDate: '',
      startDate: "",
      endDate: "",
    days: 0,
    employeeType: '',
    workYears: '',
      employeeType: "",
      workYears: "",
    annualDays: 0,
    maxCarryOver: 0,
    startTime: '',
    endTime: '',
    workStartTime: '',
    workEndTime: '',
      startTime: "",
      endTime: "",
      workStartTime: "",
      workEndTime: "",
    rate: 1.5,
    flexibleStart: false,
    flexibleMinutes: 30,
    status: 'active'
  })
}
      status: "active",
    });
  };
const fillForm = (row) => {
  if (currentType.value === 'holiday') {
  const fillForm = row => {
    if (currentType.value === "holiday") {
    Object.assign(form, {
      name: row.name,
      type: row.type,
@@ -603,201 +762,214 @@
      startDate: row.startDate,
      endDate: row.endDate,
      days: row.days,
      status: row.status
    })
  } else if (currentType.value === 'annual') {
        status: row.status,
      });
    } else if (currentType.value === "annual") {
    Object.assign(form, {
      employeeType: row.employeeType,
      workYears: row.workYears,
      annualDays: row.annualDays,
      maxCarryOver: row.maxCarryOver,
      status: row.status
    })
  } else if (currentType.value === 'overtime') {
        status: row.status,
      });
    } else if (currentType.value === "overtime") {
    Object.assign(form, {
      name: row.name,
      type: row.type,
      startTime: row.startTime || '',
      endTime: row.endTime || '',
        startTime: row.startTime || "",
        endTime: row.endTime || "",
      rate: row.rate,
      status: row.status
    })
  } else if (currentType.value === 'worktime') {
        status: row.status,
      });
    } else if (currentType.value === "worktime") {
    Object.assign(form, {
      name: row.name,
      workStartTime: row.startTime || '',
      workEndTime: row.endTime || '',
        workStartTime: row.startTime || "",
        workEndTime: row.endTime || "",
      flexibleStart: row.flexibleStart,
      flexibleMinutes: row.flexibleMinutes,
      status: row.status
    })
        status: row.status,
      });
  }
}
  };
// 提交表单
const submitForm = async () => {
  try {
    if (!formRef.value) {
      ElMessage.error('表单引用不存在')
      return
        ElMessage.error("表单引用不存在");
        return;
    }
    await formRef.value.validate()
      await formRef.value.validate();
    if (currentAction.value === 'add') {
      addItem()
    } else if (currentAction.value === 'edit') {
      editItem()
      if (currentAction.value === "add") {
        addItem();
      } else if (currentAction.value === "edit") {
        editItem();
    }
    dialogVisible.value = false
    ElMessage.success('操作成功')
      dialogVisible.value = false;
      ElMessage.success("操作成功");
  } catch (error) {
    console.error('表单验证失败:', error)
    ElMessage.error('表单验证失败,请检查输入')
      console.error("表单验证失败:", error);
      ElMessage.error("表单验证失败,请检查输入");
  }
}
  };
const addItem = () => {
  if (currentType.value === 'holiday') {
    if (currentType.value === "holiday") {
    const params = {
      name: form.name,
      type: form.type,
      startDate: form.startDate,
      endDate: form.endDate,
      days: form.days,
      status: form.status
    }
    addHolidaySettings(params).then(res => {
        status: form.status,
      };
      addHolidaySettings(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("添加成功");
        // dialogVisible.value = false;
        getHolidaySettingsList()
            getHolidaySettingsList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
  } else if (currentType.value === 'annual') {
        .catch(err => {
          ElMessage.error(err.msg);
        });
    } else if (currentType.value === "annual") {
    // annualData.value.push(newItem)
    const params = {
      employeeType: form.employeeType,
      workYears: form.workYears,
      annualDays: form.annualDays,
      maxCarryOver: form.maxCarryOver,
      status: form.status
    }
    addAnnualLeaveSetting(params).then(res => {
        status: form.status,
      };
      addAnnualLeaveSetting(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("添加成功");
        // dialogVisible.value = false;
        getAnnualLeaveSettingList()
            getAnnualLeaveSettingList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
  } else if (currentType.value === 'overtime') {
        .catch(err => {
          ElMessage.error(err.msg);
        });
    } else if (currentType.value === "overtime") {
    const params = {
      name: form.name,
      type: form.type,
      startTime: form.startTime || '',
      endTime: form.endTime || '',
        startTime: form.startTime || "",
        endTime: form.endTime || "",
      rate: form.rate,
      status: form.status
    }
    addOvertimeSetting(params).then(res => {
        status: form.status,
      };
      addOvertimeSetting(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("添加成功");
        // dialogVisible.value = false;
        getOvertimeSettingList()
            getOvertimeSettingList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // newItem.startTime = form.startTime || ''
    // newItem.endTime = form.endTime || ''
    // overtimeData.value.push(newItem)
  } else if (currentType.value === 'worktime') {
    } else if (currentType.value === "worktime") {
    const params = {
      name: form.name,
      startTime: form.workStartTime || '',
      endTime: form.workEndTime || '',
        startTime: form.workStartTime || "",
        endTime: form.workEndTime || "",
      flexibleStart: form.flexibleStart,
      flexibleMinutes: form.flexibleMinutes,
      status: form.status
    }
    addWorkingHoursSetting(params).then(res => {
        status: form.status,
      };
      addWorkingHoursSetting(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("添加成功");
        getWorkingHoursSettingList()
            getWorkingHoursSettingList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // newItem.startTime = form.workStartTime || ''
    // newItem.endTime = form.workEndTime || ''
    // worktimeData.value.push(newItem)
  }
}
  };
const editItem = () => {
  let dataArray
  let index
    let dataArray;
    let index;
  if (currentType.value === 'holiday') {
    if (currentType.value === "holiday") {
    const params = {
      id: currentEditId.value,
      name: form.name,
      type: form.type,
      startDate: form.dateRange[0].toISOString().split('T')[0],
      endDate: form.dateRange[1].toISOString().split('T')[0],
        startDate: form.dateRange[0].toISOString().split("T")[0],
        endDate: form.dateRange[1].toISOString().split("T")[0],
      days: form.days,
      status: form.status
    }
    updateHolidaySettings(params).then(res => {
        status: form.status,
      };
      updateHolidaySettings(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("更新成功");
        // dialogVisible.value = false;
        getHolidaySettingsList()
            getHolidaySettingsList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
  } else if (currentType.value === 'annual') {
        .catch(err => {
          ElMessage.error(err.msg);
        });
    } else if (currentType.value === "annual") {
    const params = {
      id: currentEditId.value,
      employeeType: form.employeeType,
      workYears: form.workYears,
      annualDays: form.annualDays,
      maxCarryOver: form.maxCarryOver,
      status: form.status
    }
    updateAnnualLeaveSetting(params).then(res => {
        status: form.status,
      };
      updateAnnualLeaveSetting(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("更新成功");
        getAnnualLeaveSettingList()
            getAnnualLeaveSettingList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
  } else if (currentType.value === 'overtime') {
        .catch(err => {
          ElMessage.error(err.msg);
        });
    } else if (currentType.value === "overtime") {
    const params = {
      id: currentEditId.value,
      name: form.name,
      type: form.type,
      startTime: form.startTime || '',
      endTime: form.endTime || '',
        startTime: form.startTime || "",
        endTime: form.endTime || "",
      rate: form.rate,
      status: form.status
    }
    updateOvertimeSetting(params).then(res => {
        status: form.status,
      };
      updateOvertimeSetting(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("更新成功");
        getOvertimeSettingList()
            getOvertimeSettingList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // dataArray = overtimeData.value
    // index = dataArray.findIndex(item => item.id === currentEditId.value)
@@ -812,24 +984,26 @@
    //     status: form.status
    //   }
    // }
  } else if (currentType.value === 'worktime') {
    } else if (currentType.value === "worktime") {
    const params = {
      id: currentEditId.value,
      name: form.name,
      startTime: form.workStartTime || '',
      endTime: form.workEndTime || '',
        startTime: form.workStartTime || "",
        endTime: form.workEndTime || "",
      flexibleStart: form.flexibleStart,
      flexibleMinutes: form.flexibleMinutes,
      status: form.status
    }
    updateWorkingHoursSetting(params).then(res => {
        status: form.status,
      };
      updateWorkingHoursSetting(params)
        .then(res => {
      if(res.code == 200){
        ElMessage.success("更新成功");
        getWorkingHoursSettingList()
            getWorkingHoursSettingList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // dataArray = worktimeData.value
    // index = dataArray.findIndex(item => item.id === currentEditId.value)
    // if (index > -1) {
@@ -844,311 +1018,316 @@
    //   }
    // }
  }
}
  };
// 打卡记录过滤功能
const filterAttendanceData = () => {
  let filtered = attendanceData.value
    let filtered = attendanceData.value;
  
  // 按日期过滤
  if (attendanceDate.value) {
    filtered = filtered.filter(item => item.date === attendanceDate.value)
      filtered = filtered.filter(item => item.date === attendanceDate.value);
  }
  
  // 按状态过滤
  if (attendanceStatus.value) {
    filtered = filtered.filter(item => item.status === attendanceStatus.value)
      filtered = filtered.filter(item => item.status === attendanceStatus.value);
  }
  
  filteredAttendanceData.value = filtered
}
    filteredAttendanceData.value = filtered;
  };
// 导出打卡记录
const exportAttendance = () => {
  ElMessage.success('导出功能开发中...')
}
    ElMessage.success("导出功能开发中...");
  };
// 初始化打卡记录假数据
const initAttendanceData = () => {
  const mockData = [
    {
      id: 1,
      employeeName: '陈志强',
      department: '技术部',
      date: '2025-08-15',
      clockInTime: '09:00:00',
      clockOutTime: '18:00:00',
      workHours: '8.0h',
      status: 'normal',
      location: '公司总部',
      remark: ''
        employeeName: "陈志强",
        department: "技术部",
        date: "2025-08-15",
        clockInTime: "09:00:00",
        clockOutTime: "18:00:00",
        workHours: "8.0h",
        status: "normal",
        location: "公司总部",
        remark: "",
    },
    {
      id: 2,
      employeeName: '李雪梅',
      department: '市场部',
      date: '2025-08-16',
       clockInTime: '08:58:00',
       clockOutTime: '18:05:00',
       workHours: '8.12h',
       status: 'normal',
       location: '公司总部',
       remark: ''
        employeeName: "李雪梅",
        department: "市场部",
        date: "2025-08-16",
        clockInTime: "08:58:00",
        clockOutTime: "18:05:00",
        workHours: "8.12h",
        status: "normal",
        location: "公司总部",
        remark: "",
     },
     {
       id: 3,
       employeeName: '王建华',
       department: '人事部',
       date: '2025-08-16',
       clockInTime: '09:02:00',
       clockOutTime: '18:00:00',
       workHours: '7.97h',
       status: 'normal',
       location: '公司总部',
       remark: ''
        employeeName: "王建华",
        department: "人事部",
        date: "2025-08-16",
        clockInTime: "09:02:00",
        clockOutTime: "18:00:00",
        workHours: "7.97h",
        status: "normal",
        location: "公司总部",
        remark: "",
     },
     {
       id: 4,
       employeeName: '赵晓丽',
       department: '财务部',
       date: '2025-09-02',
       clockInTime: '08:55:00',
       clockOutTime: '18:10:00',
       workHours: '8.25h',
       status: 'normal',
       location: '公司总部',
       remark: ''
        employeeName: "赵晓丽",
        department: "财务部",
        date: "2025-09-02",
        clockInTime: "08:55:00",
        clockOutTime: "18:10:00",
        workHours: "8.25h",
        status: "normal",
        location: "公司总部",
        remark: "",
     },
     {
       id: 5,
       employeeName: '张国庆',
       department: '技术部',
       date: '2025-09-02',
       clockInTime: '09:00:00',
       clockOutTime: '18:30:00',
       workHours: '8.5h',
       status: 'normal',
       location: '公司总部',
       remark: '加班'
        employeeName: "张国庆",
        department: "技术部",
        date: "2025-09-02",
        clockInTime: "09:00:00",
        clockOutTime: "18:30:00",
        workHours: "8.5h",
        status: "normal",
        location: "公司总部",
        remark: "加班",
     },
     {
       id: 6,
       employeeName: '刘明辉',
       department: '运营部',
       date: '2025-09-03',
       clockInTime: '09:05:00',
       clockOutTime: '18:00:00',
       workHours: '7.92h',
       status: 'normal',
       location: '公司总部',
       remark: ''
        employeeName: "刘明辉",
        department: "运营部",
        date: "2025-09-03",
        clockInTime: "09:05:00",
        clockOutTime: "18:00:00",
        workHours: "7.92h",
        status: "normal",
        location: "公司总部",
        remark: "",
     },
     {
       id: 7,
       employeeName: '孙丽华',
       department: '设计部',
       date: '2025-09-03',
       clockInTime: '08:59:00',
       clockOutTime: '18:02:00',
       workHours: '8.05h',
       status: 'normal',
       location: '公司总部',
       remark: ''
        employeeName: "孙丽华",
        department: "设计部",
        date: "2025-09-03",
        clockInTime: "08:59:00",
        clockOutTime: "18:02:00",
        workHours: "8.05h",
        status: "normal",
        location: "公司总部",
        remark: "",
     },
     {
       id: 8,
       employeeName: '周建军',
       department: '销售部',
       date: '2025-09-04',
       clockInTime: '09:15:00',
       clockOutTime: '18:00:00',
       workHours: '7.75h',
       status: 'late',
       location: '公司总部',
       remark: '交通堵塞'
        employeeName: "周建军",
        department: "销售部",
        date: "2025-09-04",
        clockInTime: "09:15:00",
        clockOutTime: "18:00:00",
        workHours: "7.75h",
        status: "late",
        location: "公司总部",
        remark: "交通堵塞",
     },
     {
       id: 9,
       employeeName: '吴小芳',
       department: '客服部',
       date: '2025-09-04',
       clockInTime: '09:01:00',
       clockOutTime: '18:00:00',
       workHours: '7.98h',
       status: 'normal',
       location: '公司总部',
       remark: ''
        employeeName: "吴小芳",
        department: "客服部",
        date: "2025-09-04",
        clockInTime: "09:01:00",
        clockOutTime: "18:00:00",
        workHours: "7.98h",
        status: "normal",
        location: "公司总部",
        remark: "",
     },
     {
       id: 10,
       employeeName: '马文杰',
       department: '技术部',
       date: '2025-09-05',
       clockInTime: '08:57:00',
       clockOutTime: '17:30:00',
       workHours: '7.55h',
       status: 'early',
       location: '公司总部',
       remark: '有急事提前离开'
        employeeName: "马文杰",
        department: "技术部",
        date: "2025-09-05",
        clockInTime: "08:57:00",
        clockOutTime: "17:30:00",
        workHours: "7.55h",
        status: "early",
        location: "公司总部",
        remark: "有急事提前离开",
     },
     {
       id: 11,
       employeeName: '林晓东',
       department: '行政部',
       date: '2025-09-05',
       clockInTime: '09:03:00',
       clockOutTime: '18:08:00',
       workHours: '8.08h',
       status: 'normal',
       location: '公司总部',
       remark: ''
        employeeName: "林晓东",
        department: "行政部",
        date: "2025-09-05",
        clockInTime: "09:03:00",
        clockOutTime: "18:08:00",
        workHours: "8.08h",
        status: "normal",
        location: "公司总部",
        remark: "",
     },
     {
       id: 12,
       employeeName: '黄美玲',
       department: '财务部',
       date: '2025-09-06',
       clockInTime: '',
       clockOutTime: '',
       workHours: '0h',
       status: 'absent',
       location: '',
       remark: '请病假'
        employeeName: "黄美玲",
        department: "财务部",
        date: "2025-09-06",
        clockInTime: "",
        clockOutTime: "",
        workHours: "0h",
        status: "absent",
        location: "",
        remark: "请病假",
     },
    {
      id: 13,
      employeeName: '郑海涛',
      department: '市场部',
      date: '2025-08-14',
      clockInTime: '09:00:00',
      clockOutTime: '18:00:00',
      workHours: '8.0h',
      status: 'normal',
      location: '公司总部',
      remark: ''
        employeeName: "郑海涛",
        department: "市场部",
        date: "2025-08-14",
        clockInTime: "09:00:00",
        clockOutTime: "18:00:00",
        workHours: "8.0h",
        status: "normal",
        location: "公司总部",
        remark: "",
    },
    {
      id: 14,
      employeeName: '谢丽娟',
      department: '人事部',
      date: '2025-08-20',
      clockInTime: '08:58:00',
      clockOutTime: '18:03:00',
      workHours: '8.08h',
      status: 'normal',
      location: '公司总部',
      remark: ''
        employeeName: "谢丽娟",
        department: "人事部",
        date: "2025-08-20",
        clockInTime: "08:58:00",
        clockOutTime: "18:03:00",
        workHours: "8.08h",
        status: "normal",
        location: "公司总部",
        remark: "",
    },
    {
      id: 15,
      employeeName: '何志伟',
      department: '技术部',
      date: '2025-08-21',
      clockInTime: '09:10:00',
      clockOutTime: '18:00:00',
      workHours: '7.83h',
      status: 'late',
      location: '公司总部',
      remark: ''
        employeeName: "何志伟",
        department: "技术部",
        date: "2025-08-21",
        clockInTime: "09:10:00",
        clockOutTime: "18:00:00",
        workHours: "7.83h",
        status: "late",
        location: "公司总部",
        remark: "",
    },
    {
      id: 16,
      employeeName: '许雅芳',
      department: '设计部',
      date: '2025-08-22',
      clockInTime: '09:01:00',
      clockOutTime: '18:00:00',
      workHours: '7.98h',
      status: 'normal',
      location: '公司总部',
      remark: ''
        employeeName: "许雅芳",
        department: "设计部",
        date: "2025-08-22",
        clockInTime: "09:01:00",
        clockOutTime: "18:00:00",
        workHours: "7.98h",
        status: "normal",
        location: "公司总部",
        remark: "",
    },
    {
      id: 17,
      employeeName: '邓建平',
      department: '运营部',
      date: '2025-09-10',
      clockInTime: '08:59:00',
      clockOutTime: '18:05:00',
      workHours: '8.1h',
      status: 'normal',
      location: '公司总部',
      remark: ''
        employeeName: "邓建平",
        department: "运营部",
        date: "2025-09-10",
        clockInTime: "08:59:00",
        clockOutTime: "18:05:00",
        workHours: "8.1h",
        status: "normal",
        location: "公司总部",
        remark: "",
    },
    {
      id: 18,
      employeeName: '曾小红',
      department: '客服部',
      date: '2025-09-11',
      clockInTime: '09:02:00',
      clockOutTime: '18:00:00',
      workHours: '7.97h',
      status: 'normal',
      location: '公司总部',
      remark: ''
    }
  ]
        employeeName: "曾小红",
        department: "客服部",
        date: "2025-09-11",
        clockInTime: "09:02:00",
        clockOutTime: "18:00:00",
        workHours: "7.97h",
        status: "normal",
        location: "公司总部",
        remark: "",
      },
    ];
  
  attendanceData.value = mockData
  filteredAttendanceData.value = mockData
}
    attendanceData.value = mockData;
    filteredAttendanceData.value = mockData;
  };
// 删除项目
const deleteItem = (type, row) => {
  ElMessageBox.confirm('确定要删除这个项目吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
    ElMessageBox.confirm("确定要删除这个项目吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    let ids = [];
    let dataArray
    if (type === 'holiday') {
      ids.push(row.id)
      delHolidaySettings(ids).then(res => {
      let dataArray;
      if (type === "holiday") {
        ids.push(row.id);
        delHolidaySettings(ids)
          .then(res => {
        if(res.code == 200){
          ElMessage.success("删除成功");
          ids = []
          getHolidaySettingsList()
              ids = [];
              getHolidaySettingsList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
    }
    else if (type === 'annual') {
      ids.push(row.id)
      delAnnualLeaveSetting(ids).then(res => {
          .catch(err => {
            ElMessage.error(err.msg);
          });
      } else if (type === "annual") {
        ids.push(row.id);
        delAnnualLeaveSetting(ids)
          .then(res => {
        if(res.code == 200){
          ElMessage.success("删除成功");
          ids = []
          getAnnualLeaveSettingList()
              ids = [];
              getAnnualLeaveSettingList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
    }
    else if (type === 'overtime') {
      ids.push(row.id)
      delOvertimeSetting(ids).then(res => {
          .catch(err => {
            ElMessage.error(err.msg);
          });
      } else if (type === "overtime") {
        ids.push(row.id);
        delOvertimeSetting(ids)
          .then(res => {
        if(res.code == 200){
          ElMessage.success("删除成功");
          ids = []
          getOvertimeSettingList()
              ids = [];
              getOvertimeSettingList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
    }
    else if (type === 'worktime') {
      ids.push(row.id)
      delWorkingHoursSetting(ids).then(res => {
          .catch(err => {
            ElMessage.error(err.msg);
          });
      } else if (type === "worktime") {
        ids.push(row.id);
        delWorkingHoursSetting(ids)
          .then(res => {
        if(res.code == 200){
          ElMessage.success("删除成功");
          ids = []
          getWorkingHoursSettingList()
              ids = [];
              getWorkingHoursSettingList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    }
    // const index = dataArray.findIndex(item => item.id === row.id)
@@ -1156,69 +1335,67 @@
    //   dataArray.splice(index, 1)
    //   ElMessage.success('删除成功')
    // }
  })
}
    });
  };
// 获取假期设置列表
const getHolidaySettingsList = () => {
  // tableLoading.value = true;
  listHolidaySettings({...page.value})
  .then(res => {
    // tableLoading.value = false;
    holidayData.value = res.data.records
        holidayData.value = res.data.records;
    page.total = res.data.total;
  }).catch(err => {
    // tableLoading.value = false;
  })
      .catch(err => {
        // tableLoading.value = false;
      });
};
// 获取年假规则列表
const getAnnualLeaveSettingList = () => {
  listAnnualLeaveSettingList({...page.value})
  .then(res => {
    // console.log(res.data)
    annualData.value = res.data.records
        annualData.value = res.data.records;
    page.total = res.data.total;
  }).catch(err => {
  })
      .catch(err => {});
};
// 获取加班规则列表
const getOvertimeSettingList = () => {
  listOvertimeSettingList({...page.value})
  .then(res => {
    // console.log(res.data)
    overtimeData.value = res.data.records
        overtimeData.value = res.data.records;
    page.total = res.data.total;
  }).catch(err => {
  })
      .catch(err => {});
};
// 获取工作时间规则列表
const getWorkingHoursSettingList = () => {
  listWorkingHoursSettingList({...page.value})
  .then(res => {
    // console.log(res.data)
    worktimeData.value = res.data.records
        worktimeData.value = res.data.records;
    page.total = res.data.total;
  }).catch(err => {
  })
      .catch(err => {});
};
onMounted(() => {
  getHolidaySettingsList()
  getAnnualLeaveSettingList()
  getOvertimeSettingList()
  getWorkingHoursSettingList()
  initAttendanceData()
  console.log('考勤管理页面加载完成')
})
    getHolidaySettingsList();
    getAnnualLeaveSettingList();
    getOvertimeSettingList();
    getWorkingHoursSettingList();
    initAttendanceData();
    console.log("考勤管理页面加载完成");
  });
onUnmounted(() => {
  // 清理工作
  dialogVisible.value = false
  currentType.value = ''
  currentAction.value = ''
  currentEditId.value = ''
})
    dialogVisible.value = false;
    currentType.value = "";
    currentAction.value = "";
    currentEditId.value = "";
  });
</script>
<style scoped>
src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -3,36 +3,46 @@
    <div class="search_form">
      <div>
        <span class="search_title">知识标题:</span>
        <el-input
          v-model="searchForm.title"
        <el-input v-model="searchForm.title"
          style="width: 240px"
          placeholder="请输入知识标题搜索"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
        />
                  :prefix-icon="Search" />
        <span class="search_title ml10">知识类型:</span>
        <el-select v-model="searchForm.type" clearable @change="handleQuery" style="width: 240px">
          <el-option label="合同特批" :value="'contract'" />
          <el-option label="审批案例" :value="'approval'" />
          <el-option label="解决方案" :value="'solution'" />
          <el-option label="经验总结" :value="'experience'" />
          <el-option label="操作指南" :value="'guide'" />
        <el-select v-model="searchForm.type"
                   clearable
                   @change="handleQuery"
                   style="width: 240px">
          <el-option label="合同特批"
                     :value="'contract'" />
          <el-option label="审批案例"
                     :value="'approval'" />
          <el-option label="解决方案"
                     :value="'solution'" />
          <el-option label="经验总结"
                     :value="'experience'" />
          <el-option label="操作指南"
                     :value="'guide'" />
        </el-select>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">
          搜索
        </el-button>
      </div>
      <div>
        <el-button @click="handleExport" style="margin-right: 10px">导出</el-button>
        <el-button type="primary" @click="openForm('add')">新增知识</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
        <el-button @click="handleExport"
                   style="margin-right: 10px">导出</el-button>
        <el-button type="primary"
                   @click="openForm('add')">新增知识</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
        rowKey="id"
      <PIMTable rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
@@ -40,107 +50,126 @@
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="page.total"
      ></PIMTable>
                :total="page.total"></PIMTable>
    </div>
    <!-- 新增/编辑知识弹窗 -->
    <el-dialog
      v-model="dialogVisible"
    <el-dialog v-model="dialogVisible"
      :title="dialogTitle"
      width="800px"
      :close-on-click-modal="false"
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
               :close-on-click-modal="false">
      <el-form ref="formRef"
               :model="form"
               :rules="rules"
               label-width="120px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="知识标题" prop="title">
              <el-input v-model="form.title" placeholder="请输入知识标题" />
            <el-form-item label="知识标题"
                          prop="title">
              <el-input v-model="form.title"
                        placeholder="请输入知识标题" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="知识类型" prop="type">
              <el-select v-model="form.type" placeholder="请选择知识类型" style="width: 100%">
                <el-option label="合同特批" value="contract" />
                <el-option label="审批案例" value="approval" />
                <el-option label="解决方案" value="solution" />
                <el-option label="经验总结" value="experience" />
                <el-option label="操作指南" value="guide" />
            <el-form-item label="知识类型"
                          prop="type">
              <el-select v-model="form.type"
                         placeholder="请选择知识类型"
                         style="width: 100%">
                <el-option label="合同特批"
                           value="contract" />
                <el-option label="审批案例"
                           value="approval" />
                <el-option label="解决方案"
                           value="solution" />
                <el-option label="经验总结"
                           value="experience" />
                <el-option label="操作指南"
                           value="guide" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="适用场景" prop="scenario">
              <el-input v-model="form.scenario" placeholder="请输入适用场景" />
            <el-form-item label="适用场景"
                          prop="scenario">
              <el-input v-model="form.scenario"
                        placeholder="请输入适用场景" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="解决效率" prop="efficiency">
              <el-select v-model="form.efficiency" placeholder="请选择解决效率" style="width: 100%">
                <el-option label="显著提升" value="high" />
                <el-option label="一般提升" value="medium" />
                <el-option label="轻微提升" value="low" />
            <el-form-item label="解决效率"
                          prop="efficiency">
              <el-select v-model="form.efficiency"
                         placeholder="请选择解决效率"
                         style="width: 100%">
                <el-option label="显著提升"
                           value="high" />
                <el-option label="一般提升"
                           value="medium" />
                <el-option label="轻微提升"
                           value="low" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="问题描述" prop="problem">
          <el-input
            v-model="form.problem"
        <el-form-item label="问题描述"
                      prop="problem">
          <el-input v-model="form.problem"
            type="textarea"
            :rows="3"
            placeholder="请描述遇到的问题"
          />
                    placeholder="请描述遇到的问题" />
        </el-form-item>
        <el-form-item label="解决方案" prop="solution">
          <el-input
            v-model="form.solution"
        <el-form-item label="解决方案"
                      prop="solution">
          <el-input v-model="form.solution"
            type="textarea"
            :rows="4"
            placeholder="请详细描述解决方案"
          />
                    placeholder="请详细描述解决方案" />
        </el-form-item>
        <el-form-item label="关键要点" prop="keyPoints">
          <el-input
            v-model="form.keyPoints"
        <el-form-item label="关键要点"
                      prop="keyPoints">
          <el-input v-model="form.keyPoints"
            type="textarea"
            :rows="3"
            placeholder="请输入关键要点,用逗号分隔"
          />
                    placeholder="请输入关键要点,用逗号分隔" />
        </el-form-item>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="创建人" prop="creator">
              <el-input v-model="form.creator" placeholder="请输入创建人" />
            <el-form-item label="创建人"
                          prop="creator">
              <el-input v-model="form.creator"
                        placeholder="请输入创建人" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="使用次数" prop="usageCount">
              <el-input-number v-model="form.usageCount" :min="0" style="width: 100%" />
            <el-form-item label="使用次数"
                          prop="usageCount">
              <el-input-number v-model="form.usageCount"
                               :min="0"
                               style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 查看知识详情弹窗 -->
    <el-dialog
      v-model="viewDialogVisible"
    <el-dialog v-model="viewDialogVisible"
      title="知识详情"
      width="900px"
      :close-on-click-modal="false"
    >
               :close-on-click-modal="false">
      <div class="knowledge-detail">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="知识标题" :span="2">
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="知识标题"
                                :span="2">
            <span class="detail-title">{{ currentKnowledge.title }}</span>
          </el-descriptions-item>
          <el-descriptions-item label="知识类型">
@@ -166,31 +195,25 @@
            {{ currentKnowledge.createTime }}
          </el-descriptions-item>
        </el-descriptions>
        <div class="detail-section">
          <h4>问题描述</h4>
          <div class="detail-content">{{ currentKnowledge.problem }}</div>
        </div>
        <div class="detail-section">
          <h4>解决方案</h4>
          <div class="detail-content">{{ currentKnowledge.solution }}</div>
        </div>
        <div class="detail-section">
          <h4>关键要点</h4>
          <div class="key-points">
            <el-tag
              v-for="(point, index) in currentKnowledge.keyPoints.split(',')"
            <el-tag v-for="(point, index) in currentKnowledge.keyPoints.split(',')"
              :key="index"
              type="success"
              style="margin-right: 8px; margin-bottom: 8px;"
            >
                    style="margin-right: 8px; margin-bottom: 8px;">
              {{ point.trim() }}
            </el-tag>
          </div>
        </div>
        <div class="detail-section">
          <h4>使用统计</h4>
          <div class="usage-stats">
@@ -217,11 +240,11 @@
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="copyKnowledge">复制知识</el-button>
          <el-button @click="viewDialogVisible = false">关闭</el-button>
          <el-button type="primary" @click="copyKnowledge">复制知识</el-button>
          <!-- <el-button type="success" @click="markAsFavorite">收藏@</el-button> -->
        </span>
      </template>
@@ -234,22 +257,21 @@
import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
  import {
    listKnowledgeBase,
    delKnowledgeBase,
    addKnowledgeBase,
    updateKnowledgeBase,
  } from "@/api/collaborativeApproval/knowledgeBase.js";
// 表单验证规则
const rules = {
  title: [
    { required: true, message: "请输入知识标题", trigger: "blur" }
  ],
  type: [
    { required: true, message: "请选择知识类型", trigger: "change" }
  ],
  problem: [
    { required: true, message: "请描述遇到的问题", trigger: "blur" }
  ],
    title: [{ required: true, message: "请输入知识标题", trigger: "blur" }],
    type: [{ required: true, message: "请选择知识类型", trigger: "change" }],
    problem: [{ required: true, message: "请描述遇到的问题", trigger: "blur" }],
  solution: [
    { required: true, message: "请详细描述解决方案", trigger: "blur" }
  ]
      { required: true, message: "请详细描述解决方案", trigger: "blur" },
    ],
};
// 响应式数据
@@ -275,13 +297,13 @@
    solution: "",
    keyPoints: "",
    creator: "",
    usageCount: 0
      usageCount: 0,
  },
  dialogVisible: false,
  dialogTitle: "",
  dialogType: "add",
  viewDialogVisible: false,
  currentKnowledge: {}
    currentKnowledge: {},
});
const {
@@ -295,7 +317,7 @@
  dialogTitle,
  dialogType,
  viewDialogVisible,
  currentKnowledge
    currentKnowledge,
} = toRefs(data);
// 表单引用
@@ -312,26 +334,26 @@
    label: "知识类型",
    prop: "type",
    dataType: "tag",
    formatData: (params) => {
      formatData: params => {
      const typeMap = {
        contract: "合同特批",
        approval: "审批案例",
        solution: "解决方案",
        experience: "经验总结",
        guide: "操作指南"
          guide: "操作指南",
      };
      return typeMap[params] || params;
    },
    formatType: (params) => {
      formatType: params => {
      const typeMap = {
        contract: "success",
        approval: "warning",
        solution: "primary",
        experience: "info",
        guide: "danger"
          guide: "danger",
      };
      return typeMap[params] || "info";
    }
      },
  },
  {
    label: "适用场景",
@@ -343,28 +365,28 @@
    label: "解决效率",
    prop: "efficiency",
    dataType: "tag",
    formatData: (params) => {
      formatData: params => {
      const efficiencyMap = {
        high: "显著提升",
        medium: "一般提升",
        low: "轻微提升"
          low: "轻微提升",
      };
      return efficiencyMap[params] || params;
    },
    formatType: (params) => {
      formatType: params => {
      const typeMap = {
        high: "success",
        medium: "warning",
        low: "info"
          low: "info",
      };
      return typeMap[params] || "info";
    }
      },
  },
  {
    label: "使用次数",
    prop: "usageCount",
    width: 100,
    align: "center"
      align: "center",
  },
  {
    label: "创建人",
@@ -386,19 +408,19 @@
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          clickFun: row => {
          openForm("edit", row);
        }
          },
      },
      {
        name: "查看",
        type: "text",
        clickFun: (row) => {
          clickFun: row => {
          viewKnowledge(row);
        }
      }
    ]
  }
          },
        },
      ],
    },
]);
// 模拟数据
@@ -453,7 +475,7 @@
  "{type}标准化操作流程",
  "{scenario}问题解决方案",
  "{type}最佳实践总结",
  "{scenario}效率提升方案"
    "{scenario}效率提升方案",
];
// 知识类型配置
@@ -462,24 +484,35 @@
  { type: "approval", label: "审批案例", efficiency: "medium" },
  { type: "solution", label: "解决方案", efficiency: "high" },
  { type: "experience", label: "经验总结", efficiency: "medium" },
  { type: "guide", label: "操作指南", efficiency: "low" }
    { type: "guide", label: "操作指南", efficiency: "low" },
];
// 场景列表
const scenarios = ["大额合同审批", "跨部门协作", "紧急采购", "特殊申请", "流程优化", "问题处理", "标准化建设", "效率提升"];
  const scenarios = [
    "大额合同审批",
    "跨部门协作",
    "紧急采购",
    "特殊申请",
    "流程优化",
    "问题处理",
    "标准化建设",
    "效率提升",
  ];
// 自动生成新数据
const generateNewData = () => {
  const newId = (mockData.length + 1).toString();
  const now = new Date();
  const randomType = knowledgeTypes[Math.floor(Math.random() * knowledgeTypes.length)];
  const randomScenario = scenarios[Math.floor(Math.random() * scenarios.length)];
    const randomType =
      knowledgeTypes[Math.floor(Math.random() * knowledgeTypes.length)];
    const randomScenario =
      scenarios[Math.floor(Math.random() * scenarios.length)];
  // 生成随机标题
  let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)];
  title = title
    .replace('{type}', randomType.label)
    .replace('{scenario}', randomScenario);
      .replace("{type}", randomType.label)
      .replace("{scenario}", randomScenario);
  const newKnowledge = {
    id: newId,
@@ -490,9 +523,11 @@
    problem: `在${randomScenario}过程中遇到的问题描述...`,
    solution: `针对${randomScenario}的解决方案和操作步骤...`,
    keyPoints: "关键要点1,关键要点2,关键要点3,关键要点4",
    creator: ["张经理", "李主管", "王专员", "刘总监"][Math.floor(Math.random() * 4)],
      creator: ["张经理", "李主管", "王专员", "刘总监"][
        Math.floor(Math.random() * 4)
      ],
    usageCount: Math.floor(Math.random() * 20) + 1,
    createTime: now.toLocaleString()
      createTime: now.toLocaleString(),
  };
  // 添加到数据开头
@@ -531,22 +566,23 @@
  listKnowledgeBase({...page.value, ...searchForm.value})
  .then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
        tableData.value = res.data.records;
    page.total = res.data.total;
  }).catch(err => {
    tableLoading.value = false;
  })
      .catch(err => {
        tableLoading.value = false;
      });
};
// 分页处理
const pagination = (obj) => {
  const pagination = obj => {
  page.value.current = obj.page;
  page.value.size = obj.limit;
  handleQuery();
};
// 选择变化处理
const handleSelectionChange = (selection) => {
  const handleSelectionChange = selection => {
  selectedIds.value = selection.map(item => item.id);
};
@@ -565,7 +601,7 @@
      solution: "",
      keyPoints: "",
      creator: "",
      usageCount: 0
        usageCount: 0,
    });
  } else if (type === "edit" && row) {
    dialogTitle.value = "编辑知识";
@@ -579,78 +615,78 @@
      solution: row.solution,
      keyPoints: row.keyPoints,
      creator: row.creator,
      usageCount: row.usageCount
        usageCount: row.usageCount,
    });
  }
  dialogVisible.value = true;
};
// 查看知识详情
const viewKnowledge = (row) => {
  const viewKnowledge = row => {
  currentKnowledge.value = { ...row };
  viewDialogVisible.value = true;
};
// 获取类型标签类型
const getTypeTagType = (type) => {
  const getTypeTagType = type => {
  const typeMap = {
    contract: "success",
    approval: "warning",
    solution: "primary",
    experience: "info",
    guide: "danger"
      guide: "danger",
  };
  return typeMap[type] || "info";
};
// 获取类型标签文本
const getTypeLabel = (type) => {
  const getTypeLabel = type => {
  const typeMap = {
    contract: "合同特批",
    approval: "审批案例",
    solution: "解决方案",
    experience: "经验总结",
    guide: "操作指南"
      guide: "操作指南",
  };
  return typeMap[type] || type;
};
// 获取效率标签类型
const getEfficiencyTagType = (efficiency) => {
  const getEfficiencyTagType = efficiency => {
  const typeMap = {
    high: "success",
    medium: "warning",
    low: "info"
      low: "info",
  };
  return typeMap[efficiency] || "info";
};
// 获取效率标签文本
const getEfficiencyLabel = (efficiency) => {
  const getEfficiencyLabel = efficiency => {
  const efficiencyMap = {
    high: "显著提升",
    medium: "一般提升",
    low: "轻微提升"
      low: "轻微提升",
  };
  return efficiencyMap[efficiency] || efficiency;
};
// 获取效率提升百分比
const getEfficiencyScore = (efficiency) => {
  const getEfficiencyScore = efficiency => {
  const scoreMap = {
    high: 40,
    medium: 25,
    low: 15
      low: 15,
  };
  return scoreMap[efficiency] || 0;
};
// 获取平均节省时间
const getTimeSaved = (efficiency) => {
  const getTimeSaved = efficiency => {
  const timeMap = {
    high: "2-3天",
    medium: "1-2天",
    low: "0.5-1天"
      low: "0.5-1天",
  };
  return timeMap[efficiency] || "未知";
};
@@ -668,9 +704,12 @@
  `.trim();
  // 复制到剪贴板
  navigator.clipboard.writeText(knowledgeText).then(() => {
    navigator.clipboard
      .writeText(knowledgeText)
      .then(() => {
    ElMessage.success("知识内容已复制到剪贴板");
  }).catch(() => {
      })
      .catch(() => {
    ElMessage.error("复制失败,请手动复制");
  });
};
@@ -678,7 +717,9 @@
// 收藏知识
const markAsFavorite = () => {
  // 增加使用次数
  const index = mockData.findIndex(item => item.id === currentKnowledge.value.id);
    const index = mockData.findIndex(
      item => item.id === currentKnowledge.value.id
    );
  if (index !== -1) {
    mockData[index].usageCount += 1;
    currentKnowledge.value.usageCount += 1;
@@ -693,25 +734,29 @@
    await formRef.value.validate();
    if (dialogType.value === "add") {
      // 新增知识
      addKnowledgeBase({...form.value}).then(res => {
        addKnowledgeBase({ ...form.value })
          .then(res => {
        if(res.code == 200){
          ElMessage.success("添加成功");
          dialogVisible.value = false;
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    } else {
      updateKnowledgeBase({...form.value}).then(res => {
        updateKnowledgeBase({ ...form.value })
          .then(res => {
        if(res.code == 200){
          ElMessage.success("更新成功");
          dialogVisible.value = false;
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    }
  } catch (error) {
    console.error("表单验证失败:", error);
@@ -729,7 +774,8 @@
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    })
      .then(() => {
    // console.log(selectedIds.value);
    delKnowledgeBase(selectedIds.value).then(res => {
      if(res.code == 200){
@@ -737,17 +783,22 @@
        selectedIds.value = [];
        getList();
      }
        });
    })
  }).catch(() => {
      .catch(() => {
    // 用户取消
  });
};
// 导出
const { proxy } = getCurrentInstance()
  const { proxy } = getCurrentInstance();
const handleExport = () => {
  proxy.download('/knowledgeBase/export', { ...searchForm.value }, '知识库.xlsx')
}
    proxy.download(
      "/knowledgeBase/export",
      { ...searchForm.value },
      "知识库.xlsx"
    );
  };
</script>
<style scoped>
src/views/collaborativeApproval/notificationManagement/index.vue
@@ -3,37 +3,49 @@
    <div class="search_form">
      <div>
        <span class="search_title">通知标题:</span>
        <el-input
          v-model="searchForm.title"
        <el-input v-model="searchForm.title"
          style="width: 240px"
          placeholder="请输入通知标题搜索"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
        />
                  :prefix-icon="Search" />
        <span class="search_title ml10">通知类型:</span>
        <el-select v-model="searchForm.type" clearable @change="handleQuery" style="width: 240px">
          <el-option label="放假通知" :value="'holiday'" />
          <el-option label="处罚通知" :value="'penalty'" />
          <el-option label="开会通知" :value="'meeting'" />
          <el-option label="临时通知" :value="'temporary'" />
          <el-option label="正式通知" :value="'formal'" />
        <el-select v-model="searchForm.type"
                   clearable
                   @change="handleQuery"
                   style="width: 240px">
          <el-option label="放假通知"
                     :value="'holiday'" />
          <el-option label="处罚通知"
                     :value="'penalty'" />
          <el-option label="开会通知"
                     :value="'meeting'" />
          <el-option label="临时通知"
                     :value="'temporary'" />
          <el-option label="正式通知"
                     :value="'formal'" />
        </el-select>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">
          搜索
        </el-button>
      </div>
      <div>
        <el-button type="primary" @click="openForm('add')">新增通知</el-button>
        <el-button type="success" @click="openMeetingDialog">在线会议</el-button>
        <el-button type="warning" @click="openFileShareDialog">文件共享</el-button>
        <el-button type="primary"
                   @click="openForm('add')">新增通知</el-button>
        <el-button type="success"
                   @click="openMeetingDialog">在线会议</el-button>
        <el-button type="warning"
                   @click="openFileShareDialog">文件共享</el-button>
        <!-- <el-button type="info" @click="refreshEmployees">刷新员工</el-button> -->
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
        rowKey="id"
      <PIMTable rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
@@ -41,171 +53,177 @@
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="page.total"
      ></PIMTable>
                :total="page.total"></PIMTable>
    </div>
    <!-- 新增/编辑通知弹窗 -->
    <el-dialog
      v-model="dialogVisible"
    <el-dialog v-model="dialogVisible"
      :title="dialogTitle"
      width="800px"
      :close-on-click-modal="false"
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
               :close-on-click-modal="false">
      <el-form ref="formRef"
               :model="form"
               :rules="rules"
               label-width="120px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="通知标题" prop="title">
              <el-input v-model="form.title" placeholder="请输入通知标题" />
            <el-form-item label="通知标题"
                          prop="title">
              <el-input v-model="form.title"
                        placeholder="请输入通知标题" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="通知类型" prop="type">
              <el-select v-model="form.type" placeholder="请选择通知类型" style="width: 100%">
                <el-option label="放假通知" value="holiday" />
                <el-option label="处罚通知" value="penalty" />
                <el-option label="开会通知" value="meeting" />
                <el-option label="临时通知" value="temporary" />
                <el-option label="正式通知" value="formal" />
            <el-form-item label="通知类型"
                          prop="type">
              <el-select v-model="form.type"
                         placeholder="请选择通知类型"
                         style="width: 100%">
                <el-option label="放假通知"
                           value="holiday" />
                <el-option label="处罚通知"
                           value="penalty" />
                <el-option label="开会通知"
                           value="meeting" />
                <el-option label="临时通知"
                           value="temporary" />
                <el-option label="正式通知"
                           value="formal" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="优先级" prop="priority">
              <el-select v-model="form.priority" placeholder="请选择优先级" style="width: 100%">
                <el-option label="普通" value="low" />
                <el-option label="重要" value="medium" />
                <el-option label="紧急" value="high" />
            <el-form-item label="优先级"
                          prop="priority">
              <el-select v-model="form.priority"
                         placeholder="请选择优先级"
                         style="width: 100%">
                <el-option label="普通"
                           value="low" />
                <el-option label="重要"
                           value="medium" />
                <el-option label="紧急"
                           value="high" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="有效期至" prop="expireDate">
              <el-date-picker
                v-model="form.expireDate"
            <el-form-item label="有效期至"
                          prop="expireDate">
              <el-date-picker v-model="form.expireDate"
                type="date"
                placeholder="请选择有效期"
                value-format="YYYY-MM-DD"
                format="YYYY-MM-DD"
                style="width: 100%"
              />
                              style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="接收部门" prop="departments">
          <el-select
            v-model="form.departments"
        <el-form-item label="接收部门"
                      prop="departments">
          <el-select v-model="form.departments"
            multiple
            placeholder="请选择接收部门"
            style="width: 100%"
          >
            <el-option
              v-for="dept in departments"
                     style="width: 100%">
            <el-option v-for="dept in departments"
              :key="dept"
              :label="dept"
              :value="dept"
            />
                       :value="dept" />
          </el-select>
        </el-form-item>
        <el-form-item label="同步方式" prop="syncMethods">
        <el-form-item label="同步方式"
                      prop="syncMethods">
          <el-checkbox-group v-model="form.syncMethods">
            <el-checkbox
              v-for="method in syncMethods"
            <el-checkbox v-for="method in syncMethods"
              :key="method.value"
              :label="method.value"
            >
                         :label="method.value">
              {{ method.label }}
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>
        <el-form-item label="通知内容" prop="content">
          <el-input
            v-model="form.content"
        <el-form-item label="通知内容"
                      prop="content">
          <el-input v-model="form.content"
            type="textarea"
            :rows="4"
            placeholder="请输入通知内容"
          />
                    placeholder="请输入通知内容" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 在线会议弹窗 -->
    <el-dialog
      v-model="meetingDialogVisible"
    <el-dialog v-model="meetingDialogVisible"
      title="创建在线会议"
      width="700px"
      :close-on-click-modal="false"
    >
      <el-form ref="meetingFormRef" :model="meetingForm" :rules="meetingRules" label-width="120px">
        <el-form-item label="会议标题" prop="title">
          <el-input v-model="meetingForm.title" placeholder="请输入会议标题" />
               :close-on-click-modal="false">
      <el-form ref="meetingFormRef"
               :model="meetingForm"
               :rules="meetingRules"
               label-width="120px">
        <el-form-item label="会议标题"
                      prop="title">
          <el-input v-model="meetingForm.title"
                    placeholder="请输入会议标题" />
        </el-form-item>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="开始时间" prop="startTime">
              <el-date-picker
                v-model="meetingForm.startTime"
            <el-form-item label="开始时间"
                          prop="startTime">
              <el-date-picker v-model="meetingForm.startTime"
                type="datetime"
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择开始时间"
                style="width: 100%"
              />
                              style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="会议时长" prop="duration">
              <el-input-number
                v-model="meetingForm.duration"
            <el-form-item label="会议时长"
                          prop="duration">
              <el-input-number v-model="meetingForm.duration"
                :min="15"
                :max="480"
                :step="15"
                style="width: 100%"
              />
                               style="width: 100%" />
              <span style="margin-left: 10px">分钟</span>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="会议平台" prop="platform">
          <el-select v-model="meetingForm.platform" placeholder="请选择会议平台" style="width: 100%">
            <el-option
              v-for="platform in meetingPlatforms"
        <el-form-item label="会议平台"
                      prop="platform">
          <el-select v-model="meetingForm.platform"
                     placeholder="请选择会议平台"
                     style="width: 100%">
            <el-option v-for="platform in meetingPlatforms"
              :key="platform.value"
              :label="platform.label"
              :value="platform.value"
            />
                       :value="platform.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="参会人员" prop="participants">
          <el-select
            v-model="meetingForm.participants"
        <el-form-item label="参会人员"
                      prop="participants">
          <el-select v-model="meetingForm.participants"
            multiple
            filterable
            remote
            :remote-method="filterEmployees"
            :loading="employeesLoading"
            placeholder="请选择参会人员"
            style="width: 100%"
          >
            <el-option-group
              v-for="group in employeeGroups"
                     style="width: 100%">
            <el-option-group v-for="group in employeeGroups"
              :key="group.label"
              :label="group.label"
            >
                             <el-option
                 v-for="employee in group.options"
                             :label="group.label">
              <el-option v-for="employee in group.options"
                 :key="employee.value"
                 :label="`${employee.label} (${employee.dept})`"
                 :value="employee.value"
               >
                         :value="employee.value">
                 <div style="display: flex; justify-content: space-between; align-items: center;">
                   <div>
                     <div style="font-weight: 500;">{{ employee.label }}</div>
@@ -223,80 +241,76 @@
            已选择 {{ meetingForm.participants.length }} 人
          </div>
          <!-- 已选择人员详情 -->
          <div v-if="meetingForm.participants.length > 0" style="margin-top: 10px;">
            <el-tag
              v-for="participantId in meetingForm.participants"
          <div v-if="meetingForm.participants.length > 0"
               style="margin-top: 10px;">
            <el-tag v-for="participantId in meetingForm.participants"
              :key="participantId"
              closable
              @close="removeParticipant(participantId)"
              style="margin-right: 8px; margin-bottom: 8px;"
            >
                    style="margin-right: 8px; margin-bottom: 8px;">
              {{ getEmployeeName(participantId) }}
            </el-tag>
          </div>
        </el-form-item>
        <el-form-item label="会议描述" prop="description">
          <el-input
            v-model="meetingForm.description"
        <el-form-item label="会议描述"
                      prop="description">
          <el-input v-model="meetingForm.description"
            type="textarea"
            :rows="3"
            placeholder="请输入会议描述"
          />
                    placeholder="请输入会议描述" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="createMeeting">创建会议</el-button>
          <el-button @click="meetingDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="createMeeting">创建会议</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 文件共享弹窗 -->
    <el-dialog
      v-model="fileShareDialogVisible"
    <el-dialog v-model="fileShareDialogVisible"
      title="文件共享"
      width="700px"
      :close-on-click-modal="false"
    >
      <el-form ref="fileShareFormRef" :model="fileShareForm" :rules="fileShareRules" label-width="120px">
        <el-form-item label="共享标题" prop="title">
          <el-input v-model="fileShareForm.title" placeholder="请输入共享标题" />
               :close-on-click-modal="false">
      <el-form ref="fileShareFormRef"
               :model="fileShareForm"
               :rules="fileShareRules"
               label-width="120px">
        <el-form-item label="共享标题"
                      prop="title">
          <el-input v-model="fileShareForm.title"
                    placeholder="请输入共享标题" />
        </el-form-item>
        <el-form-item label="共享描述" prop="description">
          <el-input
            v-model="fileShareForm.description"
        <el-form-item label="共享描述"
                      prop="description">
          <el-input v-model="fileShareForm.description"
            type="textarea"
            :rows="3"
            placeholder="请输入共享描述"
          />
                    placeholder="请输入共享描述" />
        </el-form-item>
        <el-form-item label="接收部门" prop="departments">
          <el-select
            v-model="fileShareForm.departments"
        <el-form-item label="接收部门"
                      prop="departments">
          <el-select v-model="fileShareForm.departments"
            multiple
            placeholder="请选择接收部门"
            style="width: 100%"
          >
            <el-option
              v-for="dept in departments"
                     style="width: 100%">
            <el-option v-for="dept in departments"
              :key="dept"
              :label="dept"
              :value="dept"
            />
                       :value="dept" />
          </el-select>
        </el-form-item>
        <el-form-item label="上传文件" prop="files">
          <el-upload
            ref="uploadRef"
        <el-form-item label="上传文件"
                      prop="files">
          <el-upload ref="uploadRef"
            :auto-upload="false"
            :on-change="handleFileChange"
            :on-remove="removeFile"
            :file-list="fileList"
            multiple
            :limit="10"
            accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.txt,.jpg,.jpeg,.png,.gif"
          >
                     accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.txt,.jpg,.jpeg,.png,.gif">
            <el-button type="primary">选择文件</el-button>
            <template #tip>
              <div class="el-upload__tip">
@@ -308,8 +322,9 @@
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="shareFiles">共享文件</el-button>
          <el-button @click="fileShareDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="shareFiles">共享文件</el-button>
        </span>
      </template>
    </el-dialog>
@@ -323,41 +338,36 @@
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { userListNoPageByTenantId } from "@/api/system/user.js";
import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js";
import { listNotification, addNotification, updateNotification, delNotification,addOnlineMeeting,addFileSharing } from "@/api/collaborativeApproval/notificationManagement.js";
  import {
    listNotification,
    addNotification,
    updateNotification,
    delNotification,
    addOnlineMeeting,
    addFileSharing,
  } from "@/api/collaborativeApproval/notificationManagement.js";
import { id } from "element-plus/es/locales.mjs";
// 表单验证规则
const rules = {
  title: [
    { required: true, message: "请输入通知标题", trigger: "blur" }
  ],
  type: [
    { required: true, message: "请选择通知类型", trigger: "change" }
  ],
  content: [
    { required: true, message: "请输入通知内容", trigger: "blur" }
  ]
    title: [{ required: true, message: "请输入通知标题", trigger: "blur" }],
    type: [{ required: true, message: "请选择通知类型", trigger: "change" }],
    content: [{ required: true, message: "请输入通知内容", trigger: "blur" }],
};
const meetingRules = {
  title: [
    { required: true, message: "请输入会议标题", trigger: "blur" }
  ],
    title: [{ required: true, message: "请输入会议标题", trigger: "blur" }],
  startTime: [
    { required: true, message: "请选择会议开始时间", trigger: "change" }
      { required: true, message: "请选择会议开始时间", trigger: "change" },
  ],
  participants: [
    { required: true, message: "请选择参会人员", trigger: "change" }
  ]
      { required: true, message: "请选择参会人员", trigger: "change" },
    ],
};
const fileShareRules = {
  title: [
    { required: true, message: "请输入共享标题", trigger: "blur" }
  ],
  description: [
    { required: true, message: "请输入共享描述", trigger: "blur" }
  ]
    title: [{ required: true, message: "请输入共享标题", trigger: "blur" }],
    description: [{ required: true, message: "请输入共享描述", trigger: "blur" }],
};
// 响应式数据
@@ -383,7 +393,7 @@
    content: "",
    departments: [],
    expireDate: "",
    syncMethods: []
      syncMethods: [],
  },
  dialogVisible: false,
  dialogTitle: "",
@@ -396,7 +406,7 @@
    duration: 60,
    participants: [],
    description: "",
    platform: "wechat"
      platform: "wechat",
  },
  // 文件共享相关
  fileShareDialogVisible: false,
@@ -404,9 +414,9 @@
    title: "",
    description: "",
    departments: [],
    files: []
      files: [],
  },
  fileList: []
    fileList: [],
});
const {
@@ -423,7 +433,7 @@
  meetingForm,
  fileShareDialogVisible,
  fileShareForm,
  fileList
    fileList,
} = toRefs(data);
// 表单引用
@@ -442,87 +452,87 @@
    label: "通知类型",
    prop: "type",
    dataType: "tag",
    formatData: (params) => {
      formatData: params => {
      const typeMap = {
        holiday: "放假通知",
        penalty: "处罚通知",
        meeting: "开会通知",
        temporary: "临时通知",
        formal: "正式通知"
          formal: "正式通知",
      };
      return typeMap[params] || params;
    },
    formatType: (params) => {
      formatType: params => {
      const typeMap = {
        holiday: "success",
        penalty: "danger",
        meeting: "warning",
        temporary: "info",
        formal: "primary"
          formal: "primary",
      };
      return typeMap[params] || "info";
    }
      },
  },
  {
    label: "优先级",
    prop: "priority",
    dataType: "tag",
    formatData: (params) => {
      formatData: params => {
      const priorityMap = {
        low: "普通",
        medium: "重要",
        high: "紧急"
          high: "紧急",
      };
      return priorityMap[params] || params;
    },
    formatType: (params) => {
      formatType: params => {
      const typeMap = {
        low: "info",
        medium: "warning",
        high: "danger"
          high: "danger",
      };
      return typeMap[params] || "info";
    }
      },
  },
  {
    label: "状态",
    prop: "status",
    dataType: "tag",
    formatData: (params) => {
      formatData: params => {
      const statusMap = {
        draft: "草稿",
        published: "已发布",
        expired: "已过期"
          expired: "已过期",
      };
      return statusMap[params] || params;
    },
    formatType: (params) => {
      formatType: params => {
      const typeMap = {
        draft: "info",
        published: "success",
        expired: "danger"
          expired: "danger",
      };
      return typeMap[params] || "info";
    }
      },
  },
  {
    label: "接收部门",
    prop: "departments",
    width: 150,
    showOverflowTooltip: true,
    formatData: (params) => {
      formatData: params => {
      if (!params || params.length === 0) return "全部部门";
      return params.join(", ");
    }
      },
  },
  {
    label: "有效期至",
    prop: "expireDate",
    width: 150,
    formatData: (params) => {
      formatData: params => {
      if (!params) return "永久有效";
      return params;
    }
      },
  },
  {
    label: "创建时间",
@@ -539,14 +549,14 @@
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          clickFun: row => {
          openForm("edit", row);
        }
          },
      },
      {
        name: "发布",
        type: "text",
        clickFun: (row) => {
          clickFun: row => {
          publishNotification(row);
        },
        // disabled: (row) => row.status === "published"
@@ -554,13 +564,13 @@
      {
        name: "撤回",
        type: "text",
        clickFun: (row) => {
          clickFun: row => {
          revokeNotification(row);
        },
        // disabled: (row) => row.status !== "published"
      }
    ]
  }
        },
      ],
    },
]);
// 通知标题模板
const titleTemplates = [
@@ -571,7 +581,7 @@
  "{dept}部门工作安排通知",
  "关于{project}项目进度的通知",
  "{dept}部门人员调整通知",
  "公司{policy}政策更新通知"
    "公司{policy}政策更新通知",
];
// 通知类型配置
@@ -580,11 +590,19 @@
  { type: "meeting", label: "开会通知", priority: "medium" },
  { type: "penalty", label: "处罚通知", priority: "high" },
  { type: "temporary", label: "临时通知", priority: "low" },
  { type: "formal", label: "正式通知", priority: "medium" }
    { type: "formal", label: "正式通知", priority: "medium" },
];
// 部门列表
const departments = ["技术部", "销售部", "人事部", "财务部", "运营部", "市场部", "客服部"];
  const departments = [
    "技术部",
    "销售部",
    "人事部",
    "财务部",
    "运营部",
    "市场部",
    "客服部",
  ];
// 人员列表
const employees = ref([]);
@@ -598,40 +616,63 @@
    const userResponse = await userListNoPageByTenantId();
    if (userResponse.data) {
      employees.value = userResponse.data.map(user => ({
        label: user.nickName || user.userName || '未知姓名',
        employees.value = userResponse.data
          .map(user => ({
            label: user.nickName || user.userName || "未知姓名",
        value: user.userId || user.id,
        dept: user.dept?.deptName || '未知部门',
        phone: user.phonenumber || '',
        email: user.email || '',
        status: user.status || '0'
      })).filter(user => user.status === '0'); // 只显示正常状态的用户
            dept: user.dept?.deptName || "未知部门",
            phone: user.phonenumber || "",
            email: user.email || "",
            status: user.status || "0",
          }))
          .filter(user => user.status === "0"); // 只显示正常状态的用户
    } else {
      // 如果系统用户接口失败,使用员工台账接口
      const response = await staffOnJobListPage({
        pageNum: 1,
        pageSize: 1000,
        staffState: 1 // 在职状态
          staffState: 1, // 在职状态
      });
      if (response.data && response.data.records) {
        employees.value = response.data.records.map(employee => ({
          label: employee.staffName || employee.name || '未知姓名',
            label: employee.staffName || employee.name || "未知姓名",
          value: employee.staffNo || employee.id || employee.staffId,
          dept: employee.deptName || employee.department || '未知部门',
          phone: employee.phone || employee.mobile || '',
          email: employee.email || '',
          status: '0'
            dept: employee.deptName || employee.department || "未知部门",
            phone: employee.phone || employee.mobile || "",
            email: employee.email || "",
            status: "0",
        }));
      }
    }
  } catch (error) {
    console.error('获取员工列表失败:', error);
      console.error("获取员工列表失败:", error);
    // 如果接口都失败,使用默认数据
    employees.value = [
      { label: "张三", value: "001", dept: "技术部", phone: "13800138001", email: "zhangsan@company.com", status: "0" },
      { label: "李四", value: "002", dept: "销售部", phone: "13800138002", email: "lisi@company.com", status: "0" },
      { label: "王五", value: "003", dept: "人事部", phone: "13800138003", email: "wangwu@company.com", status: "0" }
        {
          label: "张三",
          value: "001",
          dept: "技术部",
          phone: "13800138001",
          email: "zhangsan@company.com",
          status: "0",
        },
        {
          label: "李四",
          value: "002",
          dept: "销售部",
          phone: "13800138002",
          email: "lisi@company.com",
          status: "0",
        },
        {
          label: "王五",
          value: "003",
          dept: "人事部",
          phone: "13800138003",
          email: "wangwu@company.com",
          status: "0",
        },
    ];
  } finally {
    employeesLoading.value = false;
@@ -642,7 +683,7 @@
const employeeGroups = computed(() => {
  const groups = {};
  employees.value.forEach(employee => {
    const dept = employee.dept || '其他部门';
      const dept = employee.dept || "其他部门";
    if (!groups[dept]) {
      groups[dept] = [];
    }
@@ -654,15 +695,18 @@
    .sort()
    .map(dept => ({
      label: dept,
      options: groups[dept].sort((a, b) => a.label.localeCompare(b.label, 'zh-CN'))
        options: groups[dept].sort((a, b) =>
          a.label.localeCompare(b.label, "zh-CN")
        ),
    }));
});
// 过滤员工(远程搜索)
const filterEmployees = (query) => {
  if (query !== '') {
  const filterEmployees = query => {
    if (query !== "") {
    const lowerQuery = query.toLowerCase();
    return employees.value.filter(employee =>
      return employees.value.filter(
        employee =>
      employee.label.toLowerCase().includes(lowerQuery) ||
      employee.dept.toLowerCase().includes(lowerQuery) ||
      (employee.phone && employee.phone.includes(query)) ||
@@ -681,25 +725,27 @@
  // 统计各部门人数
  const deptStats = {};
  employees.value.forEach(emp => {
    const dept = emp.dept || '其他部门';
      const dept = emp.dept || "其他部门";
    deptStats[dept] = (deptStats[dept] || 0) + 1;
  });
  const deptInfo = Object.entries(deptStats)
    .map(([dept, count]) => `${dept}: ${count}人`)
    .join(', ');
      .join(", ");
  ElMessage.success(`员工列表刷新完成,共 ${employees.value.length} 人 (${deptInfo})`);
    ElMessage.success(
      `员工列表刷新完成,共 ${employees.value.length} 人 (${deptInfo})`
    );
};
// 获取员工姓名
const getEmployeeName = (employeeId) => {
  const getEmployeeName = employeeId => {
  const employee = employees.value.find(emp => emp.value === employeeId);
  return employee ? employee.label : '未知人员';
    return employee ? employee.label : "未知人员";
};
// 获取员工详细信息
const getEmployeeInfo = (employeeId) => {
  const getEmployeeInfo = employeeId => {
  const employee = employees.value.find(emp => emp.value === employeeId);
  if (!employee) return null;
@@ -707,12 +753,12 @@
    name: employee.label,
    dept: employee.dept,
    phone: employee.phone,
    email: employee.email
      email: employee.email,
  };
};
// 移除参会人员
const removeParticipant = (participantId) => {
  const removeParticipant = participantId => {
  const index = meetingForm.value.participants.indexOf(participantId);
  if (index > -1) {
    meetingForm.value.participants.splice(index, 1);
@@ -724,7 +770,7 @@
  { label: "企业微信", value: "wechat" },
  { label: "钉钉", value: "dingtalk" },
  { label: "邮件", value: "email" },
  { label: "短信", value: "sms" }
    { label: "短信", value: "sms" },
];
// 会议平台选项
@@ -732,35 +778,60 @@
  { label: "企业微信会议", value: "wechat" },
  { label: "钉钉会议", value: "dingtalk" },
  { label: "腾讯会议", value: "tencent" },
  { label: "Zoom", value: "zoom" }
    { label: "Zoom", value: "zoom" },
];
// 自动生成新数据
const generateNewData = () => {
  const newId = (mockData.length + 1).toString();
  const now = new Date();
  const randomType = notificationTypes[Math.floor(Math.random() * notificationTypes.length)];
  const randomDept = departments[Math.floor(Math.random() * departments.length)];
    const randomType =
      notificationTypes[Math.floor(Math.random() * notificationTypes.length)];
    const randomDept =
      departments[Math.floor(Math.random() * departments.length)];
  // 生成随机标题
  let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)];
  title = title
    .replace('{year}', now.getFullYear())
    .replace('{holiday}', ['春节', '国庆', '中秋', '元旦'][Math.floor(Math.random() * 4)])
    .replace('{dept}', randomDept)
    .replace('{meeting}', ['周例会', '月度总结', '项目评审', '培训会议'][Math.floor(Math.random() * 4)])
    .replace('{behavior}', ['考勤', '着装', '工作态度', '团队协作'][Math.floor(Math.random() * 4)])
    .replace('{company}', ['公司', '集团', '总部'][Math.floor(Math.random() * 4)])
    .replace('{project}', ['数字化转型', '产品升级', '市场拓展', '人才培养'][Math.floor(Math.random() * 4)])
    .replace('{policy}', ['考勤', '薪酬', '福利', '晋升'][Math.floor(Math.random() * 4)]);
      .replace("{year}", now.getFullYear())
      .replace(
        "{holiday}",
        ["春节", "国庆", "中秋", "元旦"][Math.floor(Math.random() * 4)]
      )
      .replace("{dept}", randomDept)
      .replace(
        "{meeting}",
        ["周例会", "月度总结", "项目评审", "培训会议"][
          Math.floor(Math.random() * 4)
        ]
      )
      .replace(
        "{behavior}",
        ["考勤", "着装", "工作态度", "团队协作"][Math.floor(Math.random() * 4)]
      )
      .replace(
        "{company}",
        ["公司", "集团", "总部"][Math.floor(Math.random() * 4)]
      )
      .replace(
        "{project}",
        ["数字化转型", "产品升级", "市场拓展", "人才培养"][
          Math.floor(Math.random() * 4)
        ]
      )
      .replace(
        "{policy}",
        ["考勤", "薪酬", "福利", "晋升"][Math.floor(Math.random() * 4)]
      );
  // 随机状态
  const statuses = ['draft', 'published'];
    const statuses = ["draft", "published"];
  const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];
  // 随机优先级
  const priorities = ['low', 'medium', 'high'];
  const randomPriority = priorities[Math.floor(Math.random() * priorities.length)];
    const priorities = ["low", "medium", "high"];
    const randomPriority =
      priorities[Math.floor(Math.random() * priorities.length)];
  const newNotification = {
    id: newId,
@@ -770,9 +841,11 @@
    status: randomStatus,
    content: `这是${title}的详细内容,请相关人员注意查看...`,
    departments: [randomDept],
    expireDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], // 30天后过期
      expireDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000)
        .toISOString()
        .split("T")[0], // 30天后过期
    syncMethods: ["wechat", "dingtalk"],
    createTime: now.toLocaleString()
      createTime: now.toLocaleString(),
  };
  // 添加到数据开头
@@ -812,22 +885,23 @@
  listNotification({...page.value, ...searchForm.value})
  .then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
        tableData.value = res.data.records;
    page.value.total = res.data.total;
  }).catch(err => {
    tableLoading.value = false;
  })
      .catch(err => {
        tableLoading.value = false;
      });
};
// 分页处理
const pagination = (obj) => {
  const pagination = obj => {
  page.value.current = obj.page;
  page.value.size = obj.limit;
  handleQuery();
};
// 选择变化处理
const handleSelectionChange = (selection) => {
  const handleSelectionChange = selection => {
  selectedIds.value = selection.map(item => item.id);
};
@@ -846,7 +920,7 @@
      departments: [],
      expireDate: "",
      status: "draft",
      syncMethods: []
        syncMethods: [],
    });
  } else if (type === "edit" && row) {
    dialogTitle.value = "编辑通知";
@@ -859,7 +933,7 @@
      departments: row.departments || [],
      expireDate: row.expireDate || "",
      status: row.status,
      syncMethods: row.syncMethods || []
        syncMethods: row.syncMethods || [],
    });
  }
  dialogVisible.value = true;
@@ -874,7 +948,7 @@
    duration: 60,
    participants: [],
    description: "",
    platform: "wechat"
      platform: "wechat",
  });
  meetingDialogVisible.value = true;
};
@@ -886,7 +960,7 @@
    title: "",
    description: "",
    departments: [],
    files: []
      files: [],
  });
  fileList.value = [];
  fileShareDialogVisible.value = true;
@@ -906,26 +980,30 @@
    if (dialogType.value === "add") {
      // 新增通知
      addNotification({...form.value}).then(res => {
        addNotification({ ...form.value })
          .then(res => {
        if(res.code == 200){
          ElMessage.success("添加成功");
          dialogVisible.value = false;
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    } else {
      // 编辑通知
      updateNotification({...form.value}).then(res => {
        updateNotification({ ...form.value })
          .then(res => {
        if(res.code == 200){
          ElMessage.success("更新成功");
          dialogVisible.value = false;
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    }
  } catch (error) {
    console.error("表单验证失败:", error);
@@ -944,38 +1022,50 @@
      duration: meetingForm.value.duration,
      participants: meetingForm.value.participants,
      description: meetingForm.value.description,
      platform: meetingForm.value.platform
        platform: meetingForm.value.platform,
    };
    // 新增会议
    addOnlineMeeting({...meetingInfo}).then(res => {
      addOnlineMeeting({ ...meetingInfo })
        .then(res => {
      if(res.code == 200){
        ElMessage.success("会议添加成功");
        meetingDialogVisible.value = false;
        getList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // 模拟发送到企业微信/钉钉
    // const platformName = meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "未知平台";
    // ElMessage.success(`会议创建成功!会议ID: ${meetingInfo.meetingId},将通过${platformName}发送通知`);
    // 获取参会人员信息
     const participantNames = meetingForm.value.participants.map(participantId => {
       const employee = employees.value.find(emp => emp.value === participantId);
       return employee ? employee.label : '未知人员';
     }).join('、');
      const participantNames = meetingForm.value.participants
        .map(participantId => {
          const employee = employees.value.find(
            emp => emp.value === participantId
          );
          return employee ? employee.label : "未知人员";
        })
        .join("、");
     // 获取参会人员详细信息
     const participantDetails = meetingForm.value.participants.map(participantId => {
       const employee = employees.value.find(emp => emp.value === participantId);
       return employee ? {
      const participantDetails = meetingForm.value.participants
        .map(participantId => {
          const employee = employees.value.find(
            emp => emp.value === participantId
          );
          return employee
            ? {
         name: employee.label,
         dept: employee.dept,
         phone: employee.phone,
         email: employee.email
       } : null;
     }).filter(Boolean);
                email: employee.email,
              }
            : null;
        })
        .filter(Boolean);
    // 将会议信息添加到通知列表
    const meetingNotification = {
@@ -983,20 +1073,27 @@
      type: "meeting",
      priority: "high",
      status: "published",
      content: `会议时间: ${meetingInfo.startTime},时长: ${meetingInfo.duration}分钟,平台: ${meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "未知平台"},参会人员: ${participantNames},共${participantDetails.length}人`,
        content: `会议时间: ${meetingInfo.startTime},时长: ${
          meetingInfo.duration
        }分钟,平台: ${
          meetingPlatforms.find(p => p.value === meetingForm.value.platform)
            ?.label || "未知平台"
        },参会人员: ${participantNames},共${participantDetails.length}人`,
      departments: [],
      expireDate: "",
      syncMethods: [meetingForm.value.platform]
        syncMethods: [meetingForm.value.platform],
    };
    addNotification({...meetingNotification}).then(res => {
      addNotification({ ...meetingNotification })
        .then(res => {
        if(res.code == 200){
          ElMessage.success("添加成功");
          // dialogVisible.value = false;
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // mockData.unshift(meetingNotification);
    // getList();
  } catch (error) {
@@ -1005,7 +1102,7 @@
};
// 文件上传处理
const handleFileChange = (file) => {
  const handleFileChange = file => {
  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isLt10M) {
    ElMessage.error("上传文件大小不能超过 10MB!");
@@ -1016,7 +1113,7 @@
    name: file.name,
    size: file.size,
    type: file.type,
    uid: file.uid
      uid: file.uid,
  };
  fileList.value.push(fileInfo);
@@ -1025,10 +1122,12 @@
};
// 移除文件
const removeFile = (file) => {
  const removeFile = file => {
  const index = fileList.value.findIndex(item => item.uid === file.uid);
  if (index !== -1) {
    const index2 = fileShareForm.value.files.findIndex(item => item.uid === file.uid);
      const index2 = fileShareForm.value.files.findIndex(
        item => item.uid === file.uid
      );
    if (index2 !== -1) {
      fileShareForm.value.files.splice(index2, 1);
    }
@@ -1053,18 +1152,19 @@
      departments: fileShareForm.value.departments,
      files: fileShareForm.value.files,
    };
    addFileSharing({...shareInfo}).then(res => {
      addFileSharing({ ...shareInfo })
        .then(res => {
      if(res.code == 200){
        ElMessage.success("文件共享成功");
        fileShareDialogVisible.value = false;
        getList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // ElMessage.success(`文件共享成功!共享ID: ${shareInfo.shareId},已通知相关部门`);
    // 将文件共享信息添加到通知列表
    const fileShareNotification = {
@@ -1077,15 +1177,17 @@
      expireDate: "",
      syncMethods: ["wechat", "dingtalk"],
    };
    addNotification({...fileShareNotification}).then(res => {
      addNotification({ ...fileShareNotification })
        .then(res => {
      if(res.code == 200){
        ElMessage.success("添加成功");
        // dialogVisible.value = false;
        getList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
    // mockData.unshift(fileShareNotification);
    // getList();
@@ -1095,7 +1197,7 @@
};
// 发布通知
const publishNotification = (row) => {
  const publishNotification = row => {
  Object.assign(form.value, {
    id: row.id,
    title: row.title,
@@ -1105,21 +1207,23 @@
    departments: row.departments || [],
    expireDate: row.expireDate || "",
    status: row.status,
    syncMethods: row.syncMethods || []
      syncMethods: row.syncMethods || [],
  });
  form.value.status = "published";
  updateNotification({...form.value}).then(res => {
    updateNotification({ ...form.value })
      .then(res => {
        if(res.code == 200){
          ElMessage.success("通知发布成功");
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
      .catch(err => {
        ElMessage.error(err.msg);
      });
};
// 撤回通知
const revokeNotification = (row) => {
  const revokeNotification = row => {
    Object.assign(form.value, {
    id: row.id,
    title: row.title,
@@ -1129,17 +1233,19 @@
    departments: row.departments || [],
    expireDate: row.expireDate || "",
    status: row.status,
    syncMethods: row.syncMethods || []
      syncMethods: row.syncMethods || [],
  });
  form.value.status = "draft";
  updateNotification({...form.value}).then(res => {
    updateNotification({ ...form.value })
      .then(res => {
        if(res.code == 200){
          ElMessage.success("通知已撤回");
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
      .catch(err => {
        ElMessage.error(err.msg);
      });
};
// 删除通知
@@ -1155,17 +1261,21 @@
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    delNotification(ids).then(res => {
    })
      .then(() => {
        delNotification(ids)
          .then(res => {
      if(res.code == 200){
        ElMessage.success("删除成功");
        selectedIds.value = [];
        getList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
  }).catch(() => {
          .catch(err => {
            ElMessage.error(err.msg);
          });
      })
      .catch(() => {
    // 用户取消
  });
};
src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue
@@ -3,139 +3,174 @@
    <!-- 页面标题 -->
    <div class="page-header">
      <h2>会议草稿</h2>
      <el-button type="primary" @click="handleAdd">
        <el-icon><Plus /></el-icon>
      <el-button type="primary"
                 @click="handleAdd">
        <el-icon>
          <Plus />
        </el-icon>
        新建草稿
      </el-button>
    </div>
    <!-- 搜索区域 -->
    <el-card class="search-card">
      <el-form :model="searchForm" label-width="100px" inline>
      <el-form :model="searchForm"
               label-width="100px"
               inline>
        <el-form-item label="会议主题">
          <el-input v-model="searchForm.title" placeholder="请输入会议主题" clearable />
          <el-input v-model="searchForm.title"
                    placeholder="请输入会议主题"
                    clearable />
        </el-form-item>
        <el-form-item label="会议日期">
          <el-date-picker
            v-model="searchForm.meetingDate"
          <el-date-picker v-model="searchForm.meetingDate"
            type="date"
            placeholder="请选择会议日期"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- 草稿列表 -->
    <el-card>
      <el-table v-loading="loading" :data="draftList" border>
        <el-table-column prop="title" label="会议主题" align="center" min-width="200" show-overflow-tooltip />
        <el-table-column prop="room" label="会议室" align="center" width="120" />
        <el-table-column prop="host" label="主持人" align="center" width="120" />
        <el-table-column prop="meetingTime" label="会议时间" align="center" width="180">
      <el-table v-loading="loading"
                :data="draftList"
                border>
        <el-table-column prop="title"
                         label="会议主题"
                         align="center"
                         min-width="200"
                         show-overflow-tooltip />
        <el-table-column prop="room"
                         label="会议室"
                         align="center"
                         width="120" />
        <el-table-column prop="host"
                         label="主持人"
                         align="center"
                         width="120" />
        <el-table-column prop="meetingTime"
                         label="会议时间"
                         align="center"
                         width="180">
          <template #default="scope">
            {{ formatDateTime(scope.row.meetingTime) }}
          </template>
        </el-table-column>
        <el-table-column prop="participants" label="参会人数" align="center" width="100">
        <el-table-column prop="participants"
                         label="参会人数"
                         align="center"
                         width="100">
          <template #default="scope">
            {{ scope.row.participants }}人
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="创建时间" align="center" width="180" />
        <el-table-column label="操作" align="center" width="200" fixed="right">
        <el-table-column prop="createTime"
                         label="创建时间"
                         align="center"
                         width="180" />
        <el-table-column label="操作"
                         align="center"
                         width="200"
                         fixed="right">
          <template #default="scope">
            <el-button type="primary" link @click="viewDraft(scope.row)">查看</el-button>
            <el-button type="primary" link @click="editDraft(scope.row)">编辑</el-button>
            <el-button type="danger" link @click="deleteDraft(scope.row)">删除</el-button>
            <el-button type="primary"
                       link
                       @click="viewDraft(scope.row)">查看</el-button>
            <el-button type="primary"
                       link
                       @click="editDraft(scope.row)">编辑</el-button>
            <el-button type="danger"
                       link
                       @click="deleteDraft(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
        v-show="total > 0"
      <pagination v-show="total > 0"
        :total="total"
        v-model:page="queryParams.current"
        v-model:limit="queryParams.size"
        @pagination="getList"
      />
                  @pagination="getList" />
    </el-card>
    <!-- 会议草稿详情对话框 -->
    <el-dialog
      title="会议草稿详情"
    <el-dialog title="会议草稿详情"
      v-model="detailDialogVisible"
      width="800px"
    >
               width="800px">
      <div v-if="currentDraft">
        <el-descriptions :column="2" border>
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="会议主题">{{ currentDraft.title }}</el-descriptions-item>
          <el-descriptions-item label="会议编号">{{ currentDraft.meetingId }}</el-descriptions-item>
          <el-descriptions-item label="会议室">{{ currentDraft.room }}</el-descriptions-item>
          <el-descriptions-item label="主持人">{{ currentDraft.host }}</el-descriptions-item>
          <el-descriptions-item label="会议时间" :span="2">
          <el-descriptions-item label="会议时间"
                                :span="2">
            {{ formatDateTime(currentDraft.meetingTime) }}
          </el-descriptions-item>
          <el-descriptions-item label="创建时间">{{ currentDraft.createTime }}</el-descriptions-item>
        </el-descriptions>
        <div class="content-section mt-20">
          <h4>参会人员</h4>
          <div class="participants-list">
            {{ currentDraft.participantList }}
          </div>
        </div>
        <div class="content-section mt-20">
          <h4>会议说明</h4>
          <div class="meeting-description">{{ currentDraft.description }}</div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="detailDialogVisible = false">关 闭</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 新建/编辑草稿对话框 -->
    <el-dialog
      :title="dialogTitle"
    <el-dialog :title="dialogTitle"
      v-model="editDialogVisible"
      width="700px"
    >
      <el-form :model="meetingForm" :rules="rules" ref="meetingFormRef" label-width="100px">
        <el-form-item label="会议主题" prop="title">
          <el-input v-model="meetingForm.title" placeholder="请输入会议主题" />
               width="700px">
      <el-form :model="meetingForm"
               :rules="rules"
               ref="meetingFormRef"
               label-width="100px">
        <el-form-item label="会议主题"
                      prop="title">
          <el-input v-model="meetingForm.title"
                    placeholder="请输入会议主题" />
        </el-form-item>
        <el-form-item label="会议室" prop="room">
          <el-select v-model="meetingForm.roomId" placeholder="请选择会议室" style="width: 100%">
            <el-option v-for="(v,k) in roomList" :label="v.name" :value="v.id" />
        <el-form-item label="会议室"
                      prop="room">
          <el-select v-model="meetingForm.roomId"
                     placeholder="请选择会议室"
                     style="width: 100%">
            <el-option v-for="(v,k) in roomList"
                       :label="v.name"
                       :value="v.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="主持人" prop="host">
          <el-input v-model="meetingForm.host" placeholder="请输入主持人" />
        <el-form-item label="主持人"
                      prop="host">
          <el-input v-model="meetingForm.host"
                    placeholder="请输入主持人" />
        </el-form-item>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="会议日期" prop="meetingDate">
              <el-date-picker
                v-model="meetingForm.meetingDate"
            <el-form-item label="会议日期"
                          prop="meetingDate">
              <el-date-picker v-model="meetingForm.meetingDate"
                type="date"
                placeholder="请选择会议日期"
                value-format="YYYY-MM-DD"
                format="YYYY-MM-DD"
                :disabled-date="disabledDate"
                style="width: 100%"
              />
                              style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
@@ -144,67 +179,57 @@
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="开始时间" prop="startTime">
              <el-select
                v-model="meetingForm.startTime"
            <el-form-item label="开始时间"
                          prop="startTime">
              <el-select v-model="meetingForm.startTime"
                placeholder="请选择开始时间"
                style="width: 100%"
              >
                <el-option
                  v-for="time in timeOptions"
                         style="width: 100%">
                <el-option v-for="time in timeOptions"
                  :key="time.value"
                  :label="time.label"
                  :value="time.value"
                />
                           :value="time.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="结束时间" prop="endTime">
              <el-select
                v-model="meetingForm.endTime"
            <el-form-item label="结束时间"
                          prop="endTime">
              <el-select v-model="meetingForm.endTime"
                placeholder="请选择结束时间"
                style="width: 100%"
              >
                <el-option
                  v-for="time in timeOptions"
                         style="width: 100%">
                <el-option v-for="time in timeOptions"
                  :key="time.value"
                  :label="time.label"
                  :value="time.value"
                />
                           :value="time.value" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="参会人数" prop="participants">
          <el-input
              v-model="meetingForm.participants"
        <el-form-item label="参会人数"
                      prop="participants">
          <el-input v-model="meetingForm.participants"
              type="number"
              placeholder="请输入参会人数"
          />
                    placeholder="请输入参会人数" />
        </el-form-item>
        <el-form-item label="参会人员" prop="participants">
          <el-input
            v-model="meetingForm.participantList"
        <el-form-item label="参会人员"
                      prop="participants">
          <el-input v-model="meetingForm.participantList"
            type="textarea"
            :rows="3"
            placeholder="请输入参会人员,用逗号分隔"
          />
                    placeholder="请输入参会人员,用逗号分隔" />
        </el-form-item>
        <el-form-item label="会议说明">
          <el-input
            v-model="meetingForm.description"
          <el-input v-model="meetingForm.description"
            type="textarea"
            :rows="4"
            placeholder="请输入会议说明"
          />
                    placeholder="请输入会议说明" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">保 存</el-button>
          <el-button @click="editDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="submitForm">保 存</el-button>
        </div>
      </template>
    </el-dialog>
@@ -212,150 +237,159 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import Pagination from '@/components/Pagination/index.vue'
import {getRoomEnum,getDraftList,saveDraft,delDraft} from '@/api/collaborativeApproval/meeting.js'
  import { ref, reactive, onMounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus } from "@element-plus/icons-vue";
  import Pagination from "@/components/Pagination/index.vue";
  import {
    getRoomEnum,
    getDraftList,
    saveDraft,
    delDraft,
  } from "@/api/collaborativeApproval/meeting.js";
import dayjs from "dayjs";
// 数据列表加载状态
const loading = ref(false)
  const loading = ref(false);
// 总条数
const total = ref(0)
  const total = ref(0);
// 草稿列表数据
const draftList = ref([])
  const draftList = ref([]);
// 查询参数
const queryParams = reactive({
  current: 1,
  size: 10
})
    size: 10,
  });
// 搜索表单
const searchForm = reactive({
  title: '',
  meetingDate: ''
})
    title: "",
    meetingDate: "",
  });
// 是否显示对话框
const detailDialogVisible = ref(false)
const editDialogVisible = ref(false)
  const detailDialogVisible = ref(false);
  const editDialogVisible = ref(false);
const roomList = ref([])
  const roomList = ref([]);
// 对话框标题
const dialogTitle = ref('')
  const dialogTitle = ref("");
// 当前查看的草稿
const currentDraft = ref(null)
  const currentDraft = ref(null);
// 表单引用
const meetingFormRef = ref(null)
  const meetingFormRef = ref(null);
// 时间选项(以半小时为间隔,工作时间8:00-18:00)
const timeOptions = ref([])
  const timeOptions = ref([]);
// 表单数据
const meetingForm = reactive({
  id: '',
  meetingId: '',
  title: '',
  roomId: '',
  host: '',
  meetingDate: '',
  startTime: '',
  endTime: '',
    id: "",
    meetingId: "",
    title: "",
    roomId: "",
    host: "",
    meetingDate: "",
    startTime: "",
    endTime: "",
  participants: 0,
  participantList: '',
  description: '',
  createTime: ''
})
    participantList: "",
    description: "",
    createTime: "",
  });
// 表单校验规则
const rules = {
  title: [{ required: true, message: '请输入会议主题', trigger: 'blur' }],
  roomId: [{ required: true, message: '请选择会议室', trigger: 'change' }],
  host: [{ required: true, message: '请输入主持人', trigger: 'blur' }],
  meetingDate: [{ required: true, message: '请选择会议日期', trigger: 'change' }],
  startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
  endTime: [{ required: true, message: '请选择结束时间', trigger: 'change' }]
}
    title: [{ required: true, message: "请输入会议主题", trigger: "blur" }],
    roomId: [{ required: true, message: "请选择会议室", trigger: "change" }],
    host: [{ required: true, message: "请输入主持人", trigger: "blur" }],
    meetingDate: [
      { required: true, message: "请选择会议日期", trigger: "change" },
    ],
    startTime: [{ required: true, message: "请选择开始时间", trigger: "change" }],
    endTime: [{ required: true, message: "请选择结束时间", trigger: "change" }],
  };
// 初始化时间选项(以半小时为间隔,工作时间8:00-18:00)
const initTimeOptions = () => {
  const options = []
    const options = [];
  for (let hour = 8; hour <= 18; hour++) {
    // 每个小时添加两个选项:整点和半点
    options.push({
      value: `${hour.toString().padStart(2, '0')}:00`,
      label: `${hour.toString().padStart(2, '0')}:00`
    })
        value: `${hour.toString().padStart(2, "0")}:00`,
        label: `${hour.toString().padStart(2, "0")}:00`,
      });
    if (hour < 18) { // 18:00之后没有半点选项
      if (hour < 18) {
        // 18:00之后没有半点选项
      options.push({
        value: `${hour.toString().padStart(2, '0')}:30`,
        label: `${hour.toString().padStart(2, '0')}:30`
      })
          value: `${hour.toString().padStart(2, "0")}:30`,
          label: `${hour.toString().padStart(2, "0")}:30`,
        });
    }
  }
  timeOptions.value = options
}
    timeOptions.value = options;
  };
// 禁用日期(禁用今天之前的日期)
const disabledDate = (time) => {
  const disabledDate = time => {
  // 禁用今天之前的日期
  return time.getTime() < Date.now() - 86400000
}
    return time.getTime() < Date.now() - 86400000;
  };
// 查询数据
const getList = async () => {
  loading.value = true
    loading.value = true;
  let resp = await getDraftList({...queryParams,...searchForm})
  queryParams.current = resp.data.current
    let resp = await getDraftList({ ...queryParams, ...searchForm });
    queryParams.current = resp.data.current;
  draftList.value = resp.data.records.map(it=>{
    it.room = roomList.value.find(room=>it.roomId===room.id).name ?? ""
    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format("HH:mm")} ~ ${dayjs(it.endTime).format("HH:mm")}`
    return it
  })
      it.room = roomList.value.find(room => it.roomId === room.id).name ?? "";
      it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format(
        "HH:mm"
      )} ~ ${dayjs(it.endTime).format("HH:mm")}`;
      return it;
    });
  loading.value = false
}
    loading.value = false;
  };
// 搜索按钮操作
const handleSearch = () => {
  queryParams.pageNum = 1
  getList()
}
    queryParams.pageNum = 1;
    getList();
  };
// 重置搜索表单
const resetSearch = () => {
  Object.assign(searchForm, {
    title: '',
    createTime: []
  })
  handleSearch()
}
      title: "",
      createTime: [],
    });
    handleSearch();
  };
// 添加按钮操作
const handleAdd = () => {
  dialogTitle.value = '新建草稿'
  resetForm()
  editDialogVisible.value = true
}
    dialogTitle.value = "新建草稿";
    resetForm();
    editDialogVisible.value = true;
  };
// 查看草稿详情
const viewDraft = (row) => {
  currentDraft.value = row
  detailDialogVisible.value = true
}
  const viewDraft = row => {
    currentDraft.value = row;
    detailDialogVisible.value = true;
  };
// 编辑草稿
const editDraft = (row) => {
  dialogTitle.value = '编辑草稿'
  const editDraft = row => {
    dialogTitle.value = "编辑草稿";
  Object.assign(meetingForm, {
    id: row.id,
    meetingId: row.meetingId,
@@ -363,84 +397,85 @@
    room: row.room,
    roomId: row.id,
    host: row.host,
    meetingDate: row.meetingTime.split(' ')[0],
    startTime: row.meetingTime.split(' ')[1],
    endTime: row.meetingTime.split(' ')[3],
      meetingDate: row.meetingTime.split(" ")[0],
      startTime: row.meetingTime.split(" ")[1],
      endTime: row.meetingTime.split(" ")[3],
    participants: row.participants,
    participantList: row.participantList,
    description: row.description,
    createTime: row.createTime
  })
  editDialogVisible.value = true
}
      createTime: row.createTime,
    });
    editDialogVisible.value = true;
  };
// 删除草稿
const deleteDraft = (row) => {
  ElMessageBox.confirm(
    `确认删除会议草稿 "${row.title}"?`,
    '删除草稿',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    delDraft(row.id).then(resp=>{
      ElMessage.success('草稿删除成功')
      getList()
  const deleteDraft = row => {
    ElMessageBox.confirm(`确认删除会议草稿 "${row.title}"?`, "删除草稿", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
  }).catch(() => {})
}
      .then(() => {
        delDraft(row.id).then(resp => {
          ElMessage.success("草稿删除成功");
          getList();
        });
      })
      .catch(() => {});
  };
// 重置表单
const resetForm = () => {
  Object.assign(meetingForm, {
    id: '',
    meetingId: '',
    title: '',
    room: '',
    host: '',
    meetingDate: '',
    startTime: '',
    endTime: '',
      id: "",
      meetingId: "",
      title: "",
      room: "",
      host: "",
      meetingDate: "",
      startTime: "",
      endTime: "",
    participants: 0,
    participantList: '',
    description: '',
    createTime: ''
  })
}
      participantList: "",
      description: "",
      createTime: "",
    });
  };
// 提交表单
const submitForm = () => {
  meetingFormRef.value.validate((valid) => {
    meetingFormRef.value.validate(valid => {
    if (valid) {
      let formData = {...meetingForm}
      formData.startTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.startTime).format("YYYY-MM-DD HH:mm:ss")
      formData.endTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.endTime).format("YYYY-MM-DD HH:mm:ss")
        let formData = { ...meetingForm };
        formData.startTime = dayjs(
          meetingForm.meetingDate + " " + meetingForm.startTime
        ).format("YYYY-MM-DD HH:mm:ss");
        formData.endTime = dayjs(
          meetingForm.meetingDate + " " + meetingForm.endTime
        ).format("YYYY-MM-DD HH:mm:ss");
      saveDraft(formData).then(()=>{
        ElMessage.success('保存成功')
        editDialogVisible.value = false
        getList()
      })
          ElMessage.success("保存成功");
          editDialogVisible.value = false;
          getList();
        });
    }
  })
}
    });
  };
// 格式化日期时间
const formatDateTime = (dateTime) => {
  if (!dateTime) return ''
  return dateTime.replace(' ', '\n')
}
  const formatDateTime = dateTime => {
    if (!dateTime) return "";
    return dateTime.replace(" ", "\n");
  };
// 页面加载时获取数据
onMounted(() => {
  initTimeOptions()
  getList()
  getRoomEnum().then((res) => {
    roomList.value = res.data
  })
})
    initTimeOptions();
    getList();
    getRoomEnum().then(res => {
      roomList.value = res.data;
    });
  });
</script>
<style scoped>
src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
@@ -4,184 +4,216 @@
    <div class="page-header">
      <h2>会议发布</h2>
    </div>
    <!-- 搜索区域 -->
    <el-card class="search-card">
      <el-form :model="searchForm" inline>
      <el-form :model="searchForm"
               inline>
        <el-form-item label="会议主题">
          <el-input v-model="searchForm.title" placeholder="请输入会议主题" clearable/>
          <el-input v-model="searchForm.title"
                    placeholder="请输入会议主题"
                    clearable />
        </el-form-item>
        <el-form-item label="申请人">
          <el-input v-model="searchForm.applicant" placeholder="请输入申请人" clearable/>
          <el-input v-model="searchForm.applicant"
                    placeholder="请输入申请人"
                    clearable />
        </el-form-item>
        <el-form-item label="发布状态">
          <el-select style="width: 100px" v-model="searchForm.status" placeholder="请选择发布状态" clearable>
            <el-option label="待发布" value="0"/>
            <el-option label="已发布" value="1"/>
          <el-select style="width: 100px"
                     v-model="searchForm.status"
                     placeholder="请选择发布状态"
                     clearable>
            <el-option label="待发布"
                       value="0" />
            <el-option label="已发布"
                       value="1" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- 会议发布列表 -->
    <el-card>
      <el-table v-loading="loading" :data="approvalList" border>
        <el-table-column prop="title" label="会议主题" align="center" min-width="200" show-overflow-tooltip/>
        <el-table-column prop="applicant" label="申请人" align="center" width="120"/>
        <el-table-column prop="host" label="主理人" align="center" width="120"/>
        <el-table-column prop="meetingTime" label="会议时间" align="center" width="180">
      <el-table v-loading="loading"
                :data="approvalList"
                border>
        <el-table-column prop="title"
                         label="会议主题"
                         align="center"
                         min-width="200"
                         show-overflow-tooltip />
        <el-table-column prop="applicant"
                         label="申请人"
                         align="center"
                         width="120" />
        <el-table-column prop="host"
                         label="主理人"
                         align="center"
                         width="120" />
        <el-table-column prop="meetingTime"
                         label="会议时间"
                         align="center"
                         width="180">
          <template #default="scope">
            {{ formatDateTime(scope.row.meetingTime) }}
          </template>
        </el-table-column>
        <el-table-column prop="location" label="会议地点" align="center" width="150"/>
        <el-table-column prop="participants" label="参会人数" align="center" width="100">
        <el-table-column prop="location"
                         label="会议地点"
                         align="center"
                         width="150" />
        <el-table-column prop="participants"
                         label="参会人数"
                         align="center"
                         width="100">
          <template #default="scope">
            {{ scope.row.participants.length }}人
          </template>
        </el-table-column>
        <el-table-column prop="status" label="发布状态" align="center" width="120">
        <el-table-column prop="status"
                         label="发布状态"
                         align="center"
                         width="120">
          <template #default="scope">
            <el-tag :type="getStatusType(scope.row.status)">
              {{ getStatusText(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" width="200" fixed="right">
        <el-table-column label="操作"
                         align="center"
                         width="200"
                         fixed="right">
          <template #default="scope">
            <el-button type="primary" link @click="viewDetail(scope.row)">查看</el-button>
            <el-button
                v-if="scope.row.status == '0'"
            <el-button type="primary"
                       link
                       @click="viewDetail(scope.row)">查看</el-button>
            <el-button v-if="scope.row.status == '0'"
                type="primary"
                link
                @click="handleApproval(scope.row)"
            >
                       @click="handleApproval(scope.row)">
              发布
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
          v-show="total > 0"
      <pagination v-show="total > 0"
          :total="total"
          v-model:page="queryParams.current"
          v-model:limit="queryParams.size"
          @pagination="getList"
      />
                  @pagination="getList" />
    </el-card>
    <!-- 会议详情对话框 -->
    <el-dialog
        title="会议详情"
    <el-dialog title="会议详情"
        v-model="detailDialogVisible"
        width="800px"
    >
               width="800px">
      <div v-if="currentMeeting">
         <el-descriptions label-width="100px" class="meeting-desc" :column="2" border>
          <el-descriptions-item label="会议主题" label-class-name="nowrap-label">{{
        <el-descriptions label-width="100px"
                         class="meeting-desc"
                         :column="2"
                         border>
          <el-descriptions-item label="会议主题"
                                label-class-name="nowrap-label">{{
              currentMeeting.title
            }}</el-descriptions-item>
          <el-descriptions-item label="申请人" label-class-name="nowrap-label">{{
          <el-descriptions-item label="申请人"
                                label-class-name="nowrap-label">{{
              currentMeeting.applicant
            }}</el-descriptions-item>
          <el-descriptions-item label="主理人" label-class-name="nowrap-label">{{
          <el-descriptions-item label="主理人"
                                label-class-name="nowrap-label">{{
              currentMeeting.host
            }}</el-descriptions-item>
          <el-descriptions-item label="会议时间" :span="2" label-class-name="nowrap-label">
          <el-descriptions-item label="会议时间"
                                :span="2"
                                label-class-name="nowrap-label">
            {{ formatDateTime(currentMeeting.meetingTime) }}
          </el-descriptions-item>
          <el-descriptions-item label="会议地点" label-class-name="nowrap-label">{{
          <el-descriptions-item label="会议地点"
                                label-class-name="nowrap-label">{{
              currentMeeting.location
            }}</el-descriptions-item>
          <el-descriptions-item label="参会人数" label-class-name="nowrap-label">{{
          <el-descriptions-item label="参会人数"
                                label-class-name="nowrap-label">{{
              currentMeeting.participants.length
            }}人</el-descriptions-item>
          <el-descriptions-item label="发布状态" label-class-name="nowrap-label">
          <el-descriptions-item label="发布状态"
                                label-class-name="nowrap-label">
            <el-tag :type="getStatusType(currentMeeting.status)">
              {{ getStatusText(currentMeeting.status) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="申请时间" label-class-name="nowrap-label">{{
          <el-descriptions-item label="申请时间"
                                label-class-name="nowrap-label">{{
              currentMeeting.createTime
            }}</el-descriptions-item>
          <el-descriptions-item style="max-height: 400px" label="会议说明" :span="2"
          <el-descriptions-item style="max-height: 400px"
                                label="会议说明"
                                :span="2"
                                label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item>
        </el-descriptions>
        <div class="content-section mt-20">
          <h4>参会人员</h4>
          <div class="participants-list">
            <el-tag
                v-for="participant in currentMeeting.participants"
            <el-tag v-for="participant in currentMeeting.participants"
                :key="participant.id"
                style="margin-right: 10px; margin-bottom: 10px;"
            >
                    style="margin-right: 10px; margin-bottom: 10px;">
              {{ participant.name }}
            </el-tag>
          </div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="detailDialogVisible = false">关 闭</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 会议发布对话框 -->
    <el-dialog
        title="会议发布"
        v-model="approvalDialogVisible"
    >
    <el-dialog title="会议发布"
               v-model="approvalDialogVisible">
      <div v-if="currentMeeting">
        <el-descriptions :column="2" border>
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="会议主题">{{ currentMeeting.title }}</el-descriptions-item>
          <el-descriptions-item label="申请人">{{ currentMeeting.applicant }}</el-descriptions-item>
          <el-descriptions-item label="主理人">{{ currentMeeting.host }}</el-descriptions-item>
          <el-descriptions-item label="会议时间" :span="2">
          <el-descriptions-item label="会议时间"
                                :span="2">
            {{ formatDateTime(currentMeeting.meetingTime) }}
          </el-descriptions-item>
          <el-descriptions-item label="会议地点">{{ currentMeeting.location }}</el-descriptions-item>
          <el-descriptions-item label="参会人数">{{ currentMeeting.participants.length }}人</el-descriptions-item>
        </el-descriptions>
        <div class="content-section mt-20">
          <h4>参会人员</h4>
          <div class="participants-list">
            <el-tag
                v-for="participant in currentMeeting.participants"
            <el-tag v-for="participant in currentMeeting.participants"
                :key="participant.id"
                style="margin-right: 10px; margin-bottom: 10px;"
            >
                    style="margin-right: 10px; margin-bottom: 10px;">
              {{ participant.name }}
            </el-tag>
          </div>
        </div>
        <div class="approval-opinion mt-20">
          <h4>发布意见</h4>
          <el-input
              v-model="publishComment"
          <el-input v-model="publishComment"
              type="textarea"
              placeholder="请输入发布意见"
              :rows="4"
          />
                    :rows="4" />
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitApproval('1')">发 布</el-button>
          <el-button @click="approvalDialogVisible = false">取 消</el-button>
<!--          <el-button type="danger" @click="submitApproval('2')">不通过</el-button>-->
          <el-button type="primary" @click="submitApproval('1')">发 布</el-button>
        </div>
      </template>
    </el-dialog>
@@ -189,167 +221,174 @@
</template>
<script setup>
import {ref, reactive, onMounted} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import Pagination from '@/components/Pagination/index.vue'
import {getRoomEnum, getMeetingPublish,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js'
  import { ref, reactive, onMounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import Pagination from "@/components/Pagination/index.vue";
  import {
    getRoomEnum,
    getMeetingPublish,
    saveMeetingApplication,
  } from "@/api/collaborativeApproval/meeting.js";
import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
import dayjs from "dayjs";
// 数据列表加载状态
const loading = ref(false)
  const loading = ref(false);
// 总条数
const total = ref(0)
const roomEnum = ref([])
const staffList = ref([])
  const total = ref(0);
  const roomEnum = ref([]);
  const staffList = ref([]);
// 发布列表数据
const approvalList = ref([])
  const approvalList = ref([]);
// 查询参数
const queryParams = reactive({
  current: 1,
  size: 10
})
    size: 10,
  });
// 搜索表单
const searchForm = reactive({
  title: '',
  applicant: '',
  status: ''
})
    title: "",
    applicant: "",
    status: "",
  });
// 是否显示对话框
const detailDialogVisible = ref(false)
const approvalDialogVisible = ref(false)
  const detailDialogVisible = ref(false);
  const approvalDialogVisible = ref(false);
// 当前查看的会议
const currentMeeting = ref(null)
  const currentMeeting = ref(null);
// 发布意见
const publishComment = ref('')
  const publishComment = ref("");
// 查询数据
const getList = async () => {
  loading.value = true
  let resp = await getMeetingPublish({...searchForm, ...queryParams})
    loading.value = true;
    let resp = await getMeetingPublish({ ...searchForm, ...queryParams });
  approvalList.value = resp.data.records.map(it => {
    let room = roomEnum.value.find(room => it.roomId === room.id)
    it.location = `${room.name}(${room.location})`
    let staffs = JSON.parse(it.participants)
    it.staffCount = staffs.size
    it.status = it.publishStatus
    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
    it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
      let room = roomEnum.value.find(room => it.roomId === room.id);
      it.location = `${room.name}(${room.location})`;
      let staffs = JSON.parse(it.participants);
      it.staffCount = staffs.size;
      it.status = it.publishStatus;
      it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format(
        "HH:mm:ss"
      )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`;
      it.participants = staffList.value
        .filter(staff => staffs.some(id => id === staff.id))
        .map(staff => {
      return {
        id: staff.id,
        name: `${staff.staffName}(${staff.postJob})`
      }
    })
            name: `${staff.staffName}(${staff.postJob})`,
          };
        });
    return it
  })
  total.value = resp.data.total
  loading.value = false
}
      return it;
    });
    total.value = resp.data.total;
    loading.value = false;
  };
// 搜索按钮操作
const handleSearch = () => {
  queryParams.pageNum = 1
  getList()
}
    queryParams.pageNum = 1;
    getList();
  };
// 重置搜索表单
const resetSearch = () => {
  Object.assign(searchForm, {
    title: '',
    applicant: '',
    status: ''
  })
  handleSearch()
}
      title: "",
      applicant: "",
      status: "",
    });
    handleSearch();
  };
// 查看详情
const viewDetail = (row) => {
  currentMeeting.value = row
  detailDialogVisible.value = true
}
  const viewDetail = row => {
    currentMeeting.value = row;
    detailDialogVisible.value = true;
  };
// 处理发布
const handleApproval = (row) => {
  currentMeeting.value = row
  publishComment.value = ''
  approvalDialogVisible.value = true
}
  const handleApproval = row => {
    currentMeeting.value = row;
    publishComment.value = "";
    approvalDialogVisible.value = true;
  };
// 获取状态类型
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    '0': 'info',     // 待发布
    '1': 'success',  // 已通过
    '2': 'danger',  // 未通过
  }
  return statusMap[status] || 'info'
}
      0: "info", // 待发布
      1: "success", // 已通过
      2: "danger", // 未通过
    };
    return statusMap[status] || "info";
  };
// 获取状态文本
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusMap = {
    '0': '待发布',
    '1': '已发布',
    '2': '已取消',
  }
  return statusMap[status] || '未知'
}
      0: "待发布",
      1: "已发布",
      2: "已取消",
    };
    return statusMap[status] || "未知";
  };
// 格式化日期时间
const formatDateTime = (dateTime) => {
  if (!dateTime) return ''
  return dateTime.replace(' ', '\n')
}
  const formatDateTime = dateTime => {
    if (!dateTime) return "";
    return dateTime.replace(" ", "\n");
  };
// 提交发布
const submitApproval = (status) => {
  const submitApproval = status => {
  // if (status === 'approved' && !publishComment.value.trim()) {
  //   ElMessage.warning('请填写发布意见')
  //   return
  // }
  ElMessageBox.confirm(
      `确认${status === '1' ? '发布' : '取消'}该会议?`,
      '发布确认',
      `确认${status === "1" ? "发布" : "取消"}该会议?`,
      "发布确认",
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }
  ).then(() => {
    )
      .then(() => {
    saveMeetingApplication({
      id: currentMeeting.value.id,
      publishStatus: status,
      publishComment: publishComment.value
          publishComment: publishComment.value,
    }).then(resp=>{
      // 更新会议状态
      currentMeeting.value.status = status
          currentMeeting.value.status = status;
      ElMessage.success('发布提交成功')
      approvalDialogVisible.value = false
      getList()
          ElMessage.success("发布提交成功");
          approvalDialogVisible.value = false;
          getList();
        });
    })
  }).catch(() => {
  })
}
      .catch(() => {});
  };
// 页面加载时获取数据
onMounted(async () => {
  const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()])
  roomEnum.value = resp1.data
  staffList.value = resp2.data
    const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]);
    roomEnum.value = resp1.data;
    staffList.value = resp2.data;
  await getList()
})
    await getList();
  });
</script>
<style scoped>
src/views/collaborativeApproval/notificationManagement/summary/index.vue
@@ -4,157 +4,185 @@
    <div class="page-header">
      <h2>会议纪要</h2>
    </div>
    <!-- 搜索区域 -->
    <el-card class="search-card">
      <el-form :model="searchForm" inline>
      <el-form :model="searchForm"
               inline>
        <el-form-item label="会议主题">
          <el-input v-model="searchForm.title" placeholder="请输入会议主题" clearable />
          <el-input v-model="searchForm.title"
                    placeholder="请输入会议主题"
                    clearable />
        </el-form-item>
        <el-form-item label="申请人">
          <el-input v-model="searchForm.applicant" placeholder="请输入申请人" clearable />
          <el-input v-model="searchForm.applicant"
                    placeholder="请输入申请人"
                    clearable />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- 会议列表 -->
    <el-card>
      <el-table v-loading="loading" :data="meetingList" border>
        <el-table-column prop="title" label="会议主题" align="center" min-width="200" show-overflow-tooltip />
        <el-table-column prop="applicant" label="申请人" align="center" width="120" />
        <el-table-column prop="host" label="主持人" align="center" width="120" />
        <el-table-column prop="meetingTime" label="会议时间" align="center" width="180">
      <el-table v-loading="loading"
                :data="meetingList"
                border>
        <el-table-column prop="title"
                         label="会议主题"
                         align="center"
                         min-width="200"
                         show-overflow-tooltip />
        <el-table-column prop="applicant"
                         label="申请人"
                         align="center"
                         width="120" />
        <el-table-column prop="host"
                         label="主持人"
                         align="center"
                         width="120" />
        <el-table-column prop="meetingTime"
                         label="会议时间"
                         align="center"
                         width="180">
          <template #default="scope">
            {{ formatDateTime(scope.row.meetingTime) }}
          </template>
        </el-table-column>
        <el-table-column prop="location" label="会议地点" align="center" width="150" />
        <el-table-column prop="participants" label="参会人数" align="center" width="100">
        <el-table-column prop="location"
                         label="会议地点"
                         align="center"
                         width="150" />
        <el-table-column prop="participants"
                         label="参会人数"
                         align="center"
                         width="100">
          <template #default="scope">
            {{ scope.row.participants.length }}人
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" width="200" fixed="right">
        <el-table-column label="操作"
                         align="center"
                         width="200"
                         fixed="right">
          <template #default="scope">
            <el-button type="primary" link @click="viewDetail(scope.row)">查看</el-button>
            <el-button
              type="primary"
            <el-button type="primary"
              link
              @click="addMinutes(scope.row)"
            >
                       @click="viewDetail(scope.row)">查看</el-button>
            <el-button type="primary"
                       link
                       @click="addMinutes(scope.row)">
              添加纪要
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
        v-show="total > 0"
      <pagination v-show="total > 0"
        :total="total"
        v-model:page="queryParams.current"
        v-model:limit="queryParams.size"
        @pagination="getList"
      />
                  @pagination="getList" />
    </el-card>
    <!-- 会议详情对话框 -->
    <el-dialog
      title="会议详情"
    <el-dialog title="会议详情"
      v-model="detailDialogVisible"
      width="800px"
    >
               width="800px">
      <div v-if="currentMeeting">
        <el-descriptions label-width="100px" class="meeting-desc" :column="2" border>
          <el-descriptions-item label="会议主题" label-class-name="nowrap-label">{{
        <el-descriptions label-width="100px"
                         class="meeting-desc"
                         :column="2"
                         border>
          <el-descriptions-item label="会议主题"
                                label-class-name="nowrap-label">{{
            currentMeeting.title
          }}</el-descriptions-item>
          <el-descriptions-item label="申请人" label-class-name="nowrap-label">{{
          <el-descriptions-item label="申请人"
                                label-class-name="nowrap-label">{{
            currentMeeting.applicant
          }}</el-descriptions-item>
          <el-descriptions-item label="主持人" label-class-name="nowrap-label">{{
          <el-descriptions-item label="主持人"
                                label-class-name="nowrap-label">{{
            currentMeeting.host
          }}</el-descriptions-item>
          <el-descriptions-item label="会议时间" :span="2" label-class-name="nowrap-label">
          <el-descriptions-item label="会议时间"
                                :span="2"
                                label-class-name="nowrap-label">
            {{ formatDateTime(currentMeeting.meetingTime) }}
          </el-descriptions-item>
          <el-descriptions-item label="会议地点" label-class-name="nowrap-label">{{
          <el-descriptions-item label="会议地点"
                                label-class-name="nowrap-label">{{
            currentMeeting.location
          }}</el-descriptions-item>
          <el-descriptions-item label="参会人数" label-class-name="nowrap-label">{{
          <el-descriptions-item label="参会人数"
                                label-class-name="nowrap-label">{{
            currentMeeting.participants.length
          }}人</el-descriptions-item>
          <el-descriptions-item label="审批状态" label-class-name="nowrap-label">
          <el-descriptions-item label="审批状态"
                                label-class-name="nowrap-label">
            <el-tag :type="getStatusType(currentMeeting.status)">
              {{ getStatusText(currentMeeting.status) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="申请时间" label-class-name="nowrap-label">{{
          <el-descriptions-item label="申请时间"
                                label-class-name="nowrap-label">{{
            currentMeeting.createTime
          }}</el-descriptions-item>
          <el-descriptions-item style="max-height: 400px" label="会议说明" :span="2"
          <el-descriptions-item style="max-height: 400px"
                                label="会议说明"
                                :span="2"
            label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item>
        </el-descriptions>
        <div class="content-section mt-20">
          <h4>参会人员</h4>
          <div class="participants-list">
            <el-tag
              v-for="participant in currentMeeting.participants"
            <el-tag v-for="participant in currentMeeting.participants"
              :key="participant.id"
              style="margin-right: 10px; margin-bottom: 10px;"
            >
                    style="margin-right: 10px; margin-bottom: 10px;">
              {{ participant.name }}
            </el-tag>
          </div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="detailDialogVisible = false">关 闭</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 添加会议纪要对话框 -->
    <el-dialog
      title="添加会议纪要"
    <el-dialog title="添加会议纪要"
      v-model="minutesDialogVisible"
      width="80%"
      @close="handleCloseMinutesDialog"
    >
               @close="handleCloseMinutesDialog">
      <div v-if="currentMeeting">
        <el-descriptions :column="2" border>
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="会议主题">{{ currentMeeting.title }}</el-descriptions-item>
          <el-descriptions-item label="申请人">{{ currentMeeting.applicant }}</el-descriptions-item>
          <el-descriptions-item label="主持人">{{ currentMeeting.host }}</el-descriptions-item>
          <el-descriptions-item label="会议时间" :span="2">
          <el-descriptions-item label="会议时间"
                                :span="2">
            {{ formatDateTime(currentMeeting.meetingTime) }}
          </el-descriptions-item>
          <el-descriptions-item label="会议地点">{{ currentMeeting.location }}</el-descriptions-item>
          <el-descriptions-item label="参会人数">{{ currentMeeting.participants.length }}人</el-descriptions-item>
        </el-descriptions>
        <div class="content-section mt-20">
          <h4>会议纪要内容</h4>
          <div class="editor-container">
            <Editor
              v-model="minutesContent"
              :min-height="400"
            />
            <Editor v-model="minutesContent"
                    :min-height="400" />
          </div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitMinutes">保 存</el-button>
          <el-button @click="minutesDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="submitMinutes">保 存</el-button>
        </div>
      </template>
    </el-dialog>
@@ -162,101 +190,110 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import Pagination from '@/components/Pagination/index.vue'
import Editor from '@/components/Editor/index.vue'
import { getRoomEnum, getMeetingPublish ,getMeetingMinutesByMeetingId,saveMeetingMinutes} from '@/api/collaborativeApproval/meeting.js'
import { getStaffOnJob } from "@/api/personnelManagement/onboarding.js"
import dayjs from "dayjs"
  import { ref, reactive, onMounted } from "vue";
  import { ElMessage } from "element-plus";
  import Pagination from "@/components/Pagination/index.vue";
  import Editor from "@/components/Editor/index.vue";
  import {
    getRoomEnum,
    getMeetingPublish,
    getMeetingMinutesByMeetingId,
    saveMeetingMinutes,
  } from "@/api/collaborativeApproval/meeting.js";
  import { getStaffOnJob } from "@/api/personnelManagement/onboarding.js";
  import dayjs from "dayjs";
// 数据列表加载状态
const loading = ref(false)
  const loading = ref(false);
// 总条数
const total = ref(0)
const roomEnum = ref([])
const staffList = ref([])
  const total = ref(0);
  const roomEnum = ref([]);
  const staffList = ref([]);
// 会议列表数据
const meetingList = ref([])
  const meetingList = ref([]);
// 查询参数
const queryParams = reactive({
  current: 1,
  size: 10
})
    size: 10,
  });
// 搜索表单
const searchForm = reactive({
  title: '',
  applicant: '',
    title: "",
    applicant: "",
  // status: '1' // 默认只显示已通过审批的会议
})
  });
// 是否显示对话框
const detailDialogVisible = ref(false)
const minutesDialogVisible = ref(false)
  const detailDialogVisible = ref(false);
  const minutesDialogVisible = ref(false);
// 当前查看的会议
const currentMeeting = ref(null)
  const currentMeeting = ref(null);
// 会议纪要内容
const minutesContent = ref('')
const minutesContentId = ref('')
  const minutesContent = ref("");
  const minutesContentId = ref("");
// 查询数据
const getList = async () => {
  loading.value = true
  let resp = await getMeetingPublish({ ...searchForm, ...queryParams })
    loading.value = true;
    let resp = await getMeetingPublish({ ...searchForm, ...queryParams });
  meetingList.value = resp.data.records.map(it => {
    let room = roomEnum.value.find(room => it.roomId === room.id)
    it.location = `${room.name}(${room.location})`
    let staffs = JSON.parse(it.participants)
    it.staffCount = staffs.size
    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
    it.participants = staffList.value.filter(staff => staffs.some(id => id === staff.id)).map(staff => {
      let room = roomEnum.value.find(room => it.roomId === room.id);
      it.location = `${room.name}(${room.location})`;
      let staffs = JSON.parse(it.participants);
      it.staffCount = staffs.size;
      it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format(
        "HH:mm:ss"
      )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`;
      it.participants = staffList.value
        .filter(staff => staffs.some(id => id === staff.id))
        .map(staff => {
      return {
        id: staff.id,
        name: `${staff.staffName}(${staff.postJob})`
      }
    })
            name: `${staff.staffName}(${staff.postJob})`,
          };
        });
    return it
  })
  total.value = resp.data.total
  loading.value = false
}
      return it;
    });
    total.value = resp.data.total;
    loading.value = false;
  };
// 搜索按钮操作
const handleSearch = () => {
  queryParams.current = 1
  getList()
}
    queryParams.current = 1;
    getList();
  };
// 重置搜索表单
const resetSearch = () => {
  Object.assign(searchForm, {
    title: '',
    applicant: '',
      title: "",
      applicant: "",
    // status: '1'
  })
  handleSearch()
}
    });
    handleSearch();
  };
// 查看详情
const viewDetail = (row) => {
  currentMeeting.value = row
  detailDialogVisible.value = true
}
  const viewDetail = row => {
    currentMeeting.value = row;
    detailDialogVisible.value = true;
  };
// 添加会议纪要
const addMinutes = async (row) => {
  let resp = await getMeetingMinutesByMeetingId(row.id)
  currentMeeting.value = row
  const addMinutes = async row => {
    let resp = await getMeetingMinutesByMeetingId(row.id);
    currentMeeting.value = row;
  if (resp.data){
    minutesContent.value = resp.data.content
    minutesContentId.value = resp.data.id
      minutesContent.value = resp.data.content;
      minutesContentId.value = resp.data.id;
  }else {
    minutesContent.value = `<h2>${row.title}会议纪要</h2>
<p><strong>会议时间:</strong>${row.meetingTime}</p>
@@ -264,7 +301,7 @@
<p><strong>主持人:</strong>${row.host}</p>
<p><strong>参会人员:</strong></p>
<ol>
  ${row.participants.map(p => `<li>${p.name}</li>`).join('')}
    ${row.participants.map(p => `<li>${p.name}</li>`).join("")}
</ol>
<p><strong>会议内容:</strong></p>
<ol>
@@ -281,72 +318,71 @@
    </ul>
  </li>
</ol>
<p><strong>备注:</strong></p>`
  <p><strong>备注:</strong></p>`;
  }
  minutesDialogVisible.value = true
}
    minutesDialogVisible.value = true;
  };
// 提交会议纪要
const submitMinutes = () => {
  if (!minutesContent.value) {
    ElMessage.warning('请输入会议纪要内容')
    return
      ElMessage.warning("请输入会议纪要内容");
      return;
  }
  saveMeetingMinutes({
    id: minutesContentId.value,
    content: minutesContent.value,
    meetingId: currentMeeting.value.id,
    title: currentMeeting.value.title
      title: currentMeeting.value.title,
  }).then(resp=>{
    console.log('会议纪要内容:', minutesContent.value)
    ElMessage.success('会议纪要保存成功')
    minutesDialogVisible.value = false
  })
}
      console.log("会议纪要内容:", minutesContent.value);
      ElMessage.success("会议纪要保存成功");
      minutesDialogVisible.value = false;
    });
  };
// 关闭会议纪要对话框
const handleCloseMinutesDialog = () => {
  minutesContent.value = ''
}
    minutesContent.value = "";
  };
// 获取状态类型
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    '0': 'info',     // 待审批
    '1': 'success',  // 已通过
    '2': 'warning',  // 未通过
    '3': 'danger'   // 取消
  }
  return statusMap[status] || 'info'
}
      0: "info", // 待审批
      1: "success", // 已通过
      2: "warning", // 未通过
      3: "danger", // 取消
    };
    return statusMap[status] || "info";
  };
// 获取状态文本
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusMap = {
    '0': '待审批',
    '1': '已通过',
    '2': '未通过',
    '3': '已取消'
  }
  return statusMap[status] || '未知'
}
      0: "待审批",
      1: "已通过",
      2: "未通过",
      3: "已取消",
    };
    return statusMap[status] || "未知";
  };
// 格式化日期时间
const formatDateTime = (dateTime) => {
  if (!dateTime) return ''
  return dateTime.replace(' ', '\n')
}
  const formatDateTime = dateTime => {
    if (!dateTime) return "";
    return dateTime.replace(" ", "\n");
  };
// 页面加载时获取数据
onMounted(async () => {
  const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()])
  roomEnum.value = resp1.data
  staffList.value = resp2.data
    const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]);
    roomEnum.value = resp1.data;
    staffList.value = resp2.data;
  await getList()
})
    await getList();
  });
</script>
<style scoped>
src/views/collaborativeApproval/officeSupplies/index.vue
@@ -4,175 +4,241 @@
      <template #header>
        <div class="card-header">
          <span>办公物资申请管理</span>
          <el-button type="primary" @click="openShow()">
            <el-icon><Plus /></el-icon>
          <el-button type="primary"
                     @click="openShow()">
            <el-icon>
              <Plus />
            </el-icon>
            新建申请
          </el-button>
        </div>
      </template>
             <!-- 搜索区域 -->
       <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
         <el-form-item label="申请编号" prop="code">
           <el-input
             v-model="queryParams.code"
      <el-form :model="queryParams"
               ref="queryRef"
               :inline="true"
               v-show="showSearch">
        <el-form-item label="申请编号"
                      prop="code">
          <el-input v-model="queryParams.code"
             placeholder="请输入申请编号"
             clearable
             style="width: 200px"
             @keyup.enter="handleQuery"
           />
                    @keyup.enter="handleQuery" />
         </el-form-item>
         <el-form-item label="申请人" prop="applicant">
           <el-input
             v-model="queryParams.applicant"
        <el-form-item label="申请人"
                      prop="applicant">
          <el-input v-model="queryParams.applicant"
             placeholder="请输入申请人"
             clearable
             style="width: 200px"
             @keyup.enter="handleQuery"
           />
                    @keyup.enter="handleQuery" />
         </el-form-item>
         <el-form-item label="申请状态" prop="status">
           <el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 200px">
             <el-option label="待审批" value="1" />
             <el-option label="已通过" value="3" />
             <el-option label="已拒绝" value="2" />
             <el-option label="已发放" value="4" />
        <el-form-item label="申请状态"
                      prop="status">
          <el-select v-model="queryParams.status"
                     placeholder="请选择状态"
                     clearable
                     style="width: 200px">
            <el-option label="待审批"
                       value="1" />
            <el-option label="已通过"
                       value="3" />
            <el-option label="已拒绝"
                       value="2" />
            <el-option label="已发放"
                       value="4" />
           </el-select>
         </el-form-item>
         <el-form-item>
           <el-button type="primary" @click="handleQuery">
             <el-icon><Search /></el-icon>
          <el-button type="primary"
                     @click="handleQuery">
            <el-icon>
              <Search />
            </el-icon>
             搜索
           </el-button>
           <el-button @click="resetQuery">
             <el-icon><Refresh /></el-icon>
            <el-icon>
              <Refresh />
            </el-icon>
             重置
           </el-button>
         </el-form-item>
         <el-form-item>
            <el-button type="primary" @click="handleExport">
            <el-icon><Download /></el-icon>
          <el-button type="primary"
                     @click="handleExport">
            <el-icon>
              <Download />
            </el-icon>
            导出
          </el-button>
         </el-form-item>
       </el-form>
      <!-- 表格区域 -->
      <el-table
        v-loading="loading"
      <el-table v-loading="loading"
        :data="officeList"
        @selection-change="handleSelectionChange"
        style="width: 100%"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="申请编号" align="center" prop="code" width="180" />
        <el-table-column label="申请人" align="center" prop="applicant" width="120" />
        <el-table-column label="部门" align="center" prop="dept" width="120" />
        <el-table-column label="物资类型" align="center" prop="materialType" width="120">
                style="width: 100%">
        <el-table-column type="selection"
                         width="55"
                         align="center" />
        <el-table-column label="申请编号"
                         align="center"
                         prop="code"
                         width="180" />
        <el-table-column label="申请人"
                         align="center"
                         prop="applicant"
                         width="120" />
        <el-table-column label="部门"
                         align="center"
                         prop="dept"
                         width="120" />
        <el-table-column label="物资类型"
                         align="center"
                         prop="materialType"
                         width="120">
          <template #default="scope">
            <el-tag v-if="scope.row.materialType === 1" type="info">其他</el-tag>
            <el-tag v-if="scope.row.materialType === 2" type="success">清洁用品</el-tag>
            <el-tag v-if="scope.row.materialType === 3" type="warning">电子设备</el-tag>
            <el-tag v-if="scope.row.materialType === 4" type="danger">办公用品</el-tag>
            <el-tag v-if="scope.row.materialType === 1"
                    type="info">其他</el-tag>
            <el-tag v-if="scope.row.materialType === 2"
                    type="success">清洁用品</el-tag>
            <el-tag v-if="scope.row.materialType === 3"
                    type="warning">电子设备</el-tag>
            <el-tag v-if="scope.row.materialType === 4"
                    type="danger">办公用品</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="申请数量" align="center" prop="applyNum" width="100" />
        <el-table-column label="申请原因" align="center" prop="reason" min-width="200" show-overflow-tooltip />
        <el-table-column label="申请状态" align="center" prop="status" width="100">
        <el-table-column label="申请数量"
                         align="center"
                         prop="applyNum"
                         width="100" />
        <el-table-column label="申请原因"
                         align="center"
                         prop="reason"
                         min-width="200"
                         show-overflow-tooltip />
        <el-table-column label="申请状态"
                         align="center"
                         prop="status"
                         width="100">
          <template #default="scope">
            <el-tag :type="getStatusType(scope.row.status)">
              {{ getStatusText(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="申请时间" align="center" prop="applyTime" width="180" />
        <el-table-column label="审批人" align="center" prop="approval" width="120" />
        <el-table-column label="审批时间" align="center" prop="approvalTime" width="180" />
        <el-table-column label="发放时间" align="center" prop="issueTime" width="180" />
        <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width" width="200">
        <el-table-column label="申请时间"
                         align="center"
                         prop="applyTime"
                         width="180" />
        <el-table-column label="审批人"
                         align="center"
                         prop="approval"
                         width="120" />
        <el-table-column label="审批时间"
                         align="center"
                         prop="approvalTime"
                         width="180" />
        <el-table-column label="发放时间"
                         align="center"
                         prop="issueTime"
                         width="180" />
        <el-table-column label="操作"
                         align="center"
                         fixed="right"
                         class-name="small-padding fixed-width"
                         width="200">
          <template #default="scope">
            <el-button
              v-if="scope.row.status === 1"
            <el-button v-if="scope.row.status === 1"
              type="primary"
              link
              @click="handleApprove(scope.row)"
            >
                       @click="handleApprove(scope.row)">
              审批
            </el-button>
            <el-button
              v-if="scope.row.status === 3"
            <el-button v-if="scope.row.status === 3"
              type="success"
                            link
              @click="handleIssue(scope.row)"
            >
                       @click="handleIssue(scope.row)">
              发放
            </el-button>
            <el-button
              type="info"
            <el-button type="info"
                            link
              @click="handleDetail(scope.row)"
            >
                       @click="handleDetail(scope.row)">
              详情
            </el-button>
            <el-button
              v-if="scope.row.status === 2"
            <el-button v-if="scope.row.status === 2"
              type="danger"
                            link
              @click="handleDelete(scope.row)"
            >
                       @click="handleDelete(scope.row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
        v-show="total > 0"
      <pagination v-show="total > 0"
        :total="total"
        v-model:page="queryParams.current"
        v-model:limit="queryParams.size"
        @pagination="getList"
      />
                  @pagination="getList" />
    </el-card>
    <!-- 申请对话框 -->
    <el-dialog
      v-model="showApplyDialog"
    <el-dialog v-model="showApplyDialog"
      title="办公物资申请"
      width="600px"
      append-to-body
    >
      <el-form ref="applyFormRef" :model="applyForm" :rules="applyRules" label-width="100px">
        <el-form-item label="申请人" prop="applicant">
          <el-input v-model="applyForm.applicant" placeholder="请输入申请人名称" />
               append-to-body>
      <el-form ref="applyFormRef"
               :model="applyForm"
               :rules="applyRules"
               label-width="100px">
        <el-form-item label="申请人"
                      prop="applicant">
          <el-input v-model="applyForm.applicant"
                    placeholder="请输入申请人名称" />
        </el-form-item>
        <el-form-item label="部门" prop="dept">
          <el-input v-model="applyForm.dept" placeholder="请输入部门名称" />
        <el-form-item label="部门"
                      prop="dept">
          <el-input v-model="applyForm.dept"
                    placeholder="请输入部门名称" />
        </el-form-item>
        <el-form-item label="物资类型" prop="materialType">
          <el-select v-model="applyForm.materialType" placeholder="请选择物资类型" style="width: 100%">
            <el-option label="办公用品" value="4" />
            <el-option label="电子设备" value="3" />
            <el-option label="清洁用品" value="2" />
            <el-option label="其他" value="1" />
        <el-form-item label="物资类型"
                      prop="materialType">
          <el-select v-model="applyForm.materialType"
                     placeholder="请选择物资类型"
                     style="width: 100%">
            <el-option label="办公用品"
                       value="4" />
            <el-option label="电子设备"
                       value="3" />
            <el-option label="清洁用品"
                       value="2" />
            <el-option label="其他"
                       value="1" />
          </el-select>
        </el-form-item>
        <el-form-item label="具体物品" prop="itemName">
          <el-input v-model="applyForm.itemName" placeholder="请输入具体物品名称" />
        <el-form-item label="具体物品"
                      prop="itemName">
          <el-input v-model="applyForm.itemName"
                    placeholder="请输入具体物品名称" />
        </el-form-item>
        <el-form-item label="申请数量" prop="applyNum">
          <el-input-number v-model="applyForm.applyNum" :min="1" :max="999" style="width: 100%" />
        <el-form-item label="申请数量"
                      prop="applyNum">
          <el-input-number v-model="applyForm.applyNum"
                           :min="1"
                           :max="999"
                           style="width: 100%" />
        </el-form-item>
        <el-form-item label="申请原因" prop="reason">
          <el-input
            v-model="applyForm.reason"
        <el-form-item label="申请原因"
                      prop="reason">
          <el-input v-model="applyForm.reason"
            type="textarea"
            :rows="3"
            placeholder="请输入申请原因"
          />
                    placeholder="请输入申请原因" />
        </el-form-item>
        <el-form-item label="紧急程度" prop="urgency">
        <el-form-item label="紧急程度"
                      prop="urgency">
          <el-radio-group v-model="applyForm.urgency">
            <el-radio label="1">普通</el-radio>
            <el-radio label="2">紧急</el-radio>
@@ -182,58 +248,59 @@
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitApply">确 定</el-button>
          <el-button @click="showApplyDialog = false">取 消</el-button>
          <el-button type="primary" @click="submitApply">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 审批对话框 -->
    <el-dialog
      v-model="showApproveDialog"
    <el-dialog v-model="showApproveDialog"
      title="审批申请"
      width="500px"
      append-to-body
    >
      <el-form ref="approveFormRef" :model="approveForm" :rules="approveRules" label-width="100px">
        <el-form-item label="审批结果" prop="approveResult">
               append-to-body>
      <el-form ref="approveFormRef"
               :model="approveForm"
               :rules="approveRules"
               label-width="100px">
        <el-form-item label="审批结果"
                      prop="approveResult">
          <el-radio-group v-model="approveForm.approveResult">
            <el-radio label="3">通过</el-radio>
            <el-radio label="2">拒绝</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="审批意见" prop="approvalOpinions">
          <el-input
            v-model="approveForm.approvalOpinions"
        <el-form-item label="审批意见"
                      prop="approvalOpinions">
          <el-input v-model="approveForm.approvalOpinions"
            type="textarea"
            :rows="3"
            placeholder="请输入审批意见"
          />
                    placeholder="请输入审批意见" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitApprove">确 定</el-button>
          <el-button @click="showApproveDialog = false">取 消</el-button>
          <el-button type="primary" @click="submitApprove">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 详情对话框 -->
    <el-dialog
      v-model="showDetailDialog"
    <el-dialog v-model="showDetailDialog"
      title="申请详情"
      width="700px"
      append-to-body
    >
      <el-descriptions :column="2" border>
               append-to-body>
      <el-descriptions :column="2"
                       border>
        <el-descriptions-item label="申请编号">{{ currentDetail.code }}</el-descriptions-item>
        <el-descriptions-item label="申请人">{{ currentDetail.applicant }}</el-descriptions-item>
        <el-descriptions-item label="部门">{{ currentDetail.dept }}</el-descriptions-item>
        <el-descriptions-item label="物资类型">{{ currentDetail.materialType }}</el-descriptions-item>
        <el-descriptions-item label="具体物品">{{ currentDetail.itemName }}</el-descriptions-item>
        <el-descriptions-item label="申请数量">{{ currentDetail.applyNum }}</el-descriptions-item>
        <el-descriptions-item label="申请原因" :span="2">{{ currentDetail.reason }}</el-descriptions-item>
        <el-descriptions-item label="申请原因"
                              :span="2">{{ currentDetail.reason }}</el-descriptions-item>
        <el-descriptions-item label="申请状态">
          <el-tag :type="getStatusType(currentDetail.status)">
            {{ getStatusText(currentDetail.status) }}
@@ -242,7 +309,8 @@
        <el-descriptions-item label="申请时间">{{ currentDetail.applyTime }}</el-descriptions-item>
        <el-descriptions-item label="审批人">{{ currentDetail.approval || '-' }}</el-descriptions-item>
        <el-descriptions-item label="审批时间">{{ currentDetail.approvalTime || '-' }}</el-descriptions-item>
        <el-descriptions-item label="审批意见" :span="2">{{ currentDetail.approvalOpinions || '-' }}</el-descriptions-item>
        <el-descriptions-item label="审批意见"
                              :span="2">{{ currentDetail.approvalOpinions || '-' }}</el-descriptions-item>
        <el-descriptions-item label="发放时间">{{ currentDetail.issueTime || '-' }}</el-descriptions-item>
        <el-descriptions-item label="发放人">{{ currentDetail.issueUser || '-' }}</el-descriptions-item>
      </el-descriptions>
@@ -251,220 +319,235 @@
</template>
<script setup>
import {listPage,add,update,deleteOff} from "@/api/collaborativeApproval/officeSupplies.js"
import {ref, reactive, onMounted, getCurrentInstance} from 'vue'
import Cookies from 'js-cookie'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search, Refresh, Download, Check } from '@element-plus/icons-vue'
  import {
    listPage,
    add,
    update,
    deleteOff,
  } from "@/api/collaborativeApproval/officeSupplies.js";
  import { ref, reactive, onMounted, getCurrentInstance } from "vue";
  import Cookies from "js-cookie";
  import { ElMessage, ElMessageBox } from "element-plus";
  import {
    Plus,
    Search,
    Refresh,
    Download,
    Check,
  } from "@element-plus/icons-vue";
// 响应式数据
const loading = ref(false)
const showSearch = ref(true)
const showApplyDialog = ref(false)
const showApproveDialog = ref(false)
const showDetailDialog = ref(false)
const multipleSelection = ref([])
const officeList = ref([])
const total = ref(0)
const suppliesList = ref([])
const currentDetail = ref({})
  const loading = ref(false);
  const showSearch = ref(true);
  const showApplyDialog = ref(false);
  const showApproveDialog = ref(false);
  const showDetailDialog = ref(false);
  const multipleSelection = ref([]);
  const officeList = ref([]);
  const total = ref(0);
  const suppliesList = ref([]);
  const currentDetail = ref({});
// 查询参数
const queryParams = reactive({
  current: 1,
  size: 10,
  code: '',
  applicant: '',
  status: ''
})
    code: "",
    applicant: "",
    status: "",
  });
// 申请表单
const applyForm = reactive({
  applicant: '',
  dept: '',
  materialType: '',
  itemName: '',
    applicant: "",
    dept: "",
    materialType: "",
    itemName: "",
  applyNum: 1,
  reason: '',
  urgency: '1'
})
    reason: "",
    urgency: "1",
  });
// 审批表单
const approveForm = reactive({
  approveResult: '3',
  approvalOpinions: ''
})
    approveResult: "3",
    approvalOpinions: "",
  });
// 表单校验规则
const applyRules = {
  applicant: [{ required: true, message: '请选择物资类型', trigger: 'blur' }],
  dept: [{ required: true, message: '请选择物资类型', trigger: 'blur' }],
  materialType: [{ required: true, message: '请选择物资类型', trigger: 'change' }],
  itemName: [{ required: true, message: '请输入具体物品名称', trigger: 'blur' }],
  applyNum: [{ required: true, message: '请输入申请数量', trigger: 'blur' }],
  reason: [{ required: true, message: '请输入申请原因', trigger: 'blur' }]
}
    applicant: [{ required: true, message: "请选择物资类型", trigger: "blur" }],
    dept: [{ required: true, message: "请选择物资类型", trigger: "blur" }],
    materialType: [
      { required: true, message: "请选择物资类型", trigger: "change" },
    ],
    itemName: [
      { required: true, message: "请输入具体物品名称", trigger: "blur" },
    ],
    applyNum: [{ required: true, message: "请输入申请数量", trigger: "blur" }],
    reason: [{ required: true, message: "请输入申请原因", trigger: "blur" }],
  };
const approveRules = {
  approveResult: [{ required: true, message: '请选择审批结果', trigger: 'change' }],
  approvalOpinions: [{ required: true, message: '请输入审批意见', trigger: 'blur' }]
}
    approveResult: [
      { required: true, message: "请选择审批结果", trigger: "change" },
    ],
    approvalOpinions: [
      { required: true, message: "请输入审批意见", trigger: "blur" },
    ],
  };
const openShow = () => {
  showApplyDialog.value = true
  resetApplyForm()
}
    showApplyDialog.value = true;
    resetApplyForm();
  };
// 获取列表数据
const getList = () => {
  loading.value = true
    loading.value = true;
  listPage(queryParams).then(res => {
    total.value = res.data.total
    loading.value = false
    officeList.value = res.data.records
  })
}
      total.value = res.data.total;
      loading.value = false;
      officeList.value = res.data.records;
    });
  };
// 查询
const handleQuery = () => {
  queryParams.current = 1
  getList()
}
    queryParams.current = 1;
    getList();
  };
// 重置查询
const resetQuery = () => {
  queryParams.code = ''
  queryParams.applicant = ''
  queryParams.status = ''
  handleQuery()
}
    queryParams.code = "";
    queryParams.applicant = "";
    queryParams.status = "";
    handleQuery();
  };
// 多选
const handleSelectionChange = (selection) => {
  multipleSelection.value = selection
}
  const handleSelectionChange = selection => {
    multipleSelection.value = selection;
  };
// 获取状态类型
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    1: 'warning',
    3: 'success',
    2: 'danger',
    4: 'info'
  }
  return statusMap[status] || 'info'
}
      1: "warning",
      3: "success",
      2: "danger",
      4: "info",
    };
    return statusMap[status] || "info";
  };
// 获取状态文本
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusMap = {
    1: '待审批',
    3: '已通过',
    2: '已拒绝',
    4: '已发放'
  }
  return statusMap[status] || status
}
      1: "待审批",
      3: "已通过",
      2: "已拒绝",
      4: "已发放",
    };
    return statusMap[status] || status;
  };
// 提交申请
const submitApply = () => {
  add(applyForm).then(() => {
    ElMessage.success('申请成功')
    getList()
    showApplyDialog.value = false
    resetApplyForm()
  })
}
      ElMessage.success("申请成功");
      getList();
      showApplyDialog.value = false;
      resetApplyForm();
    });
  };
//重置表单
const resetApplyForm = () => {
  // 重置表单
  Object.assign(applyForm, {
    applicant: '',
    dept: '',
    materialType: '',
    itemName: '',
      applicant: "",
      dept: "",
      materialType: "",
      itemName: "",
    applyNum: 1,
    reason: '',
    urgency: '1'
  })
}
      reason: "",
      urgency: "1",
    });
  };
// 审批
const handleApprove = (row) => {
  currentDetail.value = row
  showApproveDialog.value = true
}
  const handleApprove = row => {
    currentDetail.value = row;
    showApproveDialog.value = true;
  };
const formatDate = (date) => {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  const sends = String(date.getSeconds()).padStart(2, '0')
  return `${year}-${month}-${day} ${hours}:${minutes}:${sends}`
}
  const formatDate = date => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    const hours = String(date.getHours()).padStart(2, "0");
    const minutes = String(date.getMinutes()).padStart(2, "0");
    const sends = String(date.getSeconds()).padStart(2, "0");
    return `${year}-${month}-${day} ${hours}:${minutes}:${sends}`;
  };
// 提交审批
const submitApprove = () => {
  currentDetail.value.status = approveForm.approveResult
    currentDetail.value.status = approveForm.approveResult;
  // 从cookie中获取当前登录用户名称
  currentDetail.value.approval = Cookies.get('username')
  currentDetail.value.approvalTime = formatDate(new Date())
  currentDetail.value.approvalOpinions = approveForm.approvalOpinions
  update(currentDetail.value).then((res) => {
    currentDetail.value.approval = Cookies.get("username");
    currentDetail.value.approvalTime = formatDate(new Date());
    currentDetail.value.approvalOpinions = approveForm.approvalOpinions;
    update(currentDetail.value).then(res => {
    if(res.code === 200){
      showApproveDialog.value = false
      ElMessage.success('审批完成')
      getList()
        showApproveDialog.value = false;
        ElMessage.success("审批完成");
        getList();
      // 重置表单
      Object.assign(approveForm, {
        approveResult: '3',
        approvalOpinions: ''
      })
          approveResult: "3",
          approvalOpinions: "",
        });
    }
  })
}
    });
  };
// 发放
const handleIssue = (row) => {
  row.status = 4
  row.issueTime = formatDate(new Date())
  row.issueUser = Cookies.get('username')
  update(row).then((res) =>{
  const handleIssue = row => {
    row.status = 4;
    row.issueTime = formatDate(new Date());
    row.issueUser = Cookies.get("username");
    update(row).then(res => {
    if(res.code === 200){
      ElMessage.success('发放完成')
      getList()
        ElMessage.success("发放完成");
        getList();
    }
  })
}
    });
  };
// 查看详情
const handleDetail = (row) => {
  currentDetail.value = row
  showDetailDialog.value = true
}
  const handleDetail = row => {
    currentDetail.value = row;
    showDetailDialog.value = true;
  };
// 删除
const handleDelete = (row) => {
  ElMessageBox.confirm('确认删除该申请吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const handleDelete = row => {
    ElMessageBox.confirm("确认删除该申请吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    let ids = [row.id]
    deleteOff(ids).then((res) =>{
      ElMessage.success('删除成功')
      getList()
    })
  })
}
      let ids = [row.id];
      deleteOff(ids).then(res => {
        ElMessage.success("删除成功");
        getList();
      });
    });
  };
const { proxy } = getCurrentInstance();
// 导出
const handleExport = () => {
@@ -479,12 +562,12 @@
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
}
  };
// 页面加载时获取数据
onMounted(() => {
  getList()
})
    getList();
  });
</script>
<style scoped>
src/views/collaborativeApproval/planTemplate/index.vue
@@ -3,34 +3,45 @@
    <!-- 顶部操作栏 -->
    <div class="header-actions">
      <div class="left-actions">
        <el-select v-model="currentLevel" placeholder="选择计划级别" style="width: 150px" @change="handleLevelChange">
          <el-option label="个人计划" value="personal" />
          <el-option label="小组计划" value="group" />
          <el-option label="部门计划" value="department" />
          <el-option label="公司计划" value="company" />
        <el-select v-model="currentLevel"
                   placeholder="选择计划级别"
                   style="width: 150px"
                   @change="handleLevelChange">
          <el-option label="个人计划"
                     value="personal" />
          <el-option label="小组计划"
                     value="group" />
          <el-option label="部门计划"
                     value="department" />
          <el-option label="公司计划"
                     value="company" />
        </el-select>
        <el-select v-model="currentPeriod" placeholder="选择时间周期" style="width: 120px; margin-left: 10px" @change="handlePeriodChange">
          <el-option label="周计划" value="week" />
          <el-option label="月计划" value="month" />
          <el-option label="年计划" value="year" />
        <el-select v-model="currentPeriod"
                   placeholder="选择时间周期"
                   style="width: 120px; margin-left: 10px"
                   @change="handlePeriodChange">
          <el-option label="周计划"
                     value="week" />
          <el-option label="月计划"
                     value="month" />
          <el-option label="年计划"
                     value="year" />
        </el-select>
        <el-date-picker
          v-model="currentDate"
        <el-date-picker v-model="currentDate"
          :type="datePickerType"
          placeholder="选择日期"
          format="YYYY-MM-DD"
          value-format="YYYY-MM-DD"
          style="width: 180px; margin-left: 10px"
          @change="handleDateChange"
        />
                        @change="handleDateChange" />
      </div>
      <div class="right-actions">
        <el-button type="primary" @click="handleAddPlan">新增计划</el-button>
        <el-button type="primary"
                   @click="handleAddPlan">新增计划</el-button>
        <el-button @click="handleExport">导出计划</el-button>
        <!-- <el-button @click="handleShare">共享计划@</el-button> -->
      </div>
    </div>
    <!-- 计划概览卡片 -->
    <div class="overview-cards">
      <el-row :gutter="20">
@@ -38,13 +49,16 @@
          <el-card class="overview-card">
            <div class="card-content">
              <div class="card-icon personal">
                <el-icon><User /></el-icon>
                <el-icon>
                  <User />
                </el-icon>
              </div>
              <div class="card-info">
                <div class="card-title">个人计划</div>
                <div class="card-number">{{ overviewData.personal.total }}</div>
                <div class="card-progress">
                  <el-progress :percentage="overviewData.personal.completion" :stroke-width="6" />
                  <el-progress :percentage="overviewData.personal.completion"
                               :stroke-width="6" />
                </div>
              </div>
            </div>
@@ -54,13 +68,16 @@
          <el-card class="overview-card">
            <div class="card-content">
              <div class="card-icon group">
                <el-icon><UserFilled /></el-icon>
                <el-icon>
                  <UserFilled />
                </el-icon>
              </div>
              <div class="card-info">
                <div class="card-title">小组计划</div>
                <div class="card-number">{{ overviewData.group.total }}</div>
                <div class="card-progress">
                  <el-progress :percentage="overviewData.group.completion" :stroke-width="6" />
                  <el-progress :percentage="overviewData.group.completion"
                               :stroke-width="6" />
                </div>
              </div>
            </div>
@@ -70,13 +87,16 @@
          <el-card class="overview-card">
            <div class="card-content">
              <div class="card-icon department">
                <el-icon><OfficeBuilding /></el-icon>
                <el-icon>
                  <OfficeBuilding />
                </el-icon>
              </div>
              <div class="card-info">
                <div class="card-title">部门计划</div>
                <div class="card-number">{{ overviewData.department.total }}</div>
                <div class="card-progress">
                  <el-progress :percentage="overviewData.department.completion" :stroke-width="6" />
                  <el-progress :percentage="overviewData.department.completion"
                               :stroke-width="6" />
                </div>
              </div>
            </div>
@@ -86,13 +106,16 @@
          <el-card class="overview-card">
            <div class="card-content">
              <div class="card-icon company">
                <el-icon><House /></el-icon>
                <el-icon>
                  <House />
                </el-icon>
              </div>
              <div class="card-info">
                <div class="card-title">公司计划</div>
                <div class="card-number">{{ overviewData.company.total }}</div>
                <div class="card-progress">
                  <el-progress :percentage="overviewData.company.completion" :stroke-width="6" />
                  <el-progress :percentage="overviewData.company.completion"
                               :stroke-width="6" />
                </div>
              </div>
            </div>
@@ -100,7 +123,6 @@
        </el-col>
      </el-row>
    </div>
    <!-- 计划列表 -->
    <div class="plan-content">
      <el-card>
@@ -108,68 +130,82 @@
          <div class="card-header">
            <span>{{ getCurrentLevelText() }} - {{ getCurrentPeriodText() }}</span>
            <div>
              <el-button size="small" @click="handleRefresh">刷新</el-button>
              <el-button size="small"
                         @click="handleRefresh">刷新</el-button>
              <!-- <el-button size="small" @click="handleFilter">筛选@</el-button> -->
            </div>
          </div>
        </template>
        <div class="plan-list">
          <div v-for="plan in planList" :key="plan.id" class="plan-item">
          <div v-for="plan in planList"
               :key="plan.id"
               class="plan-item">
            <div class="plan-header">
              <div class="plan-title">
                <el-tag :type="getPriorityType(plan.priority)" size="small">{{ getPriorityText(plan.priority) }}</el-tag>
                <el-tag :type="getPriorityType(plan.priority)"
                        size="small">{{ getPriorityText(plan.priority) }}</el-tag>
                <span class="title-text">{{ plan.title }}</span>
              </div>
              <div class="plan-actions">
                <el-button size="small" @click="handleEditPlan(plan)">编辑</el-button>
                <el-button size="small" @click="handleViewDetail(plan)">详情</el-button>
                <el-button size="small"
                           @click="handleEditPlan(plan)">编辑</el-button>
                <el-button size="small"
                           @click="handleViewDetail(plan)">详情</el-button>
                <el-dropdown @command="(command) => handleMoreAction(plan, command)">
                  <el-button size="small">
                    更多<el-icon class="el-icon--right"><ArrowDown /></el-icon>
                    更多<el-icon class="el-icon--right">
                      <ArrowDown />
                    </el-icon>
                  </el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <!-- <el-dropdown-item command="share">共享@</el-dropdown-item> -->
                      <el-dropdown-item command="copy">复制</el-dropdown-item>
                      <el-dropdown-item command="delete" divided>删除</el-dropdown-item>
                      <el-dropdown-item command="delete"
                                        divided>删除</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </div>
            <div class="plan-content">
              <div class="plan-description">{{ plan.description }}</div>
              <div class="plan-meta">
                <div class="meta-item">
                  <el-icon><Calendar /></el-icon>
                  <el-icon>
                    <Calendar />
                  </el-icon>
                  <span>{{ plan.startDate }} - {{ plan.endDate }}</span>
                </div>
                <div class="meta-item">
                  <el-icon><User /></el-icon>
                  <el-icon>
                    <User />
                  </el-icon>
                  <span>{{ plan.assignee }}</span>
                </div>
                <div class="meta-item">
                  <el-icon><Clock /></el-icon>
                  <el-icon>
                    <Clock />
                  </el-icon>
                  <span>进度: {{ plan.progress }}%</span>
                </div>
                <div class="meta-item">
                  <el-icon><Flag /></el-icon>
                  <el-icon>
                    <Flag />
                  </el-icon>
                  <span>{{ getStatusText(plan.status) }}</span>
                </div>
              </div>
              <div class="plan-progress">
                <el-progress
                  :percentage="plan.progress"
                <el-progress :percentage="plan.progress"
                  :color="getProgressColor(plan.progress)"
                  :stroke-width="8"
                />
                             :stroke-width="8" />
              </div>
              <div class="plan-tags">
                <el-tag v-for="tag in plan.tags" :key="tag" size="small" style="margin-right: 5px">
                <el-tag v-for="tag in plan.tags"
                        :key="tag"
                        size="small"
                        style="margin-right: 5px">
                  {{ tag }}
                </el-tag>
              </div>
@@ -178,75 +214,96 @@
        </div>
      </el-card>
    </div>
    <!-- 新增/编辑计划对话框 -->
    <el-dialog
      v-model="planDialogVisible"
    <el-dialog v-model="planDialogVisible"
      :title="operationType === 'add' ? '发布计划' : '编辑计划'"
      width="600px"
      @close="handleDialogClose"
    >
      <el-form :model="planForm" :rules="planRules" ref="planFormRef" label-width="100px">
        <el-form-item label="计划标题" prop="title">
          <el-input v-model="planForm.title" placeholder="请输入计划标题" />
               @close="handleDialogClose">
      <el-form :model="planForm"
               :rules="planRules"
               ref="planFormRef"
               label-width="100px">
        <el-form-item label="计划标题"
                      prop="title">
          <el-input v-model="planForm.title"
                    placeholder="请输入计划标题" />
        </el-form-item>
        <el-form-item label="计划描述" prop="description">
          <el-input
            v-model="planForm.description"
        <el-form-item label="计划描述"
                      prop="description">
          <el-input v-model="planForm.description"
            type="textarea"
            :rows="3"
            placeholder="请输入计划描述"
          />
                    placeholder="请输入计划描述" />
        </el-form-item>
        <el-form-item label="计划级别" prop="level">
          <el-select v-model="planForm.level" placeholder="选择计划级别" style="width: 100%">
            <el-option label="个人计划" value="personal" />
            <el-option label="小组计划" value="group" />
            <el-option label="部门计划" value="department" />
            <el-option label="公司计划" value="company" />
        <el-form-item label="计划级别"
                      prop="level">
          <el-select v-model="planForm.level"
                     placeholder="选择计划级别"
                     style="width: 100%">
            <el-option label="个人计划"
                       value="personal" />
            <el-option label="小组计划"
                       value="group" />
            <el-option label="部门计划"
                       value="department" />
            <el-option label="公司计划"
                       value="company" />
          </el-select>
        </el-form-item>
        <el-form-item label="时间周期" prop="period">
          <el-select v-model="planForm.period" placeholder="选择时间周期" style="width: 100%">
            <el-option label="周计划" value="week" />
            <el-option label="月计划" value="month" />
            <el-option label="年计划" value="year" />
        <el-form-item label="时间周期"
                      prop="period">
          <el-select v-model="planForm.period"
                     placeholder="选择时间周期"
                     style="width: 100%">
            <el-option label="周计划"
                       value="week" />
            <el-option label="月计划"
                       value="month" />
            <el-option label="年计划"
                       value="year" />
          </el-select>
        </el-form-item>
        <el-form-item label="开始时间" prop="startDate">
          <el-date-picker
            v-model="planForm.startDate"
        <el-form-item label="开始时间"
                      prop="startDate">
          <el-date-picker v-model="planForm.startDate"
            type="date"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            placeholder="选择开始时间"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="结束时间" prop="endDate">
          <el-date-picker
            v-model="planForm.endDate"
        <el-form-item label="结束时间"
                      prop="endDate">
          <el-date-picker v-model="planForm.endDate"
            type="date"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            placeholder="选择结束时间"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="负责人" prop="assignee">
          <el-input v-model="planForm.assignee" placeholder="请输入负责人" />
        <el-form-item label="负责人"
                      prop="assignee">
          <el-input v-model="planForm.assignee"
                    placeholder="请输入负责人" />
        </el-form-item>
        <el-form-item label="优先级" prop="priority">
          <el-select v-model="planForm.priority" placeholder="选择优先级" style="width: 100%">
            <el-option label="高" value="high" />
            <el-option label="中" value="medium" />
            <el-option label="低" value="low" />
        <el-form-item label="优先级"
                      prop="priority">
          <el-select v-model="planForm.priority"
                     placeholder="选择优先级"
                     style="width: 100%">
            <el-option label="高"
                       value="high" />
            <el-option label="中"
                       value="medium" />
            <el-option label="低"
                       value="low" />
          </el-select>
        </el-form-item>
        <!-- <el-form-item label="标签">
          <el-input v-model="planForm.tags" placeholder="请输入标签,用逗号分隔" />
        </el-form-item> -->
        <el-form-item label="标签" prop="tags">
        <el-form-item label="标签"
                      prop="tags">
          <!-- <el-checkbox-group v-model="planForm.tags">
            <el-checkbox label="all"></el-checkbox>
            <el-checkbox label="manager">管理层</el-checkbox>
@@ -254,50 +311,57 @@
            <el-checkbox label="finance">财务部门</el-checkbox>
            <el-checkbox label="tech">技术部门</el-checkbox>
          </el-checkbox-group> -->
          <el-select
            v-model="planForm.tags"
          <el-select v-model="planForm.tags"
            multiple
            placeholder="请选择标签"
            style="width: 100%"
          >
            <el-option
              v-for="dept in departments"
                     style="width: 100%">
            <el-option v-for="dept in departments"
              :key="dept"
              :label="dept"
              :value="dept"
            />
                       :value="dept" />
          </el-select>
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select v-model="planForm.status" placeholder="选择状态" style="width: 100%">
            <el-option label="未开始" value="not_started" />
            <el-option label="进行中" value="in_progress" />
            <el-option label="已完成" value="completed" />
            <el-option label="已暂停" value="paused" />
        <el-form-item label="状态"
                      prop="status">
          <el-select v-model="planForm.status"
                     placeholder="选择状态"
                     style="width: 100%">
            <el-option label="未开始"
                       value="not_started" />
            <el-option label="进行中"
                       value="in_progress" />
            <el-option label="已完成"
                       value="completed" />
            <el-option label="已暂停"
                       value="paused" />
          </el-select>
        </el-form-item>
        <el-form-item label="进度" prop="progress">
          <el-input-number
            v-model="planForm.progress"
        <el-form-item label="进度"
                      prop="progress">
          <el-input-number v-model="planForm.progress"
            min="0"
            max="100"
            step="1"
            placeholder="请输入进度"
            style="width: 100%"
          />
                           style="width: 100%" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="handleSavePlan">保存</el-button>
          <el-button @click="planDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSavePlan">保存</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 计划详情对话框 -->
    <el-dialog v-model="showPlanDetailDialog" title="计划详情" width="700px">
      <div v-if="currentPlanDetail" class="mb10">
        <el-descriptions :column="2" border>
    <el-dialog v-model="showPlanDetailDialog"
               title="计划详情"
               width="700px">
      <div v-if="currentPlanDetail"
           class="mb10">
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="计划标题">{{ currentPlanDetail.title }}</el-descriptions-item>
          <el-descriptions-item label="计划描述">{{ currentPlanDetail.description }}</el-descriptions-item>
          <el-descriptions-item label="计划级别">{{ getCurrentLevelText(currentPlanDetail.level) }}</el-descriptions-item>
@@ -316,8 +380,8 @@
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
  import { ref, reactive, computed, onMounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
const { proxy } = getCurrentInstance();
import {
  User,
@@ -327,113 +391,130 @@
  Calendar,
  Clock,
  Flag,
  ArrowDown
} from '@element-plus/icons-vue'
import { listDutyPlan, addDutyPlan, updateDutyPlan, delDutyPlan,NumDutyPlan,exportDutyPlan } from '@/api/collaborativeApproval/planTemplate.js'
    ArrowDown,
  } from "@element-plus/icons-vue";
  import {
    listDutyPlan,
    addDutyPlan,
    updateDutyPlan,
    delDutyPlan,
    NumDutyPlan,
    exportDutyPlan,
  } from "@/api/collaborativeApproval/planTemplate.js";
// 响应式数据
const operationType = ref('add')
const currentLevel = ref('personal')
const currentPeriod = ref('week')
const currentDate = ref(new Date())
const planDialogVisible = ref(false)
const dialogTitle = ref('新增计划')
const planFormRef = ref()
const showPlanDetailDialog = ref(false)
const currentPlanDetail = ref(null)
  const operationType = ref("add");
  const currentLevel = ref("personal");
  const currentPeriod = ref("week");
  const currentDate = ref(new Date());
  const planDialogVisible = ref(false);
  const dialogTitle = ref("新增计划");
  const planFormRef = ref();
  const showPlanDetailDialog = ref(false);
  const currentPlanDetail = ref(null);
// 表单数据
const planForm = reactive({
  id: '',
  title: '',
  description: '',
  level: 'personal',
  period: 'week',
  startDate: '',
  endDate: '',
  assignee: '',
  priority: 'medium',
    id: "",
    title: "",
    description: "",
    level: "personal",
    period: "week",
    startDate: "",
    endDate: "",
    assignee: "",
    priority: "medium",
  tags: [],
  status: '',
  progress: 0
})
    status: "",
    progress: 0,
  });
// 表单验证规则
const planRules = {
  title: [{ required: true, message: '请输入计划标题', trigger: 'blur' }],
  description: [{ required: true, message: '请输入计划描述', trigger: 'blur' }],
  level: [{ required: true, message: '请选择计划级别', trigger: 'change' }],
  period: [{ required: true, message: '请选择时间周期', trigger: 'change' }],
  startDate: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
  endDate: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
  assignee: [{ required: true, message: '请输入负责人', trigger: 'blur' }],
  priority: [{ required: true, message: '请选择优先级', trigger: 'change' }]
}
const departments = ["产品", "分析", "调研",'技术', '架构', '设计','市场', '推广', '营销'];
    title: [{ required: true, message: "请输入计划标题", trigger: "blur" }],
    description: [{ required: true, message: "请输入计划描述", trigger: "blur" }],
    level: [{ required: true, message: "请选择计划级别", trigger: "change" }],
    period: [{ required: true, message: "请选择时间周期", trigger: "change" }],
    startDate: [{ required: true, message: "请选择开始时间", trigger: "change" }],
    endDate: [{ required: true, message: "请选择结束时间", trigger: "change" }],
    assignee: [{ required: true, message: "请输入负责人", trigger: "blur" }],
    priority: [{ required: true, message: "请选择优先级", trigger: "change" }],
  };
  const departments = [
    "产品",
    "分析",
    "调研",
    "技术",
    "架构",
    "设计",
    "市场",
    "推广",
    "营销",
  ];
// 概览数据
const overviewData = reactive({
  personal: { total: 0, completion: 0 },
  group: { total: 0, completion: 0 },
  department: { total: 0, completion: 0 },
  company: { total: 0, completion: 0 }
})
    company: { total: 0, completion: 0 },
  });
// 计划列表数据
const planList = ref([])
  const planList = ref([]);
// 计算属性
const datePickerType = computed(() => {
  switch (currentPeriod.value) {
    case 'week':
      return 'week'
    case 'month':
      return 'month'
    case 'year':
      return 'year'
      case "week":
        return "week";
      case "month":
        return "month";
      case "year":
        return "year";
    default:
      return 'date'
        return "date";
  }
})
  });
// 方法
const handleLevelChange = (value) => {
  console.log('计划级别变更:', value)
  getPlanList()
  const handleLevelChange = value => {
    console.log("计划级别变更:", value);
    getPlanList();
  // 这里可以根据级别筛选数据
}
  };
const handlePeriodChange = (value) => {
  console.log('时间周期变更:', value)
  getPlanList()
  const handlePeriodChange = value => {
    console.log("时间周期变更:", value);
    getPlanList();
  // 这里可以根据周期筛选数据
}
  };
const handleDateChange = (value) => {
  console.log('日期变更:', value)
  getPlanList()
  const handleDateChange = value => {
    console.log("日期变更:", value);
    getPlanList();
  // 这里可以根据日期筛选数据
}
  };
const handleAddPlan = () => {
  operationType.value = 'add'
  dialogTitle.value = '新增计划'
  planDialogVisible.value = true
    operationType.value = "add";
    dialogTitle.value = "新增计划";
    planDialogVisible.value = true;
  // 重置表单
  Object.keys(planForm).forEach(key => {
    planForm[key] = ''
  })
  planForm.level = 'personal'
  planForm.period = 'week'
  planForm.priority = 'medium'
  planForm.status = 'not_started'
  planForm.progress = 0
}
      planForm[key] = "";
    });
    planForm.level = "personal";
    planForm.period = "week";
    planForm.priority = "medium";
    planForm.status = "not_started";
    planForm.progress = 0;
  };
const handleEditPlan = (plan) => {
  operationType.value = 'edit'
  dialogTitle.value = '编辑计划'
  planDialogVisible.value = true
  Object.assign(planForm, plan)
  const handleEditPlan = plan => {
    operationType.value = "edit";
    dialogTitle.value = "编辑计划";
    planDialogVisible.value = true;
    Object.assign(planForm, plan);
  // // 填充表单数据
  // Object.keys(planForm).forEach(key => {
  //   if (key === 'tags') {
@@ -442,23 +523,23 @@
  //     planForm[key] = plan[key]
  //   }
  // })
}
  };
const handleViewDetail = (plan) => {
  currentPlanDetail.value = plan
  showPlanDetailDialog.value = true
  const handleViewDetail = plan => {
    currentPlanDetail.value = plan;
    showPlanDetailDialog.value = true;
  // ElMessage.info(`查看计划详情: ${plan.title}`)
}
  };
const handleMoreAction = async(plan,command) => {
  let ids = [];
  ids.push(plan.id);
  console.log("ids",ids)
    console.log("ids", ids);
  switch (command) {
    case 'share':
      ElMessage.success('计划已共享')
      break
    case 'copy':
      case "share":
        ElMessage.success("计划已共享");
        break;
      case "copy":
      const knowledgeText = `
        计划标题:${plan.title}
        计划描述:${plan.description}
@@ -468,76 +549,77 @@
        结束时间:${plan.endDate}
        负责人:${plan.assignee}
        优先级:${getPriorityText(plan.priority)}
        标签:${plan.tags.join(', ')}
          标签:${plan.tags.join(", ")}
        状态:${getStatusText(plan.status)}
        进度:${plan.progress}%
      `.trim();
        // 复制到剪贴板
        navigator.clipboard.writeText(knowledgeText).then(() => {
        navigator.clipboard
          .writeText(knowledgeText)
          .then(() => {
          ElMessage.success("知识内容已复制到剪贴板");
        }).catch(() => {
          })
          .catch(() => {
          ElMessage.error("复制失败,请手动复制");
        });
      // ElMessage.success('计划已复制')
      break
    case 'delete':
      ElMessageBox.confirm('确定要删除这个计划吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
        break;
      case "delete":
        ElMessageBox.confirm("确定要删除这个计划吗?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
      }).then(() => {
        delDutyPlan(ids).then(res => {
          if (res.code === 200) {
            ElMessage.success('计划已删除')
              ElMessage.success("计划已删除");
            ids.value = [];
            getPlanList()
              getPlanList();
          }
        })
      })
      break
          });
        });
        break;
  }
}
  };
//
const handleSavePlan = async () => {
  try {
    await planFormRef.value.validate()
    if (operationType.value === 'add') {
      await planFormRef.value.validate();
      if (operationType.value === "add") {
      addDutyPlan(planForm).then(res => {
        if (res.code === 200) {
          ElMessage.success('计划保存成功')
          planDialogVisible.value = false
            ElMessage.success("计划保存成功");
            planDialogVisible.value = false;
        }
        getPlanList()
      })
          getPlanList();
        });
    } else {
      updateDutyPlan(planForm).then(res => {
        if (res.code === 200) {
          ElMessage.success('计划保存成功')
          planDialogVisible.value = false
            ElMessage.success("计划保存成功");
            planDialogVisible.value = false;
        }
        getPlanList()
      })
          getPlanList();
        });
    }
  } catch (error) {
    console.log('表单验证失败:', error)
      console.log("表单验证失败:", error);
  }
}
  };
const handleDialogClose = () => {
  planFormRef.value?.resetFields()
}
    planFormRef.value?.resetFields();
  };
const handleRefresh = () => {
  getPlanList()
    getPlanList();
  // ElMessage.success('数据已刷新')
}
  };
const handleFilter = () => {
  ElMessage.info('打开筛选面板')
}
    ElMessage.info("打开筛选面板");
  };
const handleExport = () => {
  ElMessageBox.confirm("是否确认导出?", "导出", {
@@ -556,98 +638,101 @@
    });
};
const handleShare = () => {
  ElMessage.success('计划已共享')
}
    ElMessage.success("计划已共享");
  };
const getCurrentLevelText = () => {
  const levelMap = {
    personal: '个人计划',
    group: '小组计划',
    department: '部门计划',
    company: '公司计划'
  }
  return levelMap[currentLevel.value] || '个人计划'
}
      personal: "个人计划",
      group: "小组计划",
      department: "部门计划",
      company: "公司计划",
    };
    return levelMap[currentLevel.value] || "个人计划";
  };
const getCurrentPeriodText = () => {
  const periodMap = {
    week: '周计划',
    month: '月计划',
    year: '年计划'
  }
  return periodMap[currentPeriod.value] || '周计划'
}
      week: "周计划",
      month: "月计划",
      year: "年计划",
    };
    return periodMap[currentPeriod.value] || "周计划";
  };
const getPriorityType = (priority) => {
  const getPriorityType = priority => {
  const typeMap = {
    high: 'danger',
    medium: 'warning',
    low: 'info'
  }
  return typeMap[priority] || 'info'
}
      high: "danger",
      medium: "warning",
      low: "info",
    };
    return typeMap[priority] || "info";
  };
const getPriorityText = (priority) => {
  const getPriorityText = priority => {
  const textMap = {
    high: '高',
    medium: '中',
    low: '低'
  }
  return textMap[priority] || '中'
}
      high: "高",
      medium: "中",
      low: "低",
    };
    return textMap[priority] || "中";
  };
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusMap = {
    not_started: '未开始',
    in_progress: '进行中',
    completed: '已完成',
    paused: '已暂停'
  }
  return statusMap[status] || '未知'
}
      not_started: "未开始",
      in_progress: "进行中",
      completed: "已完成",
      paused: "已暂停",
    };
    return statusMap[status] || "未知";
  };
const getProgressColor = (progress) => {
  if (progress >= 80) return '#67C23A'
  if (progress >= 50) return '#E6A23C'
  return '#F56C6C'
}
  const getProgressColor = progress => {
    if (progress >= 80) return "#67C23A";
    if (progress >= 50) return "#E6A23C";
    return "#F56C6C";
  };
//获取数据列表
const getPlanList = async () => {
  const params = {
    level: currentLevel.value,
    period: currentPeriod.value,
    queryDate:currentDate.value
  }
  listDutyPlan(params).then(res => {
      queryDate: currentDate.value,
    };
    listDutyPlan(params)
      .then(res => {
    if (res.code === 200) {
      planList.value = res.data.records
          planList.value = res.data.records;
    }
  }).catch(err => {
    console.log(err)
  })
}
      .catch(err => {
        console.log(err);
      });
  };
//获取数据
const getPlanNum = async () => {
  NumDutyPlan().then(res => {
    NumDutyPlan()
      .then(res => {
    if (res.code === 200) {
      // console.log(res.data)
      //讲结果里面的数据根据level 赋值给overviewData
      res.data.forEach(item => {
        overviewData[item.level].total = item.num
        overviewData[item.level].completion = item.completion
      })
            overviewData[item.level].total = item.num;
            overviewData[item.level].completion = item.completion;
          });
    }
  }).catch(err => {
    console.log(err)
  })
}
      .catch(err => {
        console.log(err);
      });
  };
onMounted(() => {
  getPlanList()
  getPlanNum()
  console.log('多级计划模板页面已加载')
})
    getPlanList();
    getPlanNum();
    console.log("多级计划模板页面已加载");
  });
</script>
<style scoped>
src/views/collaborativeApproval/rpaManagement/index.vue
@@ -3,33 +3,42 @@
    <div class="search_form">
      <div>
        <span class="search_title">程序名:</span>
        <el-input
          v-model="searchForm.programName"
        <el-input v-model="searchForm.programName"
          style="width: 240px"
          placeholder="请输入程序名搜索"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
        />
                  :prefix-icon="Search" />
        <span class="search_title ml10">执行状态:</span>
        <el-select v-model="searchForm.status" clearable @change="handleQuery" style="width: 240px">
          <el-option label="运行中" :value="'running'" />
          <el-option label="已停止" :value="'stopped'" />
          <el-option label="异常" :value="'error'" />
        <el-select v-model="searchForm.status"
                   clearable
                   @change="handleQuery"
                   style="width: 240px">
          <el-option label="运行中"
                     :value="'running'" />
          <el-option label="已停止"
                     :value="'stopped'" />
          <el-option label="异常"
                     :value="'error'" />
        </el-select>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">
          搜索
        </el-button>
      </div>
      <div>
        <el-button @click="handleExport" style="margin-right: 10px">导出</el-button>
        <el-button type="primary" @click="openForm('add')">新增</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
        <el-button @click="handleExport"
                   style="margin-right: 10px">导出</el-button>
        <el-button type="primary"
                   @click="openForm('add')">新增</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
        rowKey="id"
      <PIMTable rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
@@ -37,51 +46,50 @@
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="page.total"
      ></PIMTable>
                :total="page.total"></PIMTable>
    </div>
    <!-- RPA表单弹窗 -->
    <el-dialog
      v-model="dialogVisible"
    <el-dialog v-model="dialogVisible"
      :title="dialogTitle"
      width="500px"
      :close-on-click-modal="false"
    >
      <el-form
        ref="formRef"
               :close-on-click-modal="false">
      <el-form ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
      >
        <el-form-item label="程序名" prop="programName">
          <el-input
            v-model="form.programName"
               label-width="100px">
        <el-form-item label="程序名"
                      prop="programName">
          <el-input v-model="form.programName"
            placeholder="请输入程序名"
            clearable
          />
                    clearable />
        </el-form-item>
        <el-form-item label="执行状态" prop="status">
          <el-select v-model="form.status" placeholder="请选择执行状态" style="width: 100%">
            <el-option label="运行中" value="running" />
            <el-option label="已停止" value="stopped" />
            <el-option label="异常" value="error" />
        <el-form-item label="执行状态"
                      prop="status">
          <el-select v-model="form.status"
                     placeholder="请选择执行状态"
                     style="width: 100%">
            <el-option label="运行中"
                       value="running" />
            <el-option label="已停止"
                       value="stopped" />
            <el-option label="异常"
                       value="error" />
          </el-select>
        </el-form-item>
        <el-form-item label="描述" prop="description">
          <el-input
            v-model="form.description"
        <el-form-item label="描述"
                      prop="description">
          <el-input v-model="form.description"
            type="textarea"
            :rows="3"
            placeholder="请输入RPA程序描述"
            clearable
          />
                    clearable />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </span>
      </template>
    </el-dialog>
@@ -93,7 +101,13 @@
import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import {listRpa, addRpa, updateRpa, delRpa, delRpaBatch} from "@/api/collaborativeApproval/rpaManagement.js";
  import {
    listRpa,
    addRpa,
    updateRpa,
    delRpa,
    delRpaBatch,
  } from "@/api/collaborativeApproval/rpaManagement.js";
// 响应式数据
const data = reactive({
  searchForm: {
@@ -103,7 +117,7 @@
  form: {
    programName: "",
    status: "",
    description: ""
      description: "",
  },
  dialogVisible: false,
  dialogTitle: "",
@@ -117,7 +131,17 @@
  tableData: [],
});
const { searchForm, form, dialogVisible, dialogTitle, dialogType, selectedIds, tableLoading, page, tableData } = toRefs(data);
  const {
    searchForm,
    form,
    dialogVisible,
    dialogTitle,
    dialogType,
    selectedIds,
    tableLoading,
    page,
    tableData,
  } = toRefs(data);
// 表单引用
const formRef = ref();
@@ -126,12 +150,8 @@
// 表单验证规则
const rules = {
  programName: [
    { required: true, message: "请输入程序名", trigger: "blur" }
  ],
  status: [
    { required: true, message: "请选择执行状态", trigger: "change" }
  ]
    programName: [{ required: true, message: "请输入程序名", trigger: "blur" }],
    status: [{ required: true, message: "请选择执行状态", trigger: "change" }],
};
// 表格列配置
@@ -146,22 +166,22 @@
    prop: "status",
    dataType: "tag",
    // width: 120,
    formatData: (params) => {
      formatData: params => {
      const statusMap = {
        running: "运行中",
        stopped: "已停止",
        error: "异常"
          error: "异常",
      };
      return statusMap[params] || params;
    },
    formatType: (params) => {
      formatType: params => {
      const typeMap = {
        running: "success",
        stopped: "info",
        error: "danger"
          error: "danger",
      };
      return typeMap[params] || "info";
    }
      },
  },
  {
    label: "描述",
@@ -184,9 +204,9 @@
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          clickFun: row => {
          openForm("edit", row);
        }
          },
      },
      // {
      //   name: "开始",
@@ -204,10 +224,9 @@
      //   },
      //   disabled: (row) => row.status === 'stopped'
      // }
    ]
  }
      ],
    },
]);
// 生命周期
onMounted(() => {
@@ -225,22 +244,23 @@
  listRpa({...page.value, ...searchForm.value})
  .then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records
        tableData.value = res.data.records;
    page.total = res.data.total;
  }).catch(err => {
    tableLoading.value = false;
  })
      .catch(err => {
        tableLoading.value = false;
      });
};
// 分页处理
const pagination = (obj) => {
  const pagination = obj => {
  page.value.current = obj.page;
  page.value.size = obj.limit;
  handleQuery();
};
// 选择变化处理
const handleSelectionChange = (selection) => {
  const handleSelectionChange = selection => {
  selectedRows.value = selection;
};
@@ -266,31 +286,35 @@
    if (dialogType.value === "add") {
      // 添加新RPA
      addRpa({...form.value}).then(res => {
        addRpa({ ...form.value })
          .then(res => {
        if(res.code == 200){
          ElMessage.success("添加成功");
            form.value = {
              (form.value = {
            programName: "",
            status: "",
            description: ""
          },
          dialogVisible.value = false;
                description: "",
              }),
                (dialogVisible.value = false);
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    } else {
      // 编辑RPA
      updateRpa({...form.value}).then(res => {
        updateRpa({ ...form.value })
          .then(res => {
        if(res.code == 200){
          ElMessage.success("更新成功");
          dialogVisible.value = false;
          getList();
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    }
  } catch (error) {
    console.error("表单验证失败:", error);
@@ -298,31 +322,35 @@
};
// 开始RPA
const handleStart = (row) => {
  const handleStart = row => {
  ElMessageBox.confirm(`确定要启动RPA程序"${row.programName}"吗?`, "提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    })
      .then(() => {
    row.status = "running";
    ElMessage.success("RPA启动成功");
    getList();
  }).catch(() => {
      })
      .catch(() => {
    // 用户取消
  });
};
// 停止RPA
const handleStop = (row) => {
  const handleStop = row => {
  ElMessageBox.confirm(`确定要停止RPA程序"${row.programName}"吗?`, "提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    })
      .then(() => {
    row.status = "stopped";
    ElMessage.success("RPA停止成功");
    getList();
  }).catch(() => {
      })
      .catch(() => {
    // 用户取消
  });
};
@@ -331,7 +359,7 @@
const handleDelete = () => {
  let ids = [];
    if (selectedRows.value.length > 0) {
        ids = selectedRows.value.map((item) => item.id);
      ids = selectedRows.value.map(item => item.id);
    } else {
        proxy.$modal.msgWarning("请选择数据");
        return;
@@ -342,14 +370,16 @@
        type: "warning",
    })
    .then(() => {
        delRpa(ids).then((res) => {
        delRpa(ids)
          .then(res => {
                if(res.code == 200){
                    ElMessage.success("删除成功");
                    getList();
                }
            }).catch(err => {
                ElMessage.error(err.msg);
            })
          .catch(err => {
            ElMessage.error(err.msg);
          });
    })
    .catch(() => {
        proxy.$modal.msg("已取消");
@@ -357,10 +387,14 @@
};
// 导出功能
const { proxy } = getCurrentInstance()
  const { proxy } = getCurrentInstance();
const handleExport = () => {
  proxy.download('/rpaProcessAutomation/export', { ...searchForm.value }, 'RPA管理.xlsx')
}
    proxy.download(
      "/rpaProcessAutomation/export",
      { ...searchForm.value },
      "RPA管理.xlsx"
    );
  };
</script>
<style scoped></style>
src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
@@ -1,6 +1,5 @@
<template>
  <div class="app-container">
        <!-- 规章制度管理-->
          <el-card class="box-card">
            <template #header>
@@ -9,62 +8,101 @@
              </div>
            </template>
            <div class="tab-content">
              <el-row :gutter="20" class="mb-20">
        <el-row :gutter="20"
                class="mb-20">
                <span class="ml-10">制度标题:</span>
                <el-col :span="6">
                  <el-input v-model="regulationSearchForm.title" placeholder="请输入制度标题" clearable />
            <el-input v-model="regulationSearchForm.title"
                      placeholder="请输入制度标题"
                      clearable />
                </el-col>
                <span class="search_title">制度分类:</span>
                <el-col :span="4">
                  <el-select v-model="regulationSearchForm.category" placeholder="制度分类" clearable>
                    <el-option label="人事制度" value="hr" />
                    <el-option label="财务制度" value="finance" />
                    <el-option label="安全制度" value="safety" />
                    <el-option label="技术制度" value="tech" />
            <el-select v-model="regulationSearchForm.category"
                       placeholder="制度分类"
                       clearable>
              <el-option label="人事制度"
                         value="hr" />
              <el-option label="财务制度"
                         value="finance" />
              <el-option label="安全制度"
                         value="safety" />
              <el-option label="技术制度"
                         value="tech" />
                  </el-select>
                </el-col>
                <el-col :span="8">
                  <el-button type="primary" @click="searchRegulations">搜索</el-button>
            <el-button type="primary"
                       @click="searchRegulations">搜索</el-button>
                  <el-button @click="resetRegulationSearch">重置</el-button>
                  <el-button @click="handleExport">导出</el-button>
                  <el-button type="success" @click="handleAdd">
            <el-button type="success"
                       @click="handleAdd">
                    发布制度
                  </el-button>
                </el-col>
              </el-row>
              <el-table :data="regulations" border v-loading="tableLoading"  style="width: 100%">
                <el-table-column prop="regulationNum" label="制度编号" width="120" />
                <el-table-column prop="title" label="制度标题" min-width="150" />
                <el-table-column prop="category" label="分类" width="120">
        <el-table :data="regulations"
                  border
                  v-loading="tableLoading"
                  style="width: 100%">
          <el-table-column prop="regulationNum"
                           label="制度编号"
                           width="120" />
          <el-table-column prop="title"
                           label="制度标题"
                           min-width="150" />
          <el-table-column prop="category"
                           label="分类"
                           width="120">
                  <template #default="scope">
                    <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="version" label="版本" width="120" />
                <el-table-column prop="createUserName" label="发布人" width="120" />
                <el-table-column prop="createTime" label="发布时间" width="180" />
                <el-table-column prop="status" label="状态" width="100">
          <el-table-column prop="version"
                           label="版本"
                           width="120" />
          <el-table-column prop="createUserName"
                           label="发布人"
                           width="120" />
          <el-table-column prop="createTime"
                           label="发布时间"
                           width="180" />
          <el-table-column prop="status"
                           label="状态"
                           width="100">
                  <template #default="scope">
                    <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
                      {{ scope.row.status === 'active' ? '生效中' : '已废止' }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="readCount" label="已读人数" width="100" />
                <el-table-column label="操作" width="250" fixed="right">
          <el-table-column prop="readCount"
                           label="已读人数"
                           width="100" />
          <el-table-column label="操作"
                           width="250"
                           fixed="right">
                  <template #default="scope">
                    <el-button link @click="viewRegulation(scope.row)">查看</el-button>
                    <el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
                    <el-button link type="danger" @click="repealEdit(scope.row)">废弃</el-button>
                    <el-button link type="success" @click="viewVersionHistory(scope.row)">版本历史</el-button>
                    <el-button link type="warning" @click="viewReadStatus(scope.row)">阅读状态</el-button>
              <el-button link
                         @click="viewRegulation(scope.row)">查看</el-button>
              <el-button link
                         type="primary"
                         @click="handleEdit(scope.row)">编辑</el-button>
              <el-button link
                         type="danger"
                         @click="repealEdit(scope.row)">废弃</el-button>
              <el-button link
                         type="success"
                         @click="viewVersionHistory(scope.row)">版本历史</el-button>
              <el-button link
                         type="warning"
                         @click="viewReadStatus(scope.row)">阅读状态</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </el-card>
    <!-- 用印申请对话框 -->
    <!-- <el-dialog v-model="showSealApplyDialog" title="申请用印" width="600px">
      <el-form :model="sealForm" :rules="sealRules" ref="sealFormRef" label-width="100px">
@@ -100,35 +138,62 @@
        </span>
      </template>
    </el-dialog> -->
    <!-- 规章制度发布对话框 -->
    <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '发布制度' : '编辑制度'" width="800px">
      <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
        <el-form-item label="制度编号" prop="regulationNum">
          <el-input v-model="regulationForm.regulationNum" placeholder="请输入制度编号" />
    <el-dialog v-model="showRegulationDialog"
               :title="operationType === 'add' ? '发布制度' : '编辑制度'"
               width="800px">
      <el-form :model="regulationForm"
               :rules="regulationRules"
               ref="regulationFormRef"
               label-width="100px">
        <el-form-item label="制度编号"
                      prop="regulationNum">
          <el-input v-model="regulationForm.regulationNum"
                    placeholder="请输入制度编号" />
        </el-form-item>
        <el-form-item label="制度标题" prop="title">
          <el-input v-model="regulationForm.title" placeholder="请输入制度标题" />
        <el-form-item label="制度标题"
                      prop="title">
          <el-input v-model="regulationForm.title"
                    placeholder="请输入制度标题" />
        </el-form-item>
        <el-form-item label="制度分类" prop="category">
          <el-select v-model="regulationForm.category" placeholder="请选择制度分类" style="width: 100%">
            <el-option label="人事制度" value="hr" />
            <el-option label="财务制度" value="finance" />
            <el-option label="安全制度" value="safety" />
            <el-option label="技术制度" value="tech" />
        <el-form-item label="制度分类"
                      prop="category">
          <el-select v-model="regulationForm.category"
                     placeholder="请选择制度分类"
                     style="width: 100%">
            <el-option label="人事制度"
                       value="hr" />
            <el-option label="财务制度"
                       value="finance" />
            <el-option label="安全制度"
                       value="safety" />
            <el-option label="技术制度"
                       value="tech" />
          </el-select>
        </el-form-item>
        <el-form-item label="制度内容" prop="content">
          <el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="请输入制度详细内容" />
        <el-form-item label="制度内容"
                      prop="content">
          <el-input v-model="regulationForm.content"
                    type="textarea"
                    :rows="10"
                    placeholder="请输入制度详细内容" />
        </el-form-item>
        <el-form-item label="制度版本" prop="version">
          <el-input v-model="regulationForm.version" placeholder="请输入制度版本" />
        <el-form-item label="制度版本"
                      prop="version">
          <el-input v-model="regulationForm.version"
                    placeholder="请输入制度版本" />
        </el-form-item>
        <el-form-item label="生效时间" prop="effectiveTime">
          <el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
             value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择生效时间" style="width: 100%" />
        <el-form-item label="生效时间"
                      prop="effectiveTime">
          <el-date-picker v-model="regulationForm.effectiveTime"
                          type="datetime"
                          format="YYYY-MM-DD HH:mm:ss"
                          value-format="YYYY-MM-DD HH:mm:ss"
                          placeholder="选择生效时间"
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="适用范围" prop="scope">
        <el-form-item label="适用范围"
                      prop="scope">
          <el-checkbox-group v-model="regulationForm.scope">
            <el-checkbox label="all">全体员工</el-checkbox>
            <el-checkbox label="manager">管理层</el-checkbox>
@@ -137,19 +202,20 @@
            <el-checkbox label="tech">技术部门</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
        <el-form-item label="是否需要确认" prop="requireConfirm">
        <el-form-item label="是否需要确认"
                      prop="requireConfirm">
          <el-switch v-model="regulationForm.requireConfirm" />
          <span class="ml-10">开启后员工需要阅读确认</span>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitRegulation">发布制度</el-button>
          <el-button @click="showRegulationDialog = false">取消</el-button>
          <el-button type="primary" @click="submitRegulation">发布制度</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 用印详情对话框 -->
    <!-- <el-dialog v-model="showSealDetailDialog" title="用印申请详情" width="700px">
      <div v-if="currentSealDetail" class="mb10">
@@ -169,11 +235,13 @@
        </el-descriptions>
      </div>
    </el-dialog> -->
    <!-- 规章制度详情对话框 -->
    <el-dialog v-model="showRegulationDetailDialog" title="规章制度详情" width="800px">
    <el-dialog v-model="showRegulationDetailDialog"
               title="规章制度详情"
               width="800px">
      <div v-if="currentRegulationDetail">
        <el-descriptions :column="2" border>
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="制度编号">{{ currentRegulationDetail.id }}</el-descriptions-item>
          <el-descriptions-item label="制度标题">{{ currentRegulationDetail.title }}</el-descriptions-item>
          <el-descriptions-item label="分类">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item>
@@ -186,19 +254,30 @@
          <div class="regulation-content">{{ currentRegulationDetail.content }}</div>
        </div>
        <!-- 如果tableData>0 显示 -->
        <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" >
          <el-button type="success" @click="resetForm(currentRegulationDetail)">确认查看</el-button>
        <div style="margin: 10px 0;"
             v-if="tableData && tableData.length > 0">
          <el-button type="success"
                     @click="resetForm(currentRegulationDetail)">确认查看</el-button>
        </div>
      </div>
    </el-dialog>
    <!-- 版本历史对话框 -->
    <el-dialog v-model="showVersionHistoryDialog" title="版本历史" width="800px">
      <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="version" label="版本号" width="100" />
        <el-table-column prop="updateTime" label="更新时间" width="180" />
        <el-table-column prop="createUserName" label="更新人" width="120" />
        <el-table-column prop="changeLog" label="变更说明">
    <el-dialog v-model="showVersionHistoryDialog"
               title="版本历史"
               width="800px">
      <el-table :data="versionHistory"
                style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="version"
                         label="版本号"
                         width="100" />
        <el-table-column prop="updateTime"
                         label="更新时间"
                         width="180" />
        <el-table-column prop="createUserName"
                         label="更新人"
                         width="120" />
        <el-table-column prop="changeLog"
                         label="变更说明">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
              {{ scope.row.status === 'active' ? '生效中' : '已废止' }}
@@ -207,15 +286,27 @@
        </el-table-column>
      </el-table>
    </el-dialog>
    <!-- 阅读状态对话框 -->
    <el-dialog v-model="showReadStatusDialog" title="阅读状态" width="800px">
      <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="employee" label="员工姓名" width="120" />
        <el-table-column prop="department" label="所属部门" width="150" />
        <el-table-column prop="createTime" label="阅读时间" width="180" />
        <el-table-column prop="confirmTime" label="确认时间" width="180" />
        <el-table-column prop="status" label="状态" width="100">
    <el-dialog v-model="showReadStatusDialog"
               title="阅读状态"
               width="800px">
      <el-table :data="readStatusList"
                style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="employee"
                         label="员工姓名"
                         width="120" />
        <el-table-column prop="department"
                         label="所属部门"
                         width="150" />
        <el-table-column prop="createTime"
                         label="阅读时间"
                         width="180" />
        <el-table-column prop="confirmTime"
                         label="确认时间"
                         width="180" />
        <el-table-column prop="status"
                         label="状态"
                         width="100">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'">
              {{ scope.row.status === 'confirmed' ? '已确认' : '未确认' }}
@@ -228,402 +319,425 @@
</template>
<script setup>
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus  } from '@/api/collaborativeApproval/sealManagement.js'
import { el } from 'element-plus/es/locales.mjs'
import { getUserProfile } from '@/api/system/user.js'
import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
import useUserStore from '@/store/modules/user'
import { userLoginFacotryList } from "@/api/system/user.js"
  import { ref, reactive, onMounted, getCurrentInstance } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus } from "@element-plus/icons-vue";
  import {
    listSealApplication,
    addSealApplication,
    updateSealApplication,
    listRuleManagement,
    addRuleManagement,
    updateRuleManagement,
    delRuleManagement,
    getReadingStatusByRuleId,
    getReadingStatusList,
    addReadingStatus,
    updateReadingStatus,
  } from "@/api/collaborativeApproval/sealManagement.js";
  import { el } from "element-plus/es/locales.mjs";
  import { getUserProfile } from "@/api/system/user.js";
  import {
    staffJoinDel,
    staffJoinListPage,
  } from "@/api/personnelManagement/onboarding.js";
  import useUserStore from "@/store/modules/user";
  import { userLoginFacotryList } from "@/api/system/user.js";
// 响应式数据
const currentUser = ref(null)
const activeTab = ref('seal')
const operationType = ref('add')
const tableData = ref([])
  const currentUser = ref(null);
  const activeTab = ref("seal");
  const operationType = ref("add");
  const tableData = ref([]);
// 用印申请相关
const userStore = useUserStore()
const showSealApplyDialog = ref(false)
const tableLoading = ref(false)
const showSealDetailDialog = ref(false)
const currentSealDetail = ref(null)
const sealFormRef = ref()
  const userStore = useUserStore();
  const showSealApplyDialog = ref(false);
  const tableLoading = ref(false);
  const showSealDetailDialog = ref(false);
  const currentSealDetail = ref(null);
  const sealFormRef = ref();
const sealForm = reactive({
  applicationNum: '',
  title: '',
  sealType: '',
  reason: '',
  urgency: 'normal',
  status: 'pending'
})
    applicationNum: "",
    title: "",
    sealType: "",
    reason: "",
    urgency: "normal",
    status: "pending",
  });
const sealRules = {
  applicationNum: [{ required: true, message: '请输入申请编号', trigger: 'blur' }],
  title: [{ required: true, message: '请输入申请标题', trigger: 'blur' }],
  sealType: [{ required: true, message: '请选择用印类型', trigger: 'change' }],
  reason: [{ required: true, message: '请输入申请原因', trigger: 'blur' }]
}
    applicationNum: [
      { required: true, message: "请输入申请编号", trigger: "blur" },
    ],
    title: [{ required: true, message: "请输入申请标题", trigger: "blur" }],
    sealType: [{ required: true, message: "请选择用印类型", trigger: "change" }],
    reason: [{ required: true, message: "请输入申请原因", trigger: "blur" }],
  };
const sealSearchForm = reactive({
  title: '',
  status: ''
})
    title: "",
    status: "",
  });
// 分页参数
const page = reactive({
  current: 1,
  size: 10,
  total: 0
})
    total: 0,
  });
// 规章制度相关
const showRegulationDialog = ref(false)
const showRegulationDetailDialog = ref(false)
const showVersionHistoryDialog = ref(false)
const showReadStatusDialog = ref(false)
const currentRegulationDetail = ref(null)
const regulationFormRef = ref()
  const showRegulationDialog = ref(false);
  const showRegulationDetailDialog = ref(false);
  const showVersionHistoryDialog = ref(false);
  const showReadStatusDialog = ref(false);
  const currentRegulationDetail = ref(null);
  const regulationFormRef = ref();
const regulationForm = reactive({
  id: '',
  regulationNum: '',
  title: '',
  category: '',
  content: '',
  version: '',
  status: 'active',
    id: "",
    regulationNum: "",
    title: "",
    category: "",
    content: "",
    version: "",
    status: "active",
  readCount: 0,
  effectiveTime: '',
    effectiveTime: "",
  scope: [],
  requireConfirm: false
})
    requireConfirm: false,
  });
const readStatus = ref({
  id: '',
  ruleId: '',
  employee: '',
  department: '',
  createTime: '',
  confirmTime: '',
  status: 'unconfirmed'
})
    id: "",
    ruleId: "",
    employee: "",
    department: "",
    createTime: "",
    confirmTime: "",
    status: "unconfirmed",
  });
const regulationRules = {
  title: [{ required: true, message: '请输入制度标题', trigger: 'blur' }],
  category: [{ required: true, message: '请选择制度分类', trigger: 'change' }],
  content: [{ required: true, message: '请输入制度内容', trigger: 'blur' }],
  effectiveTime: [{ required: true, message: '请选择生效时间', trigger: 'change' }],
  scope: [{ required: true, message: '请选择适用范围', trigger: 'change' }]
}
    title: [{ required: true, message: "请输入制度标题", trigger: "blur" }],
    category: [{ required: true, message: "请选择制度分类", trigger: "change" }],
    content: [{ required: true, message: "请输入制度内容", trigger: "blur" }],
    effectiveTime: [
      { required: true, message: "请选择生效时间", trigger: "change" },
    ],
    scope: [{ required: true, message: "请选择适用范围", trigger: "change" }],
  };
const regulationSearchForm = reactive({
  title: '',
  category: ''
})
    title: "",
    category: "",
  });
// 假数据
const sealApplications = ref([])
  const sealApplications = ref([]);
const regulations = ref([])
  const regulations = ref([]);
const versionHistory = ref([])
  const versionHistory = ref([]);
const readStatusList = ref([])
  const readStatusList = ref([]);
  // { employee: '陈志强', department: '销售部', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' },
  // { employee: '刘雅婷', department: '技术部', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' },
  // { employee: '王建国', department: '财务部', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' }
// 用印申请状态
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    pending: 'warning',
    approved: 'success',
    rejected: 'danger'
  }
  return statusMap[status] || 'info'
}
      pending: "warning",
      approved: "success",
      rejected: "danger",
    };
    return statusMap[status] || "info";
  };
// 制度状态
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusMap = {
    pending: '待审批',
    approved: '已通过',
    rejected: '已拒绝'
  }
  return statusMap[status] || '未知'
}
      pending: "待审批",
      approved: "已通过",
      rejected: "已拒绝",
    };
    return statusMap[status] || "未知";
  };
// 用印类型
const getSealTypeText = (sealType) => {
  const getSealTypeText = sealType => {
  const sealTypeMap = {
    official: '公章',
    contract: '合同专用章',
    finance: '财务专用章',
    tegal: '技术专用章'
  }
  return sealTypeMap[sealType] || '未知'
}
      official: "公章",
      contract: "合同专用章",
      finance: "财务专用章",
      tegal: "技术专用章",
    };
    return sealTypeMap[sealType] || "未知";
  };
// 制度分类
const getCategoryText = (category) => {
  const getCategoryText = category => {
  const categoryMap = {
    hr: '人事制度',
    finance: '财务制度',
    safety: '安全制度',
    tech: '技术制度'
  }
  return categoryMap[category] || '未知'
}
      hr: "人事制度",
      finance: "财务制度",
      safety: "安全制度",
      tech: "技术制度",
    };
    return categoryMap[category] || "未知";
  };
// 搜索印章申请
const searchSealApplications = () => {
  page.current=1
  getSealApplicationList()
    page.current = 1;
    getSealApplicationList();
  // ElMessage.success('搜索完成')
}
  };
// 重置印章申请搜索
const resetSealSearch = () => {
  sealSearchForm.title = ''
  sealSearchForm.status = ''
  searchSealApplications()
}
    sealSearchForm.title = "";
    sealSearchForm.status = "";
    searchSealApplications();
  };
// 搜索制度
const searchRegulations = () => {
  page.current=1
  getRegulationList()
}
    page.current = 1;
    getRegulationList();
  };
// 重置制度搜索
const resetRegulationSearch = () => {
  regulationSearchForm.title = ''
  regulationSearchForm.category = ''
  searchRegulations()
}
    regulationSearchForm.title = "";
    regulationSearchForm.category = "";
    searchRegulations();
  };
// 提交用印申请
const submitSealApplication = async () => {
  try {
    await sealFormRef.value.validate()
    addSealApplication(sealForm).then(res => {
      await sealFormRef.value.validate();
      addSealApplication(sealForm)
        .then(res => {
      if(res.code == 200){
        ElMessage.success('申请提交成功')
        showSealApplyDialog.value = false
        getSealApplicationList()
            ElMessage.success("申请提交成功");
            showSealApplyDialog.value = false;
            getSealApplicationList();
        Object.assign(sealForm, {
        applicationNum: '',
        title: '',
        sealType: '',
        reason: '',
        urgency: 'normal',
        status: 'pending'
      })
              applicationNum: "",
              title: "",
              sealType: "",
              reason: "",
              urgency: "normal",
              status: "pending",
            });
      }
    }).catch(err => {
      ElMessage.error(err.msg)
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
  } catch (error) {
    ElMessage.error('请完善申请信息')
      ElMessage.error("请完善申请信息");
  }
}
  };
// 新增
const handleAdd = () => {
  operationType.value = 'add'
  resetRegulationForm()
  showRegulationDialog.value = true
}
    operationType.value = "add";
    resetRegulationForm();
    showRegulationDialog.value = true;
  };
// 编辑
const handleEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(regulationForm, row)
  showRegulationDialog.value = true
}
  const handleEdit = row => {
    operationType.value = "edit";
    Object.assign(regulationForm, row);
    showRegulationDialog.value = true;
  };
// 废弃
const repealEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(regulationForm, row)
  regulationForm.status = 'repealed'
  ElMessageBox.confirm('确认废弃该制度?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
  const repealEdit = row => {
    operationType.value = "edit";
    Object.assign(regulationForm, row);
    regulationForm.status = "repealed";
    ElMessageBox.confirm("确认废弃该制度?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
    updateRuleManagement(regulationForm).then(res => {
      if(res.code == 200){
        ElMessage.success('制度废弃成功')
            ElMessage.success("制度废弃成功");
        // showRegulationDialog.value = false
        getRegulationList()
        resetRegulationForm()
            getRegulationList();
            resetRegulationForm();
      }
        });
    })
  }).catch(() => {
      .catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消废弃'
    })
  })
}
          type: "info",
          message: "已取消废弃",
        });
      });
  };
// 发布制度
const submitRegulation = async () => {
  try {
    await regulationFormRef.value.validate()
    if(operationType.value == 'add'){
      await regulationFormRef.value.validate();
      if (operationType.value == "add") {
      addRuleManagement(regulationForm).then(res => {
        if(res.code == 200){
          ElMessage.success('制度发布成功')
          showRegulationDialog.value = false
          getRegulationList()
          resetRegulationForm()
            ElMessage.success("制度发布成功");
            showRegulationDialog.value = false;
            getRegulationList();
            resetRegulationForm();
        }
      })
        });
    }else{
      updateRuleManagement(regulationForm).then(res => {
        if(res.code == 200){
          ElMessage.success('制度编辑成功')
          showRegulationDialog.value = false
          resetRegulationForm()
          getRegulationList()
      }})}
            ElMessage.success("制度编辑成功");
            showRegulationDialog.value = false;
            resetRegulationForm();
            getRegulationList();
          }
        });
      }
  }catch(err){
    ElMessage.error(err.msg)
      ElMessage.error(err.msg);
  }
}
  };
//重置制度表单
const resetRegulationForm = () => {
  Object.assign(regulationForm, {
    id: '',
    regulationNum: '',
    title: '',
    category: '',
    content: '',
    version: '',
    status: 'active',
      id: "",
      regulationNum: "",
      title: "",
      category: "",
      content: "",
      version: "",
      status: "active",
    readCount: 0,
    effectiveTime: '',
      effectiveTime: "",
    scope: [],
    requireConfirm: false
})
}
      requireConfirm: false,
    });
  };
// 查看用印申请详情
const viewSealDetail = (row) => {
  currentSealDetail.value = row
  showSealDetailDialog.value = true
}
  const viewSealDetail = row => {
    currentSealDetail.value = row;
    showSealDetailDialog.value = true;
  };
// 审批用印申请
const approveSeal = (row) => {
  console.log(row)
  ElMessageBox.confirm('确认通过该用印申请?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const approveSeal = row => {
    console.log(row);
    ElMessageBox.confirm("确认通过该用印申请?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    row.status = 'approved'
      row.status = "approved";
    updateSealApplication(row).then(res => {
      if(res.code == 200){
        ElMessage.success('审批通过')
          ElMessage.success("审批通过");
      }
    })
  })
}
      });
    });
  };
// 拒绝用印申请
const rejectSeal = (row) => {
  ElMessageBox.prompt('请输入拒绝原因', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
  const rejectSeal = row => {
    ElMessageBox.prompt("请输入拒绝原因", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
    inputPattern: /\S+/,
    inputErrorMessage: '拒绝原因不能为空'
      inputErrorMessage: "拒绝原因不能为空",
  }).then(({ value }) => {
    row.status = 'rejected'
      row.status = "rejected";
    updateSealApplication(row).then(res => {
      if(res.code == 200){
        ElMessage.success('审批拒绝')
          ElMessage.success("审批拒绝");
      }
    })
    ElMessage.success('已拒绝申请')
  })
}
      });
      ElMessage.success("已拒绝申请");
    });
  };
// 获取在职员工列表
const getList = () => {
  tableLoading.value = true;
      //获取当前登录用户信息
  getUserProfile().then(res => {
    if(res.code == 200){
      console.log(res.data.userName)
      currentUser.value = res.data.userName
        console.log(res.data.userName);
        currentUser.value = res.data.userName;
    }
  })
  staffJoinListPage({staffState: 1}).then(res => {
    });
    staffJoinListPage({ staffState: 1 })
      .then(res => {
    tableLoading.value = false;
    // tableData.value = res.data.records
    // //筛选出和currentUser同名的人员
    tableData.value = res.data.records.filter(item => item.staffName === currentUser.value)
    console.log("tableData",tableData.value)
        tableData.value = res.data.records.filter(
          item => item.staffName === currentUser.value
        );
        console.log("tableData", tableData.value);
    page.total = res.data.total;
      
    if(tableData.value.length == 0){
    ElMessage.error('当前用户未加入任何部门')
          ElMessage.error("当前用户未加入任何部门");
    }
  }).catch(err => {
    tableLoading.value = false;
  })
      .catch(err => {
        tableLoading.value = false;
      });
};
// 查看制度版本历史
const viewVersionHistory = (row) => {
  showVersionHistoryDialog.value = true
  const viewVersionHistory = row => {
    showVersionHistoryDialog.value = true;
  const params = {
    category: row.category
  }
      category: row.category,
    };
  listRuleManagement(page,params).then(res => {
    if(res.code == 200){
      versionHistory.value = res.data.records
        versionHistory.value = res.data.records;
    }
  })
}
    });
  };
// 查看制度详情
const viewRegulation = (row) => {
  getList()
  currentRegulationDetail.value = row
  showRegulationDetailDialog.value = true
  const viewRegulation = row => {
    getList();
    currentRegulationDetail.value = row;
    showRegulationDetailDialog.value = true;
  getReadingStatusByRuleId(row.id).then(res => {
    if(res.code == 200){
      readStatusList.value = res.data
        readStatusList.value = res.data;
      if(readStatusList.value.length==0 && tableData.value.length>0){
          const params = {
          ruleId: row.id,
          employee: tableData.value[0].staffName,
          department: tableData.value[0].postJob,
          status: 'unconfirmed'
        }
            status: "unconfirmed",
          };
        addReadingStatus(params).then(res => {
          if(res.code == 200){
            ElMessage.success('制度阅读成功')
              ElMessage.success("制度阅读成功");
          }
        })
          });
      }
    }
  })
}
    });
  };
// 查看制度阅读状态
const viewReadStatus = (row) => {
  showReadStatusDialog.value = true
  const viewReadStatus = row => {
    showReadStatusDialog.value = true;
  //查看阅读状态列表
  getReadingStatusByRuleId(row.id).then(res => {
    if(res.code == 200){
      readStatusList.value = res.data
        readStatusList.value = res.data;
    }
  })
}
    });
  };
//确认查看
const resetForm = (row) => {
  console.log("row",row)
  row.readCount = row.readCount + 1
  const resetForm = row => {
    console.log("row", row);
    row.readCount = row.readCount + 1;
  
  updateRuleManagement(row).then(res => {
    if(res.code == 200){
      ElMessage.success('查看数量修改成功')
        ElMessage.success("查看数量修改成功");
      //修改阅读状态
      //根据制度id和当前登录的员工得到阅读状态
      // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName )
@@ -632,81 +746,96 @@
      //   item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
      // }
      // 筛选当前员工对应该制度的阅读状态记录
      let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id);
        let statusItem = readStatusList.value.find(
          item =>
            item.employee === tableData.value[0].staffName &&
            item.ruleId === row.id
        );
      if (statusItem) {
        // 如果找到记录,更新状态和确认时间
        statusItem.status = 'confirmed';
          statusItem.status = "confirmed";
        // 格式化时间为"YYYY-MM-DD HH:mm:ss"格式
        const now = new Date();
        statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
          statusItem.confirmTime = `${now.getFullYear()}-${String(
            now.getMonth() + 1
          ).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String(
            now.getHours()
          ).padStart(2, "0")}:${String(now.getMinutes()).padStart(
            2,
            "0"
          )}:${String(now.getSeconds()).padStart(2, "0")}`;
        // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
        
        updateReadingStatus(statusItem).then(res => {
          if(res.code == 200){
            ElMessage.success('制度阅读状态修改成功')
              ElMessage.success("制度阅读状态修改成功");
          }
        })
          });
      }
    }
  })
}
    });
  };
// 导出规章制度
const { proxy } = getCurrentInstance()
  const { proxy } = getCurrentInstance();
const handleExport = () => {
  proxy.download('/rulesRegulationsManagement/export', { ...regulationSearchForm }, '规章制度.xlsx')
}
    proxy.download(
      "/rulesRegulationsManagement/export",
      { ...regulationSearchForm },
      "规章制度.xlsx"
    );
  };
// 获取印章申请列表数据
const getSealApplicationList = async () => {
  tableLoading.value = true
    tableLoading.value = true;
  listSealApplication(page,sealSearchForm)
  .then(res => {
    //获取当前登录的部门信息
// 获取当前登录的部门信息并过滤数据
    const currentFactoryName = userStore.currentFactoryName
        const currentFactoryName = userStore.currentFactoryName;
    if (currentFactoryName) {
      // 根据currentFactoryName过滤出department相同的数据
      sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName)
          sealApplications.value = res.data.records.filter(
            item => item.department === currentFactoryName
          );
      // 更新过滤后的总数
      page.value.total = sealApplications.value.length
          page.value.total = sealApplications.value.length;
    } else {
      // 如果没有currentFactoryName,则显示所有数据
      sealApplications.value = res.data.records
      page.value.total = res.data.total
          sealApplications.value = res.data.records;
          page.value.total = res.data.total;
    }
    // sealApplications.value = res.data.records
    // page.value.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
      .catch(err => {
        tableLoading.value = false;
      });
  };
// 获取规章制度列表数据
const getRegulationList = async () => {
  tableLoading.value = true
    tableLoading.value = true;
  listRuleManagement(page,regulationSearchForm)
  .then(res => {
    regulations.value = res.data.records
        regulations.value = res.data.records;
    // 过滤掉已废弃的制度
    // regulations.value = res.data.records.filter(item => item.status !== 'repealed')
    page.value.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
      .catch(err => {
        tableLoading.value = false;
      });
  };
onMounted(() => {
  // 初始化
  getSealApplicationList()
  getRegulationList()
})
    getSealApplicationList();
    getRegulationList();
  });
</script>
<style scoped>
src/views/collaborativeApproval/sealManagement/index.vue
@@ -6,98 +6,145 @@
          <span>用印管理发布</span>
        </div>
      </template>
   <!-- 用印申请管理 -->
        <div class="tab-content">
            <el-row :gutter="20" class="mb-20 ">
        <el-row :gutter="20"
                class="mb-20 ">
              <span class="ml-10">用印标题:</span>
              <el-col :span="6">
                <el-input v-model="sealSearchForm.title" placeholder="请输入申请标题" clearable />
            <el-input v-model="sealSearchForm.title"
                      placeholder="请输入申请标题"
                      clearable />
              </el-col>
              <span class="search_title">审批状态:</span>
              <el-col :span="6">
                <el-select v-model="sealSearchForm.status" placeholder="审批状态" clearable>
                  <el-option label="待审批" value="pending" />
                  <el-option label="已通过" value="approved" />
                  <el-option label="已拒绝" value="rejected" />
            <el-select v-model="sealSearchForm.status"
                       placeholder="审批状态"
                       clearable>
              <el-option label="待审批"
                         value="pending" />
              <el-option label="已通过"
                         value="approved" />
              <el-option label="已拒绝"
                         value="rejected" />
                </el-select>
              </el-col>
              <el-col :span="8">
                <el-button type="primary" @click="searchSealApplications">搜索</el-button>
            <el-button type="primary"
                       @click="searchSealApplications">搜索</el-button>
                <el-button @click="resetSealSearch">重置</el-button>
                <el-button @click="handleExport">导出</el-button>
                <el-button type="primary" @click="showSealApplyDialog = true">申请用印
            <el-button type="primary"
                       @click="showSealApplyDialog = true">申请用印
                </el-button>
              </el-col>
            </el-row>
            <el-table :data="sealApplications" border v-loading="tableLoading" style="width: 100%">
              <el-table-column prop="applicationNum" label="申请编号" width="120" />
              <el-table-column prop="title" label="申请标题" min-width="200" />
              <el-table-column prop="createUserName" label="申请人" width="120" />
              <el-table-column prop="department" label="所属部门" width="150" />
              <el-table-column prop="sealType" label="用印类型" width="120">
        <el-table :data="sealApplications"
                  border
                  v-loading="tableLoading"
                  style="width: 100%">
          <el-table-column prop="applicationNum"
                           label="申请编号"
                           width="120" />
          <el-table-column prop="title"
                           label="申请标题"
                           min-width="200" />
          <el-table-column prop="createUserName"
                           label="申请人"
                           width="120" />
          <el-table-column prop="department"
                           label="所属部门"
                           width="150" />
          <el-table-column prop="sealType"
                           label="用印类型"
                           width="120">
                <template #default="scope">
                  {{ getSealTypeText(scope.row.sealType) }}
                </template>
              </el-table-column>
              <el-table-column prop="createTime" label="申请时间" width="180" />
              <el-table-column prop="status" label="状态" width="100">
          <el-table-column prop="createTime"
                           label="申请时间"
                           width="180" />
          <el-table-column prop="status"
                           label="状态"
                           width="100">
                <template #default="scope">
                  <el-tag :type="getStatusType(scope.row.status)">
                    {{ getStatusText(scope.row.status) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="200" fixed="right">
          <el-table-column label="操作"
                           width="200"
                           fixed="right">
                <template #default="scope">
                  <el-button link @click="viewSealDetail(scope.row)">查看</el-button>
                  <el-button
                    v-if="scope.row.status === 'pending'"
              <el-button link
                         @click="viewSealDetail(scope.row)">查看</el-button>
              <el-button v-if="scope.row.status === 'pending'"
                                        link
                    type="primary" 
                    @click="approveSeal(scope.row)"
                  >
                         @click="approveSeal(scope.row)">
                    审批
                  </el-button>
                  <el-button
                    v-if="scope.row.status === 'pending'"
              <el-button v-if="scope.row.status === 'pending'"
                                        link
                    type="danger" 
                    @click="rejectSeal(scope.row)"
                  >
                         @click="rejectSeal(scope.row)">
                    拒绝
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
                    <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
                                            :page="page.current" :limit="page.size" @pagination="paginationChange" />
        <pagination v-show="total > 0"
                    :total="total"
                    layout="total, sizes, prev, pager, next, jumper"
                    :page="page.current"
                    :limit="page.size"
                    @pagination="paginationChange" />
        </div> 
    </el-card>
    <!-- 用印申请对话框 -->
    <el-dialog v-model="showSealApplyDialog" title="申请用印" width="600px">
      <el-form :model="sealForm" :rules="sealRules" ref="sealFormRef" label-width="100px">
        <el-form-item label="申请编号" prop="applicationNum">
          <el-input v-model="sealForm.applicationNum" placeholder="请输入申请编号" />
    <el-dialog v-model="showSealApplyDialog"
               title="申请用印"
               width="600px">
      <el-form :model="sealForm"
               :rules="sealRules"
               ref="sealFormRef"
               label-width="100px">
        <el-form-item label="申请编号"
                      prop="applicationNum">
          <el-input v-model="sealForm.applicationNum"
                    placeholder="请输入申请编号" />
        </el-form-item>
        <el-form-item label="申请标题" prop="title">
          <el-input v-model="sealForm.title" placeholder="请输入申请标题" />
        <el-form-item label="申请标题"
                      prop="title">
          <el-input v-model="sealForm.title"
                    placeholder="请输入申请标题" />
        </el-form-item>
        <el-form-item label="用印类型" prop="sealType">
          <el-select v-model="sealForm.sealType" placeholder="请选择用印类型" style="width: 100%">
            <el-option label="公章" value="official" />
            <el-option label="合同专用章" value="contract" />
            <el-option label="财务专用章" value="finance" />
            <el-option label="法人章" value="legal" />
        <el-form-item label="用印类型"
                      prop="sealType">
          <el-select v-model="sealForm.sealType"
                     placeholder="请选择用印类型"
                     style="width: 100%">
            <el-option label="公章"
                       value="official" />
            <el-option label="合同专用章"
                       value="contract" />
            <el-option label="财务专用章"
                       value="finance" />
            <el-option label="法人章"
                       value="legal" />
          </el-select>
        </el-form-item>
        <el-form-item label="申请原因" prop="reason">
          <el-input v-model="sealForm.reason" type="textarea" :rows="4" placeholder="请详细说明用印原因" />
        <el-form-item label="申请原因"
                      prop="reason">
          <el-input v-model="sealForm.reason"
                    type="textarea"
                    :rows="4"
                    placeholder="请详细说明用印原因" />
        </el-form-item>
        <el-form-item label="紧急程度" prop="urgency">
        <el-form-item label="紧急程度"
                      prop="urgency">
          <el-radio-group v-model="sealForm.urgency">
            <el-radio label="normal">普通</el-radio>
            <el-radio label="urgent">紧急</el-radio>
@@ -107,12 +154,12 @@
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitSealApplication">提交申请</el-button>
          <el-button @click="showSealApplyDialog = false">取消</el-button>
          <el-button type="primary" @click="submitSealApplication">提交申请</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 规章制度发布对话框 -->
    <!-- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '发布制度' : '编辑制度'" width="800px">
      <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
@@ -161,11 +208,14 @@
        </span>
      </template>
    </el-dialog> -->
    <!-- 用印详情对话框 -->
    <el-dialog v-model="showSealDetailDialog" title="用印申请详情" width="700px">
      <div v-if="currentSealDetail" class="mb10">
        <el-descriptions :column="2" border>
    <el-dialog v-model="showSealDetailDialog"
               title="用印申请详情"
               width="700px">
      <div v-if="currentSealDetail"
           class="mb10">
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="申请编号">{{ currentSealDetail.id }}</el-descriptions-item>
          <el-descriptions-item label="申请标题">{{ currentSealDetail.title }}</el-descriptions-item>
          <el-descriptions-item label="申请人">{{ currentSealDetail.createUserName }}</el-descriptions-item>
@@ -177,15 +227,18 @@
              {{ getStatusText(currentSealDetail.status) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="申请原因" :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
          <el-descriptions-item label="申请原因"
                                :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
        </el-descriptions>
      </div>
    </el-dialog>
    <!-- 规章制度详情对话框 -->
    <el-dialog v-model="showRegulationDetailDialog" title="规章制度详情" width="800px">
    <el-dialog v-model="showRegulationDetailDialog"
               title="规章制度详情"
               width="800px">
      <div v-if="currentRegulationDetail">
        <el-descriptions :column="2" border>
        <el-descriptions :column="2"
                         border>
          <el-descriptions-item label="制度编号">{{ currentRegulationDetail.id }}</el-descriptions-item>
          <el-descriptions-item label="制度标题">{{ currentRegulationDetail.title }}</el-descriptions-item>
          <el-descriptions-item label="分类">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item>
@@ -198,19 +251,30 @@
          <div class="regulation-content">{{ currentRegulationDetail.content }}</div>
        </div>
        <!-- 如果tableData>0 显示 -->
        <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" >
          <el-button type="success" @click="resetForm(currentRegulationDetail)">确认查看</el-button>
        <div style="margin: 10px 0;"
             v-if="tableData && tableData.length > 0">
          <el-button type="success"
                     @click="resetForm(currentRegulationDetail)">确认查看</el-button>
        </div>
      </div>
    </el-dialog>
    <!-- 版本历史对话框 -->
    <el-dialog v-model="showVersionHistoryDialog" title="版本历史" width="800px">
      <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="version" label="版本号" width="100" />
        <el-table-column prop="updateTime" label="更新时间" width="180" />
        <el-table-column prop="createUserName" label="更新人" width="120" />
        <el-table-column prop="changeLog" label="变更说明">
    <el-dialog v-model="showVersionHistoryDialog"
               title="版本历史"
               width="800px">
      <el-table :data="versionHistory"
                style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="version"
                         label="版本号"
                         width="100" />
        <el-table-column prop="updateTime"
                         label="更新时间"
                         width="180" />
        <el-table-column prop="createUserName"
                         label="更新人"
                         width="120" />
        <el-table-column prop="changeLog"
                         label="变更说明">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
              {{ scope.row.status === 'active' ? '生效中' : '已废止' }}
@@ -219,15 +283,27 @@
        </el-table-column>
      </el-table>
    </el-dialog>
    <!-- 阅读状态对话框 -->
    <el-dialog v-model="showReadStatusDialog" title="阅读状态" width="800px">
      <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="employee" label="员工姓名" width="120" />
        <el-table-column prop="department" label="所属部门" width="150" />
        <el-table-column prop="createTime" label="阅读时间" width="180" />
        <el-table-column prop="confirmTime" label="确认时间" width="180" />
        <el-table-column prop="status" label="状态" width="100">
    <el-dialog v-model="showReadStatusDialog"
               title="阅读状态"
               width="800px">
      <el-table :data="readStatusList"
                style="width: 100%;margin-bottom: 10px">
        <el-table-column prop="employee"
                         label="员工姓名"
                         width="120" />
        <el-table-column prop="department"
                         label="所属部门"
                         width="150" />
        <el-table-column prop="createTime"
                         label="阅读时间"
                         width="180" />
        <el-table-column prop="confirmTime"
                         label="确认时间"
                         width="180" />
        <el-table-column prop="status"
                         label="状态"
                         width="100">
          <template #default="scope">
            <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'">
              {{ scope.row.status === 'confirmed' ? '已确认' : '未确认' }}
@@ -240,401 +316,424 @@
</template>
<script setup>
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus  } from '@/api/collaborativeApproval/sealManagement.js'
import { el } from 'element-plus/es/locales.mjs'
import { getUserProfile } from '@/api/system/user.js'
import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
import useUserStore from '@/store/modules/user'
import { userLoginFacotryList } from "@/api/system/user.js"
  import { ref, reactive, onMounted, getCurrentInstance } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus } from "@element-plus/icons-vue";
  import {
    listSealApplication,
    addSealApplication,
    updateSealApplication,
    listRuleManagement,
    addRuleManagement,
    updateRuleManagement,
    delRuleManagement,
    getReadingStatusByRuleId,
    getReadingStatusList,
    addReadingStatus,
    updateReadingStatus,
  } from "@/api/collaborativeApproval/sealManagement.js";
  import { el } from "element-plus/es/locales.mjs";
  import { getUserProfile } from "@/api/system/user.js";
  import {
    staffJoinDel,
    staffJoinListPage,
  } from "@/api/personnelManagement/onboarding.js";
  import useUserStore from "@/store/modules/user";
  import { userLoginFacotryList } from "@/api/system/user.js";
// 响应式数据
const currentUser = ref(null)
const activeTab = ref('seal')
const operationType = ref('add')
const tableData = ref([])
  const currentUser = ref(null);
  const activeTab = ref("seal");
  const operationType = ref("add");
  const tableData = ref([]);
// 用印申请相关
const userStore = useUserStore()
const showSealApplyDialog = ref(false)
const tableLoading = ref(false)
const showSealDetailDialog = ref(false)
const currentSealDetail = ref(null)
const sealFormRef = ref()
  const userStore = useUserStore();
  const showSealApplyDialog = ref(false);
  const tableLoading = ref(false);
  const showSealDetailDialog = ref(false);
  const currentSealDetail = ref(null);
  const sealFormRef = ref();
const sealForm = reactive({
  applicationNum: '',
  title: '',
  sealType: '',
  reason: '',
  urgency: 'normal',
  status: 'pending'
})
    applicationNum: "",
    title: "",
    sealType: "",
    reason: "",
    urgency: "normal",
    status: "pending",
  });
const sealRules = {
  applicationNum: [{ required: true, message: '请输入申请编号', trigger: 'blur' }],
  title: [{ required: true, message: '请输入申请标题', trigger: 'blur' }],
  sealType: [{ required: true, message: '请选择用印类型', trigger: 'change' }],
  reason: [{ required: true, message: '请输入申请原因', trigger: 'blur' }]
}
    applicationNum: [
      { required: true, message: "请输入申请编号", trigger: "blur" },
    ],
    title: [{ required: true, message: "请输入申请标题", trigger: "blur" }],
    sealType: [{ required: true, message: "请选择用印类型", trigger: "change" }],
    reason: [{ required: true, message: "请输入申请原因", trigger: "blur" }],
  };
const sealSearchForm = reactive({
  title: '',
  status: ''
})
    title: "",
    status: "",
  });
// 分页参数
const page = reactive({
  current: 1,
  size: 100,
  total: 0
})
    total: 0,
  });
// 规章制度相关
const showRegulationDialog = ref(false)
const showRegulationDetailDialog = ref(false)
const showVersionHistoryDialog = ref(false)
const showReadStatusDialog = ref(false)
const currentRegulationDetail = ref(null)
const regulationFormRef = ref()
  const showRegulationDialog = ref(false);
  const showRegulationDetailDialog = ref(false);
  const showVersionHistoryDialog = ref(false);
  const showReadStatusDialog = ref(false);
  const currentRegulationDetail = ref(null);
  const regulationFormRef = ref();
const regulationForm = reactive({
  id: '',
  regulationNum: '',
  title: '',
  category: '',
  content: '',
  version: '',
  status: 'active',
    id: "",
    regulationNum: "",
    title: "",
    category: "",
    content: "",
    version: "",
    status: "active",
  readCount: 0,
  effectiveTime: '',
    effectiveTime: "",
  scope: [],
  requireConfirm: false
})
    requireConfirm: false,
  });
const readStatus = ref({
  id: '',
  ruleId: '',
  employee: '',
  department: '',
  createTime: '',
  confirmTime: '',
  status: 'unconfirmed'
})
    id: "",
    ruleId: "",
    employee: "",
    department: "",
    createTime: "",
    confirmTime: "",
    status: "unconfirmed",
  });
const regulationRules = {
  title: [{ required: true, message: '请输入制度标题', trigger: 'blur' }],
  category: [{ required: true, message: '请选择制度分类', trigger: 'change' }],
  content: [{ required: true, message: '请输入制度内容', trigger: 'blur' }],
  effectiveTime: [{ required: true, message: '请选择生效时间', trigger: 'change' }],
  scope: [{ required: true, message: '请选择适用范围', trigger: 'change' }]
}
    title: [{ required: true, message: "请输入制度标题", trigger: "blur" }],
    category: [{ required: true, message: "请选择制度分类", trigger: "change" }],
    content: [{ required: true, message: "请输入制度内容", trigger: "blur" }],
    effectiveTime: [
      { required: true, message: "请选择生效时间", trigger: "change" },
    ],
    scope: [{ required: true, message: "请选择适用范围", trigger: "change" }],
  };
const regulationSearchForm = reactive({
  title: '',
  category: ''
})
    title: "",
    category: "",
  });
// 假数据
const sealApplications = ref([])
  const sealApplications = ref([]);
const regulations = ref([])
  const regulations = ref([]);
const versionHistory = ref([])
  const versionHistory = ref([]);
const readStatusList = ref([])
  const readStatusList = ref([]);
  // { employee: '陈志强', department: '销售部', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' },
  // { employee: '刘雅婷', department: '技术部', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' },
  // { employee: '王建国', department: '财务部', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' }
// 用印申请状态
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    pending: 'warning',
    approved: 'success',
    rejected: 'danger'
  }
  return statusMap[status] || 'info'
}
      pending: "warning",
      approved: "success",
      rejected: "danger",
    };
    return statusMap[status] || "info";
  };
// 制度状态
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusMap = {
    pending: '待审批',
    approved: '已通过',
    rejected: '已拒绝'
  }
  return statusMap[status] || '未知'
}
      pending: "待审批",
      approved: "已通过",
      rejected: "已拒绝",
    };
    return statusMap[status] || "未知";
  };
// 用印类型
const getSealTypeText = (sealType) => {
  const getSealTypeText = sealType => {
  const sealTypeMap = {
    official: '公章',
    contract: '合同专用章',
    finance: '财务专用章',
    tegal: '技术专用章'
  }
  return sealTypeMap[sealType] || '未知'
}
      official: "公章",
      contract: "合同专用章",
      finance: "财务专用章",
      tegal: "技术专用章",
    };
    return sealTypeMap[sealType] || "未知";
  };
// 制度分类
const getCategoryText = (category) => {
  const getCategoryText = category => {
  const categoryMap = {
    hr: '人事制度',
    finance: '财务制度',
    safety: '安全制度',
    tech: '技术制度'
  }
  return categoryMap[category] || '未知'
}
      hr: "人事制度",
      finance: "财务制度",
      safety: "安全制度",
      tech: "技术制度",
    };
    return categoryMap[category] || "未知";
  };
// 搜索印章申请
const searchSealApplications = () => {
  page.current=1
  getSealApplicationList()
    page.current = 1;
    getSealApplicationList();
  // ElMessage.success('搜索完成')
}
  };
// 重置印章申请搜索
const resetSealSearch = () => {
  sealSearchForm.title = ''
  sealSearchForm.status = ''
  searchSealApplications()
}
    sealSearchForm.title = "";
    sealSearchForm.status = "";
    searchSealApplications();
  };
// 搜索制度
const searchRegulations = () => {
  page.current=1
  getRegulationList()
}
    page.current = 1;
    getRegulationList();
  };
// 重置制度搜索
const resetRegulationSearch = () => {
  regulationSearchForm.title = ''
  regulationSearchForm.category = ''
  searchRegulations()
}
    regulationSearchForm.title = "";
    regulationSearchForm.category = "";
    searchRegulations();
  };
// 提交用印申请
const submitSealApplication = async () => {
  try {
    await sealFormRef.value.validate()
    addSealApplication(sealForm).then(res => {
      await sealFormRef.value.validate();
      addSealApplication(sealForm)
        .then(res => {
      if(res.code == 200){
        ElMessage.success('申请提交成功')
        showSealApplyDialog.value = false
        getSealApplicationList()
            ElMessage.success("申请提交成功");
            showSealApplyDialog.value = false;
            getSealApplicationList();
        Object.assign(sealForm, {
        applicationNum: '',
        title: '',
        sealType: '',
        reason: '',
        urgency: 'normal',
        status: 'pending'
      })
              applicationNum: "",
              title: "",
              sealType: "",
              reason: "",
              urgency: "normal",
              status: "pending",
            });
      }
    }).catch(err => {
      ElMessage.error(err.msg)
    })
        .catch(err => {
          ElMessage.error(err.msg);
        });
  } catch (error) {
    ElMessage.error('请完善申请信息')
      ElMessage.error("请完善申请信息");
  }
}
  };
// 新增
const handleAdd = () => {
  operationType.value = 'add'
  resetRegulationForm()
  showRegulationDialog.value = true
}
    operationType.value = "add";
    resetRegulationForm();
    showRegulationDialog.value = true;
  };
// 编辑
const handleEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(regulationForm, row)
  showRegulationDialog.value = true
}
  const handleEdit = row => {
    operationType.value = "edit";
    Object.assign(regulationForm, row);
    showRegulationDialog.value = true;
  };
// 废弃
const repealEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(regulationForm, row)
  regulationForm.status = 'repealed'
  ElMessageBox.confirm('确认废弃该制度?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
  const repealEdit = row => {
    operationType.value = "edit";
    Object.assign(regulationForm, row);
    regulationForm.status = "repealed";
    ElMessageBox.confirm("确认废弃该制度?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
    updateRuleManagement(regulationForm).then(res => {
      if(res.code == 200){
        ElMessage.success('制度废弃成功')
            ElMessage.success("制度废弃成功");
        // showRegulationDialog.value = false
        getRegulationList()
        resetRegulationForm()
            getRegulationList();
            resetRegulationForm();
      }
        });
    })
  }).catch(() => {
      .catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消废弃'
    })
  })
}
          type: "info",
          message: "已取消废弃",
        });
      });
  };
// 发布制度
const submitRegulation = async () => {
  try {
    await regulationFormRef.value.validate()
    if(operationType.value == 'add'){
      await regulationFormRef.value.validate();
      if (operationType.value == "add") {
      addRuleManagement(regulationForm).then(res => {
        if(res.code == 200){
          ElMessage.success('制度发布成功')
          showRegulationDialog.value = false
          getRegulationList()
          resetRegulationForm()
            ElMessage.success("制度发布成功");
            showRegulationDialog.value = false;
            getRegulationList();
            resetRegulationForm();
        }
      })
        });
    }else{
      updateRuleManagement(regulationForm).then(res => {
        if(res.code == 200){
          ElMessage.success('制度编辑成功')
          showRegulationDialog.value = false
          resetRegulationForm()
          getRegulationList()
      }})}
            ElMessage.success("制度编辑成功");
            showRegulationDialog.value = false;
            resetRegulationForm();
            getRegulationList();
          }
        });
      }
  }catch(err){
    ElMessage.error(err.msg)
      ElMessage.error(err.msg);
  }
}
  };
//重置制度表单
const resetRegulationForm = () => {
  Object.assign(regulationForm, {
    id: '',
    regulationNum: '',
    title: '',
    category: '',
    content: '',
    version: '',
    status: 'active',
      id: "",
      regulationNum: "",
      title: "",
      category: "",
      content: "",
      version: "",
      status: "active",
    readCount: 0,
    effectiveTime: '',
      effectiveTime: "",
    scope: [],
    requireConfirm: false
})
}
      requireConfirm: false,
    });
  };
// 查看用印申请详情
const viewSealDetail = (row) => {
  currentSealDetail.value = row
  showSealDetailDialog.value = true
}
  const viewSealDetail = row => {
    currentSealDetail.value = row;
    showSealDetailDialog.value = true;
  };
// 审批用印申请
const approveSeal = (row) => {
  console.log(row)
  ElMessageBox.confirm('确认通过该用印申请?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const approveSeal = row => {
    console.log(row);
    ElMessageBox.confirm("确认通过该用印申请?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    row.status = 'approved'
      row.status = "approved";
    updateSealApplication(row).then(res => {
      if(res.code == 200){
        ElMessage.success('审批通过')
          ElMessage.success("审批通过");
      }
    })
  })
}
      });
    });
  };
// 拒绝用印申请
const rejectSeal = (row) => {
  ElMessageBox.prompt('请输入拒绝原因', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
  const rejectSeal = row => {
    ElMessageBox.prompt("请输入拒绝原因", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
    inputPattern: /\S+/,
    inputErrorMessage: '拒绝原因不能为空'
      inputErrorMessage: "拒绝原因不能为空",
  }).then(({ value }) => {
    row.status = 'rejected'
      row.status = "rejected";
    updateSealApplication(row).then(res => {
      if(res.code == 200){
        ElMessage.success('审批拒绝')
          ElMessage.success("审批拒绝");
      }
    })
    ElMessage.success('已拒绝申请')
  })
}
      });
      ElMessage.success("已拒绝申请");
    });
  };
// 获取在职员工列表
const getList = () => {
  tableLoading.value = true;
      //获取当前登录用户信息
  getUserProfile().then(res => {
    if(res.code == 200){
      console.log(res.data.userName)
      currentUser.value = res.data.userName
        console.log(res.data.userName);
        currentUser.value = res.data.userName;
    }
  })
  staffJoinListPage({staffState: 1, ...page}).then(res => {
    });
    staffJoinListPage({ staffState: 1, ...page })
      .then(res => {
    tableLoading.value = false;
    // tableData.value = res.data.records
    // //筛选出和currentUser同名的人员
    tableData.value = res.data.records.filter(item => item.staffName === currentUser.value)
        tableData.value = res.data.records.filter(
          item => item.staffName === currentUser.value
        );
    page.total = res.data.total;
      
    if(tableData.value.length == 0){
    ElMessage.error('当前用户未加入任何部门')
          ElMessage.error("当前用户未加入任何部门");
    }
  }).catch(err => {
    tableLoading.value = false;
  })
      .catch(err => {
        tableLoading.value = false;
      });
};
// 查看制度版本历史
const viewVersionHistory = (row) => {
  showVersionHistoryDialog.value = true
  const viewVersionHistory = row => {
    showVersionHistoryDialog.value = true;
  const params = {
    category: row.category
  }
      category: row.category,
    };
  listRuleManagement(page,params).then(res => {
    if(res.code == 200){
      versionHistory.value = res.data.records
        versionHistory.value = res.data.records;
    }
  })
}
    });
  };
// 查看制度详情
const viewRegulation = (row) => {
  getList()
  currentRegulationDetail.value = row
  showRegulationDetailDialog.value = true
  const viewRegulation = row => {
    getList();
    currentRegulationDetail.value = row;
    showRegulationDetailDialog.value = true;
  getReadingStatusByRuleId(row.id).then(res => {
    if(res.code == 200){
      readStatusList.value = res.data
        readStatusList.value = res.data;
      if(readStatusList.value.length==0 && tableData.value.length>0){
          const params = {
          ruleId: row.id,
          employee: tableData.value[0].staffName,
          department: tableData.value[0].postJob,
          status: 'unconfirmed'
        }
            status: "unconfirmed",
          };
        addReadingStatus(params).then(res => {
          if(res.code == 200){
            ElMessage.success('制度阅读成功')
              ElMessage.success("制度阅读成功");
          }
        })
          });
      }
    }
  })
}
    });
  };
// 查看制度阅读状态
const viewReadStatus = (row) => {
  showReadStatusDialog.value = true
  const viewReadStatus = row => {
    showReadStatusDialog.value = true;
  //查看阅读状态列表
  getReadingStatusByRuleId(row.id).then(res => {
    if(res.code == 200){
      readStatusList.value = res.data
        readStatusList.value = res.data;
    }
  })
}
    });
  };
//确认查看
const resetForm = (row) => {
  console.log("row",row)
  row.readCount = row.readCount + 1
  const resetForm = row => {
    console.log("row", row);
    row.readCount = row.readCount + 1;
  
  updateRuleManagement(row).then(res => {
    if(res.code == 200){
      ElMessage.success('查看数量修改成功')
        ElMessage.success("查看数量修改成功");
      //修改阅读状态
      //根据制度id和当前登录的员工得到阅读状态
      // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName )
@@ -643,81 +742,96 @@
      //   item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
      // }
      // 筛选当前员工对应该制度的阅读状态记录
      let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id);
        let statusItem = readStatusList.value.find(
          item =>
            item.employee === tableData.value[0].staffName &&
            item.ruleId === row.id
        );
      if (statusItem) {
        // 如果找到记录,更新状态和确认时间
        statusItem.status = 'confirmed';
          statusItem.status = "confirmed";
        // 格式化时间为"YYYY-MM-DD HH:mm:ss"格式
        const now = new Date();
        statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
          statusItem.confirmTime = `${now.getFullYear()}-${String(
            now.getMonth() + 1
          ).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String(
            now.getHours()
          ).padStart(2, "0")}:${String(now.getMinutes()).padStart(
            2,
            "0"
          )}:${String(now.getSeconds()).padStart(2, "0")}`;
        // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
        
        updateReadingStatus(statusItem).then(res => {
          if(res.code == 200){
            ElMessage.success('制度阅读状态修改成功')
              ElMessage.success("制度阅读状态修改成功");
          }
        })
          });
      }
    }
  })
}
    });
  };
// 导出用印申请
const { proxy } = getCurrentInstance()
  const { proxy } = getCurrentInstance();
const handleExport = () => {
  proxy.download('/sealApplicationManagement/export', { ...sealSearchForm }, '用印申请.xlsx')
}
    proxy.download(
      "/sealApplicationManagement/export",
      { ...sealSearchForm },
      "用印申请.xlsx"
    );
  };
// 获取印章申请列表数据
const getSealApplicationList = async () => {
  tableLoading.value = true
    tableLoading.value = true;
  listSealApplication(page,sealSearchForm)
  .then(res => {
    //获取当前登录的部门信息
// 获取当前登录的部门信息并过滤数据
    const currentFactoryName = userStore.currentFactoryName
        const currentFactoryName = userStore.currentFactoryName;
    if (currentFactoryName) {
      // 根据currentFactoryName过滤出department相同的数据
      sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName)
          sealApplications.value = res.data.records.filter(
            item => item.department === currentFactoryName
          );
      // 更新过滤后的总数
      page.total = sealApplications.value.length
          page.total = sealApplications.value.length;
    } else {
      // 如果没有currentFactoryName,则显示所有数据
      sealApplications.value = res.data.records
      page.total = res.data.total
          sealApplications.value = res.data.records;
          page.total = res.data.total;
    }
    // sealApplications.value = res.data.records
    // page.value.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
      .catch(err => {
        tableLoading.value = false;
      });
  };
// 获取规章制度列表数据
const getRegulationList = async () => {
  tableLoading.value = true
    tableLoading.value = true;
  listRuleManagement(page,regulationSearchForm)
  .then(res => {
    regulations.value = res.data.records
        regulations.value = res.data.records;
    // 过滤掉已废弃的制度
    // regulations.value = res.data.records.filter(item => item.status !== 'repealed')
    page.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
      .catch(err => {
        tableLoading.value = false;
      });
  };
onMounted(() => {
  // 初始化
  getSealApplicationList()
  getRegulationList()
})
    getSealApplicationList();
    getRegulationList();
  });
</script>
<style scoped>
src/views/equipmentManagement/defectManagement/index.vue
@@ -2,27 +2,34 @@
  <div class="defect-management">
    <!-- 操作按钮 -->
    <div class="actions">
      <el-button type="primary" @click="showRegisterDialog = true">登记缺陷</el-button>
      <el-button type="primary"
                 @click="showRegisterDialog = true">登记缺陷</el-button>
    </div>
    <!-- 缺陷列表 -->
    <el-table :data="defectList" style="width: 100%; margin-top: 10px;" border>
      <el-table-column prop="deviceName" label="设备名称" width="180"></el-table-column>
      <el-table-column prop="defectDescription" label="缺陷描述" win-width="300"></el-table-column>
      <el-table-column prop="status" label="状态" width="220">
    <el-table :data="defectList"
              style="width: 100%; margin-top: 10px;"
              border>
      <el-table-column prop="deviceName"
                       label="设备名称"
                       width="180"></el-table-column>
      <el-table-column prop="defectDescription"
                       label="缺陷描述"
                       win-width="300"></el-table-column>
      <el-table-column prop="status"
                       label="状态"
                       width="220">
        <template #default="{ row }">
          <el-tag :type="row.status === '严重缺陷' ? 'danger' : 'success'">
            {{ row.status }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="220">
      <el-table-column label="操作"
                       width="220">
        <template #default="{ row }">
          <el-button
            v-if="row.status === '严重缺陷' || row.status === '一般缺陷'"
          <el-button v-if="row.status === '严重缺陷' || row.status === '一般缺陷'"
            type="text"
            @click="eliminateDefect(row)"
          >
                     @click="eliminateDefect(row)">
            消除缺陷
          </el-button>
          <!-- <el-button
@@ -32,30 +39,38 @@
          >
            转维修单
          </el-button> -->
          <el-button type="text" @click="getLedger(row.deviceLedgerId)">
          <el-button type="text"
                     @click="getLedger(row.deviceLedgerId)">
            查看台账
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 缺陷登记对话框 -->
    <el-dialog title="登记设备缺陷" v-model="showRegisterDialog" width="50%">
      <el-form :model="defectForm" :rules="defectRules" ref="defectFormRef" label-width="100px">
        <el-form-item label="设备名称" prop="deviceName">
          <el-select v-model="defectForm.deviceLedgerId" @change="setDeviceModel">
            <el-option
              v-for="(item, index) in deviceOptions"
    <el-dialog title="登记设备缺陷"
               v-model="showRegisterDialog"
               width="50%">
      <el-form :model="defectForm"
               :rules="defectRules"
               ref="defectFormRef"
               label-width="100px">
        <el-form-item label="设备名称"
                      prop="deviceName">
          <el-select v-model="defectForm.deviceLedgerId"
                     @change="setDeviceModel">
            <el-option v-for="(item, index) in deviceOptions"
              :key="index"
              :label="item.deviceName"
              :value="item.id"
            ></el-option>
                       :value="item.id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="缺陷描述" prop="defectDescription">
          <el-input type="textarea" v-model="defectForm.defectDescription"></el-input>
        <el-form-item label="缺陷描述"
                      prop="defectDescription">
          <el-input type="textarea"
                    v-model="defectForm.defectDescription"></el-input>
        </el-form-item>
        <el-form-item label="设备状态" prop="status">
        <el-form-item label="设备状态"
                      prop="status">
          <el-radio-group v-model="defectForm.status">
            <el-radio label="正常">正常</el-radio>
            <el-radio label="一般缺陷">一般缺陷</el-radio>
@@ -65,27 +80,35 @@
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="submitDefectForm">确定</el-button>
          <el-button @click="showRegisterDialog = false">取消</el-button>
          <el-button type="primary" @click="submitDefectForm">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 缺陷设备台账对话框 -->
    <el-dialog title="缺陷设备台账" v-model="showLedgerDialog" width="80%">
      <el-table :data="ledgerList" style="width: 100%; margin-top: 10px;" border>
        <el-table-column prop="deviceName" label="设备名称"></el-table-column>
        <el-table-column prop="defectDescription" label="缺陷描述"></el-table-column>
        <el-table-column prop="status" label="状态"></el-table-column>
        <el-table-column prop="eliminateTime" label="消缺时间"></el-table-column>
    <el-dialog title="缺陷设备台账"
               v-model="showLedgerDialog"
               width="80%">
      <el-table :data="ledgerList"
                style="width: 100%; margin-top: 10px;"
                border>
        <el-table-column prop="deviceName"
                         label="设备名称"></el-table-column>
        <el-table-column prop="defectDescription"
                         label="缺陷描述"></el-table-column>
        <el-table-column prop="status"
                         label="状态"></el-table-column>
        <el-table-column prop="eliminateTime"
                         label="消缺时间"></el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
  import { ref, reactive } from "vue";
  import { ElMessage } from "element-plus";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
// 假设以下是后端接口
import {
@@ -93,8 +116,8 @@
  getDefectList,
  eliminateDefect as apiEliminateDefect, 
  getDefectLedger,
  deleteDefect
} from '@/api/equipmentManagement/defectManagement';
    deleteDefect,
  } from "@/api/equipmentManagement/defectManagement";
// 缺陷列表
const defectList = ref([]);
@@ -104,15 +127,19 @@
const showLedgerDialog = ref(false);
// 缺陷表单
const defectForm = reactive({
  deviceLedgerId: '',
  defectDescription: '',
  status: '',
    deviceLedgerId: "",
    defectDescription: "",
    status: "",
});
const deviceOptions = ref([]);
// 表单验证规则
const defectRules = reactive({
  deviceLedgerId: [{ required: true, message: '请输入设备名称', trigger: 'blur' }],
  defectDescription: [{ required: true, message: '请输入缺陷描述', trigger: 'blur' }]
    deviceLedgerId: [
      { required: true, message: "请输入设备名称", trigger: "blur" },
    ],
    defectDescription: [
      { required: true, message: "请输入缺陷描述", trigger: "blur" },
    ],
});
// 表单引用
const defectFormRef = ref(null);
@@ -132,10 +159,10 @@
    if (res.code === 200) {
      defectList.value = res.data.records;
    } else {
      ElMessage.error(res.message || '获取缺陷列表失败');
        ElMessage.error(res.message || "获取缺陷列表失败");
    }
  } catch (error) {
    ElMessage.error('获取缺陷列表失败');
      ElMessage.error("获取缺陷列表失败");
  }
};
@@ -146,30 +173,29 @@
    await defectFormRef.value.validate();
    const res = await registerDefect(defectForm);
    if (res.code === 200) {
      ElMessage.success('缺陷登记成功');
        ElMessage.success("缺陷登记成功");
      showRegisterDialog.value = false;
      fetchDefectList();
    } else {
      ElMessage.error(res.message || '缺陷登记失败');
        ElMessage.error(res.message || "缺陷登记失败");
    }
  } catch (error) {
    ElMessage.error('请填写完整表单信息');
      ElMessage.error("请填写完整表单信息");
  }
};
// 消除缺陷
const eliminateDefect = async (row) => {
  const eliminateDefect = async row => {
  try {
    const res = await apiEliminateDefect(row);
    if (res.code === 200) {
      ElMessage.success('缺陷消除成功');
        ElMessage.success("缺陷消除成功");
      fetchDefectList();
    } else {
      ElMessage.error(res.message || '缺陷消除失败');
        ElMessage.error(res.message || "缺陷消除失败");
    }
  } catch (error) {
    ElMessage.error('缺陷消除失败');
      ElMessage.error("缺陷消除失败");
  }
};
@@ -188,17 +214,17 @@
// };
// 获取缺陷设备台账
const getLedger = async (deviceLedgerId) => {
  const getLedger = async deviceLedgerId => {
  try {
    const res = await getDefectLedger(deviceLedgerId);
    if (res.code === 200) {
      ledgerList.value = res.data.records;
      showLedgerDialog.value = true;
    } else {
      ElMessage.error(res.message || '获取缺陷设备台账失败');
        ElMessage.error(res.message || "获取缺陷设备台账失败");
    }
  } catch (error) {
    ElMessage.error('获取缺陷设备台账失败');
      ElMessage.error("获取缺陷设备台账失败");
  }
};
src/views/equipmentManagement/inspectionManagement/components/formDia.vue
@@ -1,112 +1,154 @@
<template>
    <div>
        <el-dialog :title="operationType === 'add' ? '新增巡检任务' : '编辑巡检任务'"
                             v-model="dialogVisitable" width="800px" @close="cancel">
            <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
               v-model="dialogVisitable"
               width="800px"
               @close="cancel">
      <el-form ref="formRef"
               :model="form"
               :rules="rules"
               label-width="120px">
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="设备名称" prop="taskId">
                            <el-select v-model="form.taskId" @change="setDeviceModel" filterable>
                                <el-option
                                    v-for="(item, index) in deviceOptions"
            <el-form-item label="设备名称"
                          prop="taskId">
              <el-select v-model="form.taskId"
                         @change="setDeviceModel"
                         filterable>
                <el-option v-for="(item, index) in deviceOptions"
                                    :key="index"
                                    :label="item.deviceName"
                                    :value="item.id"
                                ></el-option>
                           :value="item.id"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="巡检人" prop="inspector">
                            <el-select v-model="form.inspector"                 filterable
            <el-form-item label="巡检人"
                          prop="inspector">
              <el-select v-model="form.inspector"
                         filterable
                                                 default-first-option
                                                 :reserve-keyword="false" placeholder="请选择" multiple clearable>
                                <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/>
                         :reserve-keyword="false"
                         placeholder="请选择"
                         multiple
                         clearable>
                <el-option v-for="item in userList"
                           :label="item.nickName"
                           :value="item.userId"
                           :key="item.userId" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="备注" prop="remarks">
                            <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" />
            <el-form-item label="备注"
                          prop="remarks">
              <el-input v-model="form.remarks"
                        placeholder="请输入备注"
                        type="textarea" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="登记时间" prop="dateStr">
                            <el-date-picker
                                v-model="form.dateStr"
            <el-form-item label="登记时间"
                          prop="dateStr">
              <el-date-picker v-model="form.dateStr"
                                type="date"
                                placeholder="选择登记日期"
                                format="YYYY-MM-DD"
                                value-format="YYYY-MM-DD"
                                style="width: 100%"
                            />
                              style="width: 100%" />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="任务频率" prop="frequencyType">
                            <el-select v-model="form.frequencyType" placeholder="请选择" clearable>
                                <el-option label="每日" value="DAILY"/>
                                <el-option label="每周" value="WEEKLY"/>
                                <el-option label="每月" value="MONTHLY"/>
            <el-form-item label="任务频率"
                          prop="frequencyType">
              <el-select v-model="form.frequencyType"
                         placeholder="请选择"
                         clearable>
                <el-option label="每日"
                           value="DAILY" />
                <el-option label="每周"
                           value="WEEKLY" />
                <el-option label="每月"
                           value="MONTHLY" />
                                <!-- <el-option label="季度" value="QUARTERLY"/> -->
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-time-picker v-model="form.frequencyDetail" placeholder="选择时间" format="HH:mm"
          <el-col :span="12"
                  v-if="form.frequencyType === 'DAILY' && form.frequencyType">
            <el-form-item label="日期"
                          prop="frequencyDetail">
              <el-time-picker v-model="form.frequencyDetail"
                              placeholder="选择时间"
                              format="HH:mm"
                                                            value-format="HH:mm" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-select v-model="form.week" placeholder="请选择" clearable style="width: 50%">
                                <el-option label="周一" value="MON"/>
                                <el-option label="周二" value="TUE"/>
                                <el-option label="周三" value="WED"/>
                                <el-option label="周四" value="THU"/>
                                <el-option label="周五" value="FRI"/>
                                <el-option label="周六" value="SAT"/>
                                <el-option label="周日" value="SUN"/>
          <el-col :span="12"
                  v-if="form.frequencyType === 'WEEKLY' && form.frequencyType">
            <el-form-item label="日期"
                          prop="frequencyDetail">
              <el-select v-model="form.week"
                         placeholder="请选择"
                         clearable
                         style="width: 50%">
                <el-option label="周一"
                           value="MON" />
                <el-option label="周二"
                           value="TUE" />
                <el-option label="周三"
                           value="WED" />
                <el-option label="周四"
                           value="THU" />
                <el-option label="周五"
                           value="FRI" />
                <el-option label="周六"
                           value="SAT" />
                <el-option label="周日"
                           value="SUN" />
                            </el-select>
                            <el-time-picker v-model="form.time" placeholder="选择时间" format="HH:mm"
                                                            value-format="HH:mm"  style="width: 50%"/>
              <el-time-picker v-model="form.time"
                              placeholder="选择时间"
                              format="HH:mm"
                              value-format="HH:mm"
                              style="width: 50%" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-date-picker
                                v-model="form.frequencyDetail"
          <el-col :span="12"
                  v-if="form.frequencyType === 'MONTHLY' && form.frequencyType">
            <el-form-item label="日期"
                          prop="frequencyDetail">
              <el-date-picker v-model="form.frequencyDetail"
                                type="datetime"
                                clearable
                                placeholder="选择开始日期"
                                format="DD,HH:mm"
                                value-format="DD,HH:mm"
                            />
                              value-format="DD,HH:mm" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-date-picker
                                v-model="form.frequencyDetail"
          <el-col :span="12"
                  v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType">
            <el-form-item label="日期"
                          prop="frequencyDetail">
              <el-date-picker v-model="form.frequencyDetail"
                                type="datetime"
                                clearable
                                placeholder="选择开始日期"
                                format="MM,DD,HH:mm"
                                value-format="MM,DD,HH:mm"
                            />
                              value-format="MM,DD,HH:mm" />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">保存</el-button>
                    <el-button @click="cancel">取消</el-button>
                    <el-button type="primary" @click="submitForm">保存</el-button>
                </div>
            </template>
        </el-dialog>
@@ -115,133 +157,132 @@
<script setup>
import {reactive, ref} from "vue";
import useUserStore from '@/store/modules/user'
  import useUserStore from "@/store/modules/user";
import {addOrEditTimingTask} from "@/api/inspectionManagement/index.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
const { proxy } = getCurrentInstance()
const emit = defineEmits()
const userStore = useUserStore()
  const { proxy } = getCurrentInstance();
  const emit = defineEmits();
  const userStore = useUserStore();
const dialogVisitable = ref(false);
const operationType = ref('add');
  const operationType = ref("add");
const deviceOptions = ref([]);
const data = reactive({
    form: {
        taskId: undefined,
        taskName: undefined,
        inspector: '',
        inspectorIds: '',
        remarks: '',
        frequencyType: '',
        frequencyDetail: '',
        week: '',
        time: '',
        dateStr: ''
      inspector: "",
      inspectorIds: "",
      remarks: "",
      frequencyType: "",
      frequencyDetail: "",
      week: "",
      time: "",
      dateStr: "",
    },
    rules: {
        taskId: [{ required: true, message: "请选择设备", trigger: "change" },],
        inspector: [{ required: true, message: "请输入巡检人", trigger: "blur" },],
        dateStr: [{ required: true, message: "请选择登记时间", trigger: "change" }]
    }
})
const { form, rules } = toRefs(data)
const userList = ref([])
      taskId: [{ required: true, message: "请选择设备", trigger: "change" }],
      inspector: [{ required: true, message: "请输入巡检人", trigger: "blur" }],
      dateStr: [{ required: true, message: "请选择登记时间", trigger: "change" }],
    },
  });
  const { form, rules } = toRefs(data);
  const userList = ref([]);
const loadDeviceName = async () => {
    const { data } = await getDeviceLedger();
    deviceOptions.value = data;
};
const setDeviceModel = (id) => {
    const option = deviceOptions.value.find((item) => item.id === id);
  const setDeviceModel = id => {
    const option = deviceOptions.value.find(item => item.id === id);
    if (option) {
        form.value.taskName = option.deviceName;
    }
}
  };
// 打开弹框
const openDialog = async (type, row) => {
    dialogVisitable.value = true
    operationType.value = type
    dialogVisitable.value = true;
    operationType.value = type;
    
    // 重置表单
    resetForm();
    
    // 加载用户列表
    userListNoPageByTenantId().then((res) => {
    userListNoPageByTenantId().then(res => {
        userList.value = res.data;
    });
    
    // 加载设备列表
    await loadDeviceName();
    
    if (type === 'edit' && row) {
        form.value = {...row}
        form.value.inspector = form.value.inspectorIds.split(',').map(Number)
    if (type === "edit" && row) {
      form.value = { ...row };
      form.value.inspector = form.value.inspectorIds.split(",").map(Number);
        
        // 如果有设备ID,自动设置设备信息
        if (form.value.taskId) {
            setDeviceModel(form.value.taskId);
        }
    }
}
  };
// 关闭对话框
const cancel = () => {
    resetForm()
    dialogVisitable.value = false
    emit('closeDia')
}
    resetForm();
    dialogVisitable.value = false;
    emit("closeDia");
  };
// 重置表单函数
const resetForm = () => {
    if (proxy.$refs.formRef) {
        proxy.$refs.formRef.resetFields()
      proxy.$refs.formRef.resetFields();
    }
    // 重置表单数据确保设备信息正确重置
    form.value = {
        taskId: undefined,
        taskName: undefined,
        inspector: '',
        inspectorIds: '',
        remarks: '',
        frequencyType: '',
        frequencyDetail: '',
        week: '',
        time: ''
    }
}
      inspector: "",
      inspectorIds: "",
      remarks: "",
      frequencyType: "",
      frequencyDetail: "",
      week: "",
      time: "",
    };
  };
// 提交表单
const submitForm = () => {
    proxy.$refs["formRef"].validate(async valid => {
        if (valid) {
            try {
                form.value.inspectorIds = form.value.inspector.join(',')
                delete form.value.inspector
          form.value.inspectorIds = form.value.inspector.join(",");
          delete form.value.inspector;
                
                if (form.value.frequencyType === 'WEEKLY') {
                    let frequencyDetail = ''
                    frequencyDetail = form.value.week + ',' + form.value.time
                    form.value.frequencyDetail = frequencyDetail
          if (form.value.frequencyType === "WEEKLY") {
            let frequencyDetail = "";
            frequencyDetail = form.value.week + "," + form.value.time;
            form.value.frequencyDetail = frequencyDetail;
                }
                
                let res = await userStore.getInfo()
                form.value.registrantId = res.user.userId
          let res = await userStore.getInfo();
          form.value.registrantId = res.user.userId;
                
                await addOrEditTimingTask(form.value)
                cancel()
                proxy.$modal.msgSuccess('提交成功')
          await addOrEditTimingTask(form.value);
          cancel();
          proxy.$modal.msgSuccess("提交成功");
            } catch (error) {
                proxy.$modal.msgError('提交失败,请重试')
          proxy.$modal.msgError("提交失败,请重试");
            }
        }
    })
}
defineExpose({ openDialog })
    });
  };
  defineExpose({ openDialog });
</script>
<style scoped>
</style>
src/views/equipmentManagement/spareParts/index.vue
@@ -2,91 +2,114 @@
  <div class="spare-part-category">
    <div class="table_list">
      <div class="actions">
        <el-text class="mx-1" size="large">设备分类</el-text>
        <el-text class="mx-1"
                 size="large">设备分类</el-text>
        <div>
          <el-button @click="fetchTreeData" :loading="loading">刷新</el-button>
          <el-button type="primary" @click="addCategory" >新增</el-button>
          <el-button @click="fetchTreeData"
                     :loading="loading">刷新</el-button>
          <el-button type="primary"
                     @click="addCategory">新增</el-button>
        </div>
      </div>
      <el-table
        v-loading="loading"
      <el-table v-loading="loading"
        :data="renderTableData"
        style="width: 100%; margin-top: 10px;"
        border
        row-key="id"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      >
        <el-table-column prop="name" label="分类名称" width="450">
                :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
        <el-table-column prop="name"
                         label="分类名称"
                         width="450">
          <template #default="{ row }">
            <span :style="{ paddingLeft: getIndentation(row) + 'px' }">
              {{ row.name }}
            </span>
          </template>
        </el-table-column>
        <el-table-column prop="sparePartsNo" label="分类编号" width="200"></el-table-column>
        <el-table-column prop="status" label="状态" width="100">
        <el-table-column prop="sparePartsNo"
                         label="分类编号"
                         width="200"></el-table-column>
        <el-table-column prop="status"
                         label="状态"
                         width="100">
          <template #default="{ row }">
            <el-tag type="success" size="small">{{ row.status }}</el-tag>
            <el-tag type="success"
                    size="small">{{ row.status }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="description" label="描述" win-width="330"></el-table-column>
        <el-table-column label="操作" width="180" fixed="right">
        <el-table-column prop="description"
                         label="描述"
                         win-width="330"></el-table-column>
        <el-table-column label="操作"
                         width="180"
                         fixed="right">
          <template #default="{ row }">
            <el-button
              type="text"
            <el-button type="text"
              size="small"
              @click="() => editCategory(row)"
              :disabled="loading"
            >
                       :disabled="loading">
              编辑
            </el-button>
            <el-button
              type="text"
            <el-button type="text"
              size="small"
              @click="() => deleteCategory(row.id)"
              style="color: #f56c6c;"
              :disabled="loading"
            >
                       :disabled="loading">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <el-dialog title="分类管理" v-model="dialogVisible" width="60%">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
        <el-form-item label="分类名称" prop="name">
    <el-dialog title="分类管理"
               v-model="dialogVisible"
               width="60%">
      <el-form :model="form"
               :rules="rules"
               ref="formRef"
               label-width="100px">
        <el-form-item label="分类名称"
                      prop="name">
          <el-input v-model="form.name"></el-input>
        </el-form-item>
        <el-form-item label="分类编号" prop="sparePartsNo">
        <el-form-item label="分类编号"
                      prop="sparePartsNo">
          <el-input v-model="form.sparePartsNo"></el-input>
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select v-model="form.status" placeholder="请选择状态">
            <el-option label="正常" value="正常"></el-option>
            <el-option label="禁用" value="禁用"></el-option>
        <el-form-item label="状态"
                      prop="status">
          <el-select v-model="form.status"
                     placeholder="请选择状态">
            <el-option label="正常"
                       value="正常"></el-option>
            <el-option label="禁用"
                       value="禁用"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="描述" prop="description">
        <el-form-item label="描述"
                      prop="description">
          <el-input v-model="form.description"></el-input>
        </el-form-item>
        <el-form-item label="上级分类" prop="parentId">
          <el-select v-model="form.parentId" placeholder="请选择上级分类">
            <el-option label="无上级分类" :value="null"></el-option>
            <el-option
              v-for="(item, index) in categories"
        <el-form-item label="上级分类"
                      prop="parentId">
          <el-select v-model="form.parentId"
                     placeholder="请选择上级分类">
            <el-option label="无上级分类"
                       :value="null"></el-option>
            <el-option v-for="(item, index) in categories"
              :key="index"
              :label="item.name"
              :value="item.id"
            ></el-option>
                       :value="item.id"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false" :disabled="formLoading">取消</el-button>
          <el-button type="primary" @click="submitForm" :loading="formLoading">确定</el-button>
          <el-button type="primary"
                     @click="submitForm"
                     :loading="formLoading">确定</el-button>
          <el-button @click="dialogVisible = false"
                     :disabled="formLoading">取消</el-button>
        </span>
      </template>
    </el-dialog>
@@ -94,9 +117,15 @@
</template>
<script setup>
import { ref, computed, onMounted, reactive, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { getSparePartsList, addSparePart, editSparePart, delSparePart,getSparePartsTree } from "@/api/equipmentManagement/spareParts";
  import { ref, computed, onMounted, reactive, watch } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import {
    getSparePartsList,
    addSparePart,
    editSparePart,
    delSparePart,
    getSparePartsTree,
  } from "@/api/equipmentManagement/spareParts";
// 加载状态
const loading = ref(false);
@@ -110,38 +139,34 @@
// 渲染用的表格数据
// const renderTableData = computed(() => buildTree(categories.value));
const renderTableData = ref([]);
const operationType = ref('add')
  const operationType = ref("add");
// 表单引用
const formRef = ref(null);
// 表单数据
const form = reactive({
  id:'',
  name: '',
  sparePartsNo: '',
  status: '',
  description: '',
  parentId: null
    id: "",
    name: "",
    sparePartsNo: "",
    status: "",
    description: "",
    parentId: null,
});
// 表单验证规则
const rules = reactive({
  name: [
    { required: true, message: '请输入分类名称', trigger: 'blur' }
  ],
    name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],
  sparePartsNo: [
    { required: true, message: '请输入分类编号', trigger: 'blur' }
      { required: true, message: "请输入分类编号", trigger: "blur" },
  ],
  status: [
    { required: true, message: '请选择状态', trigger: 'change' }
  ]
    status: [{ required: true, message: "请选择状态", trigger: "change" }],
});
// 获取缩进量
const getIndentation = (row) => {
  const getIndentation = row => {
  // 这里简单返回 20,可根据实际需求实现层级缩进逻辑
  return 20; 
};
// 定义 buildTree 函数
const buildTree = (flatData) => {
  const buildTree = flatData => {
  const map = {};
  const result = [];
  if(flatData){
@@ -167,12 +192,12 @@
    if (res.code === 200) {
      renderTableData.value = res.data;
    } else {
      ElMessage.error(res.message || '获取分类列表失败');
        ElMessage.error(res.message || "获取分类列表失败");
    }
  }catch (error) {
    ElMessage.error('获取分类列表失败');
      ElMessage.error("获取分类列表失败");
  }
}
  };
// 获取分类列表
const fetchCategories = async () => {
@@ -182,10 +207,10 @@
    if (res.code === 200) {
      categories.value = res.data.records;
    } else {
      ElMessage.error(res.message || '获取分类列表失败');
        ElMessage.error(res.message || "获取分类列表失败");
    }
  } catch (error) {
    ElMessage.error('获取分类列表失败');
      ElMessage.error("获取分类列表失败");
  } finally {
    loading.value = false;
  }
@@ -193,43 +218,43 @@
// 新增分类
const addCategory = () => {
  form.id = '';
  form.name = '';
  form.sparePartsNo = '';
  form.status = '';
  form.description = '';
    form.id = "";
    form.name = "";
    form.sparePartsNo = "";
    form.status = "";
    form.description = "";
  form.parentId = null;
  operationType.value = 'add'
    operationType.value = "add";
  dialogVisible.value = true;
  console.log('dialogVisible 更新为', dialogVisible.value);
    console.log("dialogVisible 更新为", dialogVisible.value);
};
// 编辑分类
const editCategory = (row) => {
  const editCategory = row => {
  Object.assign(form, row);
  operationType.value = 'edit'
    operationType.value = "edit";
  dialogVisible.value = true;
};
// 删除分类
const deleteCategory = async (id) => {
  const deleteCategory = async id => {
  try {
    await ElMessageBox.confirm('此操作将永久删除该分类,是否继续?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
      await ElMessageBox.confirm("此操作将永久删除该分类,是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
    });
    loading.value = true;
    const res = await delSparePart(id);
    if (res.code === 200) {
      ElMessage.success('删除成功');
        ElMessage.success("删除成功");
      fetchTreeData();
    } else {
      ElMessage.error(res.message || '删除失败');
        ElMessage.error(res.message || "删除失败");
    }
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败');
      if (error !== "cancel") {
        ElMessage.error("删除失败");
    }
  } finally {
    loading.value = false;
@@ -242,23 +267,23 @@
  try {
    await formRef.value.validate();
    formLoading.value = true;
    if (operationType.value === 'edit') {
      if (operationType.value === "edit") {
      let res = await editSparePart(form);
      if (res.code === 200) {
      ElMessage.success('编辑成功');
          ElMessage.success("编辑成功");
      dialogVisible.value = false;
      fetchTreeData();
    }
    } else {
      let res = await addSparePart(form);
        if (res.code === 200) {
        ElMessage.success('编辑成功');
          ElMessage.success("编辑成功");
        dialogVisible.value = false;
        fetchTreeData();
      }
    }
  } catch (error) {
    ElMessage.error('请填写完整表单信息');
      ElMessage.error("请填写完整表单信息");
  } finally {
    formLoading.value = false;
  }
@@ -358,7 +383,7 @@
/* 空状态样式 */
.el-table .cell:empty::before {
  content: '-';
    content: "-";
  color: #c0c4cc;
}
src/views/example/DynamicTableExample.vue
@@ -1,34 +1,31 @@
<template>
  <div class="app-container">
    <div class="search-form">
      <el-form :inline="true" :model="searchForm">
      <el-form :inline="true"
               :model="searchForm">
        <el-form-item label="部门">
          <el-input
            v-model="searchForm.department"
          <el-input v-model="searchForm.department"
            placeholder="请输入部门名称"
            clearable
            style="width: 200px"
          />
                    style="width: 200px" />
        </el-form-item>
        <el-form-item label="姓名">
          <el-input
            v-model="searchForm.name"
          <el-input v-model="searchForm.name"
            placeholder="请输入姓名"
            clearable
            style="width: 200px"
          />
                    style="width: 200px" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
          <el-button @click="handleReset">重置</el-button>
          <el-button type="success" @click="handleAdd">新增</el-button>
          <el-button type="success"
                     @click="handleAdd">新增</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="table-container">
      <DynamicTable
        ref="dynamicTableRef"
      <DynamicTable ref="dynamicTableRef"
        :data="tableData"
        :dict-types="dictTypes"
        :loading="loading"
@@ -43,59 +40,52 @@
        @select-change="handleSelectChange"
        @input-change="handleInputChange"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
                    @current-change="handleCurrentChange" />
    </div>
    <!-- 新增/编辑对话框 -->
    <el-dialog
      v-model="dialogVisible"
    <el-dialog v-model="dialogVisible"
      :title="dialogTitle"
      width="600px"
      append-to-body
    >
      <el-form
        ref="formRef"
               append-to-body>
      <el-form ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
      >
        <el-form-item label="部门" prop="department">
          <el-input v-model="form.department" placeholder="请输入部门" />
               label-width="100px">
        <el-form-item label="部门"
                      prop="department">
          <el-input v-model="form.department"
                    placeholder="请输入部门" />
        </el-form-item>
        <el-form-item label="姓名" prop="name">
          <el-input v-model="form.name" placeholder="请输入姓名" />
        <el-form-item label="姓名"
                      prop="name">
          <el-input v-model="form.name"
                    placeholder="请输入姓名" />
        </el-form-item>
        <el-form-item label="工号" prop="employeeId">
          <el-input v-model="form.employeeId" placeholder="请输入工号" />
        <el-form-item label="工号"
                      prop="employeeId">
          <el-input v-model="form.employeeId"
                    placeholder="请输入工号" />
        </el-form-item>
        <!-- 动态表单项:根据字典生成 -->
        <el-form-item
          v-for="dictItem in dynamicFormItems"
        <el-form-item v-for="dictItem in dynamicFormItems"
          :key="dictItem.value"
          :label="dictItem.label"
          :prop="dictItem.value"
        >
          <el-select
            v-model="form[dictItem.value]"
                      :prop="dictItem.value">
          <el-select v-model="form[dictItem.value]"
            placeholder="请选择"
            style="width: 100%"
          >
            <el-option
              v-for="option in dictItem.options"
                     style="width: 100%">
            <el-option v-for="option in dictItem.options"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            />
                       :value="option.value" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleSubmit">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit">确定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -103,231 +93,225 @@
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import DynamicTable from '@/components/DynamicTable/index.vue'
  import { ref, reactive, computed, onMounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import DynamicTable from "@/components/DynamicTable/index.vue";
// 响应式数据
const loading = ref(false)
const dialogVisible = ref(false)
const dialogTitle = ref('')
const editIndex = ref(-1)
const selectedRows = ref([])
  const loading = ref(false);
  const dialogVisible = ref(false);
  const dialogTitle = ref("");
  const editIndex = ref(-1);
  const selectedRows = ref([]);
// 搜索表单
const searchForm = reactive({
  department: '',
  name: ''
})
    department: "",
    name: "",
  });
// 表格数据
const tableData = ref([
  {
    id: 1,
    department: '技术部',
    name: '张三',
    employeeId: 'EMP001',
    status: '1',
    level: '2',
    position: '1'
      department: "技术部",
      name: "张三",
      employeeId: "EMP001",
      status: "1",
      level: "2",
      position: "1",
  },
  {
    id: 2,
    department: '人事部',
    name: '李四',
    employeeId: 'EMP002',
    status: '0',
    level: '1',
    position: '2'
      department: "人事部",
      name: "李四",
      employeeId: "EMP002",
      status: "0",
      level: "1",
      position: "2",
  },
  {
    id: 3,
    department: '财务部',
    name: '王五',
    employeeId: 'EMP003',
    status: '1',
    level: '3',
    position: '1'
  }
])
      department: "财务部",
      name: "王五",
      employeeId: "EMP003",
      status: "1",
      level: "3",
      position: "1",
    },
  ]);
// 字典类型配置
const dictTypes = ref([
  'sys_normal_disable', // 状态字典
  'sys_user_level',     // 级别字典
  'sys_user_position'   // 职位字典
])
    "sys_normal_disable", // 状态字典
    "sys_user_level", // 级别字典
    "sys_user_position", // 职位字典
  ]);
// 分页配置
const pagination = reactive({
  current: 1,
  size: 10,
  total: 0
})
    total: 0,
  });
// 表单数据
const form = reactive({
  department: '',
  name: '',
  employeeId: '',
  status: '',
  level: '',
  position: ''
})
    department: "",
    name: "",
    employeeId: "",
    status: "",
    level: "",
    position: "",
  });
// 表单验证规则
const rules = {
  department: [
    { required: true, message: '请输入部门', trigger: 'blur' }
  ],
  name: [
    { required: true, message: '请输入姓名', trigger: 'blur' }
  ],
  employeeId: [
    { required: true, message: '请输入工号', trigger: 'blur' }
  ]
}
    department: [{ required: true, message: "请输入部门", trigger: "blur" }],
    name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
    employeeId: [{ required: true, message: "请输入工号", trigger: "blur" }],
  };
// 动态表单项
const dynamicFormItems = computed(() => {
  // 这里可以根据字典数据动态生成表单项
  return [
    {
      label: '状态',
      value: 'status',
        label: "状态",
        value: "status",
      options: [
        { label: '启用', value: '1' },
        { label: '禁用', value: '0' }
      ]
          { label: "启用", value: "1" },
          { label: "禁用", value: "0" },
        ],
    },
    {
      label: '级别',
      value: 'level',
        label: "级别",
        value: "level",
      options: [
        { label: '初级', value: '1' },
        { label: '中级', value: '2' },
        { label: '高级', value: '3' }
      ]
          { label: "初级", value: "1" },
          { label: "中级", value: "2" },
          { label: "高级", value: "3" },
        ],
    },
    {
      label: '职位',
      value: 'position',
        label: "职位",
        value: "position",
      options: [
        { label: '员工', value: '1' },
        { label: '主管', value: '2' },
        { label: '经理', value: '3' }
      ]
    }
  ]
})
          { label: "员工", value: "1" },
          { label: "主管", value: "2" },
          { label: "经理", value: "3" },
        ],
      },
    ];
  });
// 组件引用
const dynamicTableRef = ref(null)
const formRef = ref(null)
  const dynamicTableRef = ref(null);
  const formRef = ref(null);
// 事件处理函数
const handleSearch = () => {
  // 实现搜索逻辑
  console.log('搜索条件:', searchForm)
  ElMessage.success('搜索功能待实现')
}
    console.log("搜索条件:", searchForm);
    ElMessage.success("搜索功能待实现");
  };
const handleReset = () => {
  searchForm.department = ''
  searchForm.name = ''
}
    searchForm.department = "";
    searchForm.name = "";
  };
const handleAdd = () => {
  dialogTitle.value = '新增员工'
  editIndex.value = -1
  resetForm()
  dialogVisible.value = true
}
    dialogTitle.value = "新增员工";
    editIndex.value = -1;
    resetForm();
    dialogVisible.value = true;
  };
const handleEdit = (row, index) => {
  dialogTitle.value = '编辑员工'
  editIndex.value = index
  Object.assign(form, row)
  dialogVisible.value = true
}
    dialogTitle.value = "编辑员工";
    editIndex.value = index;
    Object.assign(form, row);
    dialogVisible.value = true;
  };
const handleDelete = async (row, index) => {
  try {
    await ElMessageBox.confirm('确定要删除这条记录吗?', '提示', {
      type: 'warning'
    })
      await ElMessageBox.confirm("确定要删除这条记录吗?", "提示", {
        type: "warning",
      });
    
    tableData.value.splice(index, 1)
    ElMessage.success('删除成功')
      tableData.value.splice(index, 1);
      ElMessage.success("删除成功");
  } catch (error) {
    // 用户取消删除
  }
}
  };
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
}
  const handleSelectionChange = selection => {
    selectedRows.value = selection;
  };
const handleSelectChange = (row, prop, value) => {
  console.log('选择变化:', row, prop, value)
    console.log("选择变化:", row, prop, value);
  // 可以在这里处理数据更新逻辑
}
  };
const handleInputChange = (row, prop, value) => {
  console.log('输入变化:', row, prop, value)
    console.log("输入变化:", row, prop, value);
  // 可以在这里处理数据更新逻辑
}
  };
const handleSizeChange = (size) => {
  pagination.size = size
  const handleSizeChange = size => {
    pagination.size = size;
  // 重新加载数据
}
  };
const handleCurrentChange = (current) => {
  pagination.current = current
  const handleCurrentChange = current => {
    pagination.current = current;
  // 重新加载数据
}
  };
const handleSubmit = async () => {
  try {
    await formRef.value.validate()
      await formRef.value.validate();
    
    if (editIndex.value === -1) {
      // 新增
      const newRow = {
        id: Date.now(),
        ...form
      }
      tableData.value.push(newRow)
      ElMessage.success('新增成功')
          ...form,
        };
        tableData.value.push(newRow);
        ElMessage.success("新增成功");
    } else {
      // 编辑
      Object.assign(tableData.value[editIndex.value], form)
      ElMessage.success('编辑成功')
        Object.assign(tableData.value[editIndex.value], form);
        ElMessage.success("编辑成功");
    }
    
    dialogVisible.value = false
      dialogVisible.value = false;
  } catch (error) {
    console.error('表单验证失败:', error)
      console.error("表单验证失败:", error);
  }
}
  };
const resetForm = () => {
  Object.assign(form, {
    department: '',
    name: '',
    employeeId: '',
    status: '',
    level: '',
    position: ''
  })
  formRef.value?.resetFields()
}
      department: "",
      name: "",
      employeeId: "",
      status: "",
      level: "",
      position: "",
    });
    formRef.value?.resetFields();
  };
// 组件挂载时初始化数据
onMounted(() => {
  pagination.total = tableData.value.length
})
    pagination.total = tableData.value.length;
  });
</script>
<style scoped>
src/views/fileManagement/bookshelf/index.vue
@@ -1,12 +1,19 @@
<template>
  <div class="sample">
    <div class="main-content" v-if="!isDetail">
    <div class="main-content"
         v-if="!isDetail">
      <div class="search">
                 <div class="search_thing">
           <div class="search_label">仓库名称:</div>
           <div class="search_input">
             <el-select v-model="entity.warehouseId" placeholder="选择仓库" size="small" @change="warehouseChange">
               <el-option v-for="item in warehouse" :key="item.id" :label="item.label" :value="item.id">
            <el-select v-model="entity.warehouseId"
                       placeholder="选择仓库"
                       size="small"
                       @change="warehouseChange">
              <el-option v-for="item in warehouse"
                         :key="item.id"
                         :label="item.label"
                         :value="item.id">
               </el-option>
             </el-select>
           </div>
@@ -14,8 +21,14 @@
        <div class="search_thing">
          <div class="search_label">货架:</div>
          <div class="search_input">
            <el-select v-model="entity.shelfId" placeholder="选择货架" size="small" @change="handleShelf">
              <el-option v-for="item in shelf" :key="item.id" :label="item.label" :value="item.id">
            <el-select v-model="entity.shelfId"
                       placeholder="选择货架"
                       size="small"
                       @change="handleShelf">
              <el-option v-for="item in shelf"
                         :key="item.id"
                         :label="item.label"
                         :value="item.id">
              </el-option>
            </el-select>
          </div>
@@ -25,21 +38,32 @@
           <el-button size="small" type="primary" @click="handleShelf(entity.shelfId)">查询</el-button>
         </div> -->
        <div class="btns">
          <el-button size="small" style="color:#3A7BFA" @click="keepVisible=true">维护</el-button>
          <el-button size="small" style="color:#3A7BFA" @click="warehouseVisible=true,isEdit=false">添加仓库</el-button>
          <el-button size="small" style="color:#3A7BFA" @click="shelvesVisible=true,isEdit=false"
          <el-button size="small"
                     style="color:#3A7BFA"
                     @click="keepVisible=true">维护</el-button>
          <el-button size="small"
                     style="color:#3A7BFA"
                     @click="warehouseVisible=true,isEdit=false">添加仓库</el-button>
          <el-button size="small"
                     style="color:#3A7BFA"
                     @click="shelvesVisible=true,isEdit=false"
            :disabled="entity.warehouseId==null">添加货架</el-button>
        </div>
      </div>
      <div class="table" v-loading="tableLoading">
        <table class="tables" style="table-layout:fixed;" v-if="tableList.length>0">
      <div class="table"
           v-loading="tableLoading">
        <table class="tables"
               style="table-layout:fixed;"
               v-if="tableList.length>0">
          <tbody>
            <tr v-for="(item,index) in tableList" :key="index">
              <td v-for="(m,i) in item" :key="i" class="content">
            <tr v-for="(item,index) in tableList"
                :key="index">
              <td v-for="(m,i) in item"
                  :key="i"
                  class="content">
                <h4 v-if="m.row!=undefined">{{ m.row }} - {{ m.col }}</h4>
                <ul>
                  <el-tooltip
                  effect="dark"
                  <el-tooltip effect="dark"
                  placement="top"
                  v-for="(n,j) in m.documentationDtoList"
                  :key="j">
@@ -56,39 +80,59 @@
              </td>
            </tr>
            <tr>
              <td v-for="(item,index) in rowList" :key="index" style="background: ghostwhite;height: 20px;">{{ item }}
              <td v-for="(item,index) in rowList"
                  :key="index"
                  style="background: ghostwhite;height: 20px;">{{ item }}
              </td>
            </tr>
          </tbody>
        </table>
        <span v-else style="color: rgb(144, 147, 153);display: inline-block;position: absolute;top: 60%;left: 50%;transform: translate(-50%,-50%);">暂无数据</span>
        <span v-else
              style="color: rgb(144, 147, 153);display: inline-block;position: absolute;top: 60%;left: 50%;transform: translate(-50%,-50%);">暂无数据</span>
      </div>
    </div>
    <Detail v-else @hanldeBack="isDetail=false" :current="current" />
    <Detail v-else
            @hanldeBack="isDetail=false"
            :current="current" />
    <!-- 库位维护对话框 -->
    <el-dialog v-model="keepVisible" title="库位维护" width="350px" :append-to-body="true">
                                                       <el-tree :data="warehouse" ref="tree" node-key="id"
           highlight-current v-if="keepVisible"
    <el-dialog v-model="keepVisible"
               title="库位维护"
               width="350px"
               :append-to-body="true">
      <el-tree :data="warehouse"
               ref="tree"
               node-key="id"
               highlight-current
               v-if="keepVisible"
           empty-text="暂无数据">
        <template #default="{ node, data }">
          <div class="custom-tree-node" style="width: 100%;">
          <div class="custom-tree-node"
               style="width: 100%;">
            <el-row style="width: 100%;display: flex;align-items: center;">
              <el-col :span="14">
                <span>
                  <el-icon v-if="node.level < 2" class="folder-icon">
                  <el-icon v-if="node.level < 2"
                           class="folder-icon">
                    <FolderOpened />
                  </el-icon>
                  <el-icon v-else class="file-icon">
                  <el-icon v-else
                           class="file-icon">
                    <Document />
                  </el-icon>
                  {{ data.label }}
                </span>
              </el-col>
              <el-col :span="10" v-if="node.level<3">
                <el-button type="link" size="small" :icon="Edit" @click.stop="handleEdit(data,node.level)">
              <el-col :span="10"
                      v-if="node.level<3">
                <el-button type="link"
                           size="small"
                           :icon="Edit"
                           @click.stop="handleEdit(data,node.level)">
                </el-button>
                <el-button type="danger" size="small" :icon="Delete" @click.stop="handleDelete(data,node.level)">
                <el-button type="danger"
                           size="small"
                           :icon="Delete"
                           @click.stop="handleDelete(data,node.level)">
                </el-button>
              </el-col>
            </el-row>
@@ -97,197 +141,217 @@
      </el-tree>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="keepVisible = false">确 定</el-button>
          <el-button @click="keepVisible = false">取 消</el-button>
          <el-button type="primary" @click="keepVisible = false" >确 定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 仓库新增/修改对话框 -->
    <el-dialog v-model="warehouseVisible" :title="isEdit?'仓库修改':'仓库新增'" width="350px">
    <el-dialog v-model="warehouseVisible"
               :title="isEdit?'仓库修改':'仓库新增'"
               width="350px">
      <el-row>
        <el-col class="search_thing" :span="24">
        <el-col class="search_thing"
                :span="24">
          <div class="search_label"><span class="required-span">* </span>仓库名称:</div>
          <div class="search_input">
            <el-input v-model="name" size="small" @keyup.enter="confirmWarehouse"></el-input>
            <el-input v-model="name"
                      size="small"
                      @keyup.enter="confirmWarehouse"></el-input>
          </div>
        </el-col>
      </el-row>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="confirmWarehouse"
                     :loading="upLoadWarehouse">确 定</el-button>
          <el-button @click="warehouseVisible = false">取 消</el-button>
          <el-button type="primary" @click="confirmWarehouse" :loading="upLoadWarehouse">确 定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 货架新增/修改对话框 -->
    <el-dialog v-model="shelvesVisible" :title="isEdit?'货架修改':'货架新增'" width="350px">
    <el-dialog v-model="shelvesVisible"
               :title="isEdit?'货架修改':'货架新增'"
               width="350px">
      <el-row>
        <el-col class="search_thing" :span="24">
        <el-col class="search_thing"
                :span="24">
          <div class="search_label"><span class="required-span">* </span>货架名称:</div>
          <div class="search_input">
            <el-input v-model="shelves.name" size="small"></el-input>
            <el-input v-model="shelves.name"
                      size="small"></el-input>
          </div>
        </el-col>
      </el-row>
      <el-row>
        <el-col class="search_thing" :span="24">
        <el-col class="search_thing"
                :span="24">
          <div class="search_label"><span class="required-span">* </span>货架层数:</div>
          <div class="search_input">
            <el-input v-model="shelves.row" size="small"></el-input>
            <el-input v-model="shelves.row"
                      size="small"></el-input>
          </div>
        </el-col>
      </el-row>
      <el-row>
        <el-col class="search_thing" :span="24">
        <el-col class="search_thing"
                :span="24">
          <div class="search_label"><span class="required-span">* </span>货架列数:</div>
          <div class="search_input">
            <el-input v-model="shelves.col" size="small"></el-input>
            <el-input v-model="shelves.col"
                      size="small"></el-input>
          </div>
        </el-col>
      </el-row>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="confirmShelves"
                     :loading="upLoadShelves">确 定</el-button>
          <el-button @click="shelvesVisible = false">取 消</el-button>
          <el-button type="primary" @click="confirmShelves" :loading="upLoadShelves">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Edit, Delete, FolderOpened, Document } from '@element-plus/icons-vue'
import { getWarehouseList, addWarehouse, updateWarehouse, deleteWarehouse, getWarehouseStructure, addShelf, updateShelf, deleteShelf } from '@/api/fileManagement/bookshelf'
import Detail from './detail.vue'
  import { ref, reactive, onMounted, watch } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Edit, Delete, FolderOpened, Document } from "@element-plus/icons-vue";
  import {
    getWarehouseList,
    addWarehouse,
    updateWarehouse,
    deleteWarehouse,
    getWarehouseStructure,
    addShelf,
    updateShelf,
    deleteShelf,
  } from "@/api/fileManagement/bookshelf";
  import Detail from "./detail.vue";
// 响应式数据
const entity = reactive({
  warehouseId: null,
  shelfId: null
})
    shelfId: null,
  });
const warehouse = ref([])
const shelf = ref([])
const keepVisible = ref(false)
const warehouseVisible = ref(false)
const shelvesVisible = ref(false)
const upLoadWarehouse = ref(false)
const upLoadShelves = ref(false)
const tableList = ref([])
const rowList = ref([])
const value = ref('')
const name = ref('')
const shelves = reactive({})
const isEdit = ref(false)
const isDetail = ref(false)
const currentEdit = ref(null)
const tableLoading = ref(false)
const current = ref({})
  const warehouse = ref([]);
  const shelf = ref([]);
  const keepVisible = ref(false);
  const warehouseVisible = ref(false);
  const shelvesVisible = ref(false);
  const upLoadWarehouse = ref(false);
  const upLoadShelves = ref(false);
  const tableList = ref([]);
  const rowList = ref([]);
  const value = ref("");
  const name = ref("");
  const shelves = reactive({});
  const isEdit = ref(false);
  const isDetail = ref(false);
  const currentEdit = ref(null);
  const tableLoading = ref(false);
  const current = ref({});
// 模板引用
const organization = ref(null)
  const organization = ref(null);
// 监听器
watch(isEdit, (newVal) => {
  watch(isEdit, newVal => {
  if (!newVal) {
    Object.keys(shelves).forEach(key => delete shelves[key])
      Object.keys(shelves).forEach(key => delete shelves[key]);
  }
})
  });
// 方法
const selectList = async () => {
  // 这里需要替换为实际的API调用
  const res = await getWarehouseList()
  warehouse.value = res.data
    const res = await getWarehouseList();
    warehouse.value = res.data;
  
  if (warehouse.value.length == 0) {
    entity.warehouseId = ''
    entity.shelfId = ''
    tableList.value = []
      entity.warehouseId = "";
      entity.shelfId = "";
      tableList.value = [];
  }
  
  if (!entity.warehouseId && warehouse.value.length > 0) {
    entity.warehouseId = warehouse.value[0].id
    warehouseChange(entity.warehouseId)
      entity.warehouseId = warehouse.value[0].id;
      warehouseChange(entity.warehouseId);
    if (shelf.value.length > 0) {
      entity.shelfId = shelf.value[0].id
      handleShelf(entity.shelfId)
        entity.shelfId = shelf.value[0].id;
        handleShelf(entity.shelfId);
    } else {
      tableList.value = []
        tableList.value = [];
    }
  } else if (warehouse.value.length > 0) {
    warehouseChange(entity.warehouseId)
      warehouseChange(entity.warehouseId);
    if (shelf.value.length > 0) {
      entity.shelfId = shelf.value[0].id
      handleShelf(entity.shelfId)
        entity.shelfId = shelf.value[0].id;
        handleShelf(entity.shelfId);
    } else {
      tableList.value = []
        tableList.value = [];
    }
  }
}
  };
const confirmWarehouse = () => {
  if (!name.value) {
    ElMessage.error('请填写仓库名称')
    return
      ElMessage.error("请填写仓库名称");
      return;
  }
  upLoadWarehouse.value = true
    upLoadWarehouse.value = true;
  
  if (currentEdit.value && currentEdit.value.id) {
    // 修改仓库
    // 这里需要替换为实际的API调用
    updateWarehouse({
      id: currentEdit.value.id,
      warehouseName: name.value
        warehouseName: name.value,
    }).then(res => {
      upLoadWarehouse.value = false
      warehouseVisible.value = false
      currentEdit.value = null
      ElMessage.success('修改成功')
      selectList()
      name.value = ''
      warehouseChange(entity.warehouseId)
    })
        upLoadWarehouse.value = false;
        warehouseVisible.value = false;
        currentEdit.value = null;
        ElMessage.success("修改成功");
        selectList();
        name.value = "";
        warehouseChange(entity.warehouseId);
      });
  } else {
    // 新增仓库
    // 这里需要替换为实际的API调用
    addWarehouse({
      warehouseName: name.value
        warehouseName: name.value,
    }).then(res => {
      upLoadWarehouse.value = false
      warehouseVisible.value = false
      ElMessage.success('添加成功')
      selectList()
      name.value = ''
      warehouseChange(entity.warehouseId)
    })
        upLoadWarehouse.value = false;
        warehouseVisible.value = false;
        ElMessage.success("添加成功");
        selectList();
        name.value = "";
        warehouseChange(entity.warehouseId);
      });
  }
}
  };
const confirmShelves = () => {
  if (!shelves.name) {
    ElMessage.error('请填写货架名称')
    return
      ElMessage.error("请填写货架名称");
      return;
  }
  if (!shelves.row) {
    ElMessage.error('请填写货架层数')
    return
      ElMessage.error("请填写货架层数");
      return;
  }
  if (!shelves.col) {
    ElMessage.error('请填写货架列数')
    return
      ElMessage.error("请填写货架列数");
      return;
  }
  upLoadShelves.value = true
    upLoadShelves.value = true;
  
  if (currentEdit.value && currentEdit.value.id) {
    // 修改
@@ -296,19 +360,20 @@
      name: shelves.name,
      row: Number(shelves.row),
      col: Number(shelves.col),
      warehouseId: entity.warehouseId
    }).then(res => {
      upLoadShelves.value = false
      shelvesVisible.value = false
      ElMessage.success('修改成功')
      selectList()
      currentEdit.value = {}
    }).catch(err => {
      upLoadShelves.value = false
      shelvesVisible.value = false
      ElMessage.error('修改失败')
        warehouseId: entity.warehouseId,
    })
        .then(res => {
          upLoadShelves.value = false;
          shelvesVisible.value = false;
          ElMessage.success("修改成功");
          selectList();
          currentEdit.value = {};
        })
        .catch(err => {
          upLoadShelves.value = false;
          shelvesVisible.value = false;
          ElMessage.error("修改失败");
        });
  } else {
    // 新增
    // 这里需要替换为实际的API调用
@@ -316,153 +381,153 @@
      name: shelves.name,
      row: Number(shelves.row),
      col: Number(shelves.col),
      warehouseId: entity.warehouseId
    }).then(res => {
      upLoadShelves.value = false
      shelvesVisible.value = false
      ElMessage.success('添加成功')
      selectList()
      Object.keys(shelves).forEach(key => delete shelves[key])
    }).catch(err => {
      upLoadShelves.value = false
      shelvesVisible.value = false
      ElMessage.error('添加失败')
        warehouseId: entity.warehouseId,
    })
        .then(res => {
          upLoadShelves.value = false;
          shelvesVisible.value = false;
          ElMessage.success("添加成功");
          selectList();
          Object.keys(shelves).forEach(key => delete shelves[key]);
        })
        .catch(err => {
          upLoadShelves.value = false;
          shelvesVisible.value = false;
          ElMessage.error("添加失败");
        });
  }
  warehouseChange(entity.warehouseId)
}
    warehouseChange(entity.warehouseId);
  };
const handleDelete = (row, level) => {
  ElMessageBox.confirm('是否删除当前数据?', "警告", {
    ElMessageBox.confirm("是否删除当前数据?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
      type: "warning",
    })
      .then(() => {
    if (level == 1) {
      // 删除仓库
      deleteWarehouse([row.id]).then(res => {
        ElMessage.success('删除成功')
        selectList()
      })
            ElMessage.success("删除成功");
            selectList();
          });
    } else {
      // 删除货架
      deleteShelf({
        id: row.id
            id: row.id,
      }).then(res => {
        ElMessage.success('删除成功')
        selectList()
            ElMessage.success("删除成功");
            selectList();
          });
        }
        warehouseChange(entity.warehouseId);
      })
    }
    warehouseChange(entity.warehouseId)
  }).catch(() => {})
}
      .catch(() => {});
  };
const handleEdit = (data, level) => {
  isEdit.value = true
    isEdit.value = true;
  if (level == 1) {
    warehouseVisible.value = true
    currentEdit.value = data
    name.value = data.label
      warehouseVisible.value = true;
      currentEdit.value = data;
      name.value = data.label;
  } else {
    shelvesVisible.value = true
    currentEdit.value = data
      shelvesVisible.value = true;
      currentEdit.value = data;
    Object.assign(shelves, {
      name: data.label,
      row: data.row,
      col: data.col,
      warehouseId: data.warehouseId
    })
        warehouseId: data.warehouseId,
      });
  }
}
  };
const handelDetail = (row) => {
  current.value = row
  isDetail.value = true
}
  const handelDetail = row => {
    current.value = row;
    isDetail.value = true;
  };
// 根据文档状态返回对应的颜色
const getStatusColor = (status) => {
  if (status === '正常') {
    return '#34BD66' // 绿色
  } else if (status === '借出') {
    return '#F56C6C' // 红色
  const getStatusColor = status => {
    if (status === "正常") {
      return "#34BD66"; // 绿色
    } else if (status === "借出") {
      return "#F56C6C"; // 红色
  }
  return '#606266' // 默认颜色
}
    return "#606266"; // 默认颜色
  };
const warehouseChange = (val) => {
tableList.value = []
  const warehouseChange = val => {
    tableList.value = [];
let map = warehouse.value.find(a => {
  return a && a.id === val ? a : null
})
      return a && a.id === val ? a : null;
    });
if (map && map.children) {
  shelf.value = map.children
  entity.shelfId = ''
      shelf.value = map.children;
      entity.shelfId = "";
} else {
  shelf.value = []
      shelf.value = [];
}
currentEdit.value = null
}
    currentEdit.value = null;
  };
const handleShelf = async(e) => {
  const handleShelf = async e => {
  if (e) {
    tableLoading.value = true
    let data = []
    const res = await getWarehouseStructure({warehouseGoodsShelvesId:e})
      tableLoading.value = true;
      let data = [];
      const res = await getWarehouseStructure({ warehouseGoodsShelvesId: e });
    if(res.code == 200){
      data = res.data.map(m=>{
        m.books = m.documentationDtoList|[]
        return m
      })
          m.books = m.documentationDtoList | [];
          return m;
        });
    }else{
      ElMessage.error(res.message)
        ElMessage.error(res.message);
    }
    setTimeout(() => {
      tableLoading.value = false
      let set = new Set()
      tableList.value = []
      let arr = []
        tableLoading.value = false;
        let set = new Set();
        tableList.value = [];
        let arr = [];
      
      if (data && data.length > 0) {
        data.forEach(m => {
          if (m && m.row && m.col) {
            set.add(m.col)
              set.add(m.col);
            if (arr.length > 0) {
              if (arr.find(n => n.row == m.row)) {
                arr.push(m)
                  arr.push(m);
              } else {
                tableList.value.push(arr)
                arr = []
                arr.push(m)
                  tableList.value.push(arr);
                  arr = [];
                  arr.push(m);
              }
            } else {
              arr.push(m)
                arr.push(m);
            }
          }
        })
          });
        
        if (arr.length > 0) {
          tableList.value.push(arr)
            tableList.value.push(arr);
        }
      }
      
      rowList.value = []
        rowList.value = [];
      for (let i = 0; i < set.size; i++) {
        rowList.value.push(`${i + 1} 列`)
          rowList.value.push(`${i + 1} 列`);
      }
      console.log(6666, tableList.value,rowList.value,data)
    }, 1000)
        console.log(6666, tableList.value, rowList.value, data);
      }, 1000);
  }
}
  };
// 生命周期
onMounted(() => {
  selectList()
})
    selectList();
  });
</script>
<style scoped>
@@ -597,23 +662,23 @@
  }
  li:hover i {
    background: #3A7BFA;
    background: #3a7bfa;
  }
  li:hover .num {
    color: #3A7BFA;
    color: #3a7bfa;
  }
  .green {
    background: #E0F6EA;
    background: #e0f6ea;
  }
  .green i {
    background: #34BD66;
    background: #34bd66;
  }
  .green .num {
    color: #34BD66;
    color: #34bd66;
  }
  .el-dialog {
@@ -624,7 +689,7 @@
    display: flex;
    align-items: center;
    font-size: 14px;
    color: #3A7BFA;
    color: #3a7bfa;
    position: absolute;
    top: 23px;
    right: 54px;
src/views/inventoryManagement/stockWarning/index.vue
@@ -306,8 +306,9 @@
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDialog">取消</el-button>
        </div>
      </template>
    </el-dialog>
src/views/oaSystem/projectManagement/components/milestoneList.vue
@@ -2,18 +2,21 @@
<template>
  <div class="milestone-list-container">
    <el-timeline>
      <el-timeline-item
        v-for="milestone in milestoneList"
      <el-timeline-item v-for="milestone in milestoneList"
        :key="milestone.phaseId"
        :timestamp="milestone.endDate"
      >
                        :timestamp="milestone.endDate">
        <el-card>
          <template #header>
            <div class="card-header">
              <span>{{ milestone.phaseName }}</span>
              <div class="milestone-actions">
                <el-button type="text" size="small" @click="handleEdit(milestone)">编辑</el-button>
                <el-button type="text" size="small" @click="handleDelete(milestone)" danger>删除</el-button>
                <el-button type="text"
                           size="small"
                           @click="handleEdit(milestone)">编辑</el-button>
                <el-button type="text"
                           size="small"
                           @click="handleDelete(milestone)"
                           danger>删除</el-button>
              </div>
            </div>
          </template>
@@ -26,66 +29,67 @@
        </el-card>
      </el-timeline-item>
    </el-timeline>
    <!-- 无里程碑时的提示 -->
    <div v-if="milestoneList.length === 0" class="empty-tip">
    <div v-if="milestoneList.length === 0"
         class="empty-tip">
      <el-empty description="暂无里程碑数据" />
    </div>
    <!-- 编辑里程碑对话框 -->
    <el-dialog
      v-model="dialogVisible"
    <el-dialog v-model="dialogVisible"
      :title="'编辑里程碑: ' + (form.phaseName || '')"
      width="600px"
      :close-on-click-modal="false"
    >
      <el-form
        ref="formRef"
               :close-on-click-modal="false">
      <el-form ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
      >
        <el-form-item label="里程碑名称" prop="phaseName">
          <el-input v-model="form.phaseName" placeholder="请输入里程碑名称" />
               label-width="100px">
        <el-form-item label="里程碑名称"
                      prop="phaseName">
          <el-input v-model="form.phaseName"
                    placeholder="请输入里程碑名称" />
        </el-form-item>
        <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="开始日期" prop="startDate">
          <el-date-picker
            v-model="form.startDate"
            <el-form-item label="开始日期"
                          prop="startDate">
              <el-date-picker v-model="form.startDate"
            type="date"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            placeholder="选择开始日期"
            style="width: 100%"
          />
                              style="width: 100%" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="结束日期" prop="endDate">
          <el-date-picker
            v-model="form.endDate"
            <el-form-item label="结束日期"
                          prop="endDate">
              <el-date-picker v-model="form.endDate"
            type="date"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            placeholder="选择结束日期"
            style="width: 100%"
          />
                              style="width: 100%" />
        </el-form-item>
      </el-col>
    </el-row>
        <el-form-item label="状态" prop="status">
          <el-select v-model="form.status" placeholder="请选择状态">
            <el-option label="未开始" value="notStarted" />
            <el-option label="已完成" value="completed" />
            <el-option label="已延迟" value="delayed" />
        <el-form-item label="状态"
                      prop="status">
          <el-select v-model="form.status"
                     placeholder="请选择状态">
            <el-option label="未开始"
                       value="notStarted" />
            <el-option label="已完成"
                       value="completed" />
            <el-option label="已延迟"
                       value="delayed" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitEditForm">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitEditForm">确定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -93,40 +97,43 @@
</template>
<script setup>
import { ref, onMounted, watch, reactive } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { getProject, listProjectPhase, updateProjectPhase,delProjectPhase } from '@/api/oaSystem/projectManagement';
  import { ref, onMounted, watch, reactive } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import {
    getProject,
    listProjectPhase,
    updateProjectPhase,
    delProjectPhase,
  } from "@/api/oaSystem/projectManagement";
const props = defineProps({
  projectId: {
    type: String,
    required: true
  }
      required: true,
    },
});
const emit = defineEmits(['refresh']);
  const emit = defineEmits(["refresh"]);
const milestoneList = ref([]);
const dialogVisible = ref(false);
const formRef = ref(null);
const form = reactive({
  phaseId: '',
  phaseName: '',
  startDate: '',
  endDate: '',
  status: 'notStarted',
  projectId: props.projectId
    phaseId: "",
    phaseName: "",
    startDate: "",
    endDate: "",
    status: "notStarted",
    projectId: props.projectId,
});
// 表单验证规则
const rules = {
  phaseName: [
    { required: true, message: '请输入里程碑名称', trigger: 'blur' },
    { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
      { required: true, message: "请输入里程碑名称", trigger: "blur" },
      { min: 2, max: 50, message: "长度在 2 到 50 个字符", trigger: "blur" },
  ],
  status: [
    { required: true, message: '请选择状态', trigger: 'change' }
  ]
    status: [{ required: true, message: "请选择状态", trigger: "change" }],
};
// 获取里程碑列表
@@ -136,15 +143,15 @@
      milestoneList.value = res.data.rows || res.data;
      // 按目标日期排序
      // milestoneList.value.sort((a, b) => new Date(a.endDate) - new Date(b.endDate));
    })
      });
  } catch (error) {
    ElMessage.error('获取里程碑列表失败');
    console.error('获取里程碑列表失败:', error);
      ElMessage.error("获取里程碑列表失败");
      console.error("获取里程碑列表失败:", error);
  }
};
// 编辑里程碑
const handleEdit = (milestone) => {
  const handleEdit = milestone => {
  // 复制里程碑数据到表单
  Object.assign(form, {
    phaseId: milestone.phaseId,
@@ -152,7 +159,7 @@
    description: milestone.description,
    endDate: milestone.endDate,
    status: milestone.status,
    projectId: props.projectId
      projectId: props.projectId,
  });
  dialogVisible.value = true;
};
@@ -166,32 +173,32 @@
    const res = await updateProjectPhase(form);
    
    if (res.code === 200) {
      ElMessage.success('里程碑编辑成功');
        ElMessage.success("里程碑编辑成功");
      dialogVisible.value = false;
      getMilestoneList(); // 刷新列表
      emit('refresh'); // 通知父组件刷新
        emit("refresh"); // 通知父组件刷新
    } else {
      ElMessage.error(res.msg || '里程碑编辑失败');
        ElMessage.error(res.msg || "里程碑编辑失败");
    }
  } catch (error) {
    if (error.name === 'ValidationError') {
      if (error.name === "ValidationError") {
      // 表单验证失败,Element Plus会自动提示
      return;
    }
    ElMessage.error('里程碑编辑失败');
    console.error('编辑里程碑失败:', error);
      ElMessage.error("里程碑编辑失败");
      console.error("编辑里程碑失败:", error);
  }
};
// 删除里程碑
const handleDelete = (milestone) => {
  const handleDelete = milestone => {
  ElMessageBox.confirm(
    `确定要删除里程碑 "${milestone.phaseName}" 吗?删除后将无法恢复。`,
    '删除确认',
      "删除确认",
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
    }
  )
    .then(async () => {
@@ -200,49 +207,52 @@
        const res = await delProjectPhase(milestone.phaseId);
        
        if (res.code === 200) {
          ElMessage.success('里程碑删除成功');
            ElMessage.success("里程碑删除成功");
          getMilestoneList(); // 刷新列表
          emit('refresh'); // 通知父组件刷新
            emit("refresh"); // 通知父组件刷新
        } else {
          ElMessage.error(res.msg || '里程碑删除失败');
            ElMessage.error(res.msg || "里程碑删除失败");
        }
      } catch (error) {
        ElMessage.error('里程碑删除失败');
        console.error('删除里程碑失败:', error);
          ElMessage.error("里程碑删除失败");
          console.error("删除里程碑失败:", error);
      }
    })
    .catch(() => {
      // 用户取消删除
      ElMessage.info('已取消删除');
        ElMessage.info("已取消删除");
    });
};
// 获取状态标签类型
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusTypeMap = {
    notStarted: 'info',
    completed: 'success',
    delayed: 'danger'
      notStarted: "info",
      completed: "success",
      delayed: "danger",
  };
  return statusTypeMap[status] || 'default';
    return statusTypeMap[status] || "default";
};
// 获取状态文本
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusTextMap = {
    notStarted: '未开始',
    completed: '已完成',
    delayed: '已延迟'
      notStarted: "未开始",
      completed: "已完成",
      delayed: "已延迟",
  };
  return statusTextMap[status] || status;
};
// 监听项目ID变化
watch(() => props.projectId, () => {
  watch(
    () => props.projectId,
    () => {
  if (props.projectId) {
    getMilestoneList();
  }
});
    }
  );
// 初始化
onMounted(() => {
src/views/oaSystem/projectManagement/components/taskTree.vue
@@ -2,69 +2,98 @@
  <div class="task-tree-container">
    <!-- 任务树操作按钮 -->
    <div class="tree-actions mb10">
      <el-button type="primary" size="small" icon="Plus" @click="handleAddTask">添加任务</el-button>
      <el-button type="success" size="small" icon="RefreshRight" @click="refreshTree">刷新</el-button>
      <el-button type="info" size="small" icon="Filter" @click="toggleFilter">
      <el-button type="primary"
                 size="small"
                 icon="Plus"
                 @click="handleAddTask">添加任务</el-button>
      <el-button type="success"
                 size="small"
                 icon="RefreshRight"
                 @click="refreshTree">刷新</el-button>
      <el-button type="info"
                 size="small"
                 icon="Filter"
                 @click="toggleFilter">
        {{ showFilter ? '隐藏筛选' : '显示筛选' }}
      </el-button>
    </div>
    <!-- 筛选条件 -->
    <div v-if="showFilter" class="filter-section mb10">
      <el-form :inline="true" :model="filterParams">
    <div v-if="showFilter"
         class="filter-section mb10">
      <el-form :inline="true"
               :model="filterParams">
        <el-form-item label="任务状态">
          <el-select v-model="filterParams.status" placeholder="全部" clearable style="width: 120px">
            <el-option label="未开始" value="notStarted" />
            <el-option label="进行中" value="inProgress" />
            <el-option label="已完成" value="completed" />
            <el-option label="已逾期" value="overdue" />
          <el-select v-model="filterParams.status"
                     placeholder="全部"
                     clearable
                     style="width: 120px">
            <el-option label="未开始"
                       value="notStarted" />
            <el-option label="进行中"
                       value="inProgress" />
            <el-option label="已完成"
                       value="completed" />
            <el-option label="已逾期"
                       value="overdue" />
          </el-select>
        </el-form-item>
        <el-form-item label="负责人">
          <el-input v-model="filterParams.assignee" placeholder="输入负责人" clearable style="width: 150px" />
          <el-input v-model="filterParams.assignee"
                    placeholder="输入负责人"
                    clearable
                    style="width: 150px" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="small" @click="filterTree">筛选</el-button>
          <el-button size="small" @click="resetFilter">重置</el-button>
          <el-button type="primary"
                     size="small"
                     @click="filterTree">筛选</el-button>
          <el-button size="small"
                     @click="resetFilter">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 任务树 -->
    <div class="tree-content">
      <el-tree
        v-loading="loading"
      <el-tree v-loading="loading"
        :data="taskTreeData"
        :props="defaultProps"
        :expand-on-click-node="false"
        node-key="nodeId"
        ref="treeRef"
        @node-contextmenu="handleContextMenu"
        @node-click="handleNodeClick"
      >
               @node-click="handleNodeClick">
        <template #default="{ node, data }">
          <!-- 节点内容 -->
          <div class="tree-node-content" :class="{ 'phase-node': data.type === 'phase', 'task-node': data.type === 'task' }">
          <div class="tree-node-content"
               :class="{ 'phase-node': data.type === 'phase', 'task-node': data.type === 'task' }">
            <!-- 节点图标 -->
            <div class="node-icon">
              <i v-if="data.type === 'phase'" class="el-icon-folder text-primary" />
              <i v-else-if="data.status === 'completed'" class="el-icon-circle-check text-success" />
              <i v-else-if="data.status === 'inProgress'" class="el-icon-circle-check text-primary" />
              <i v-else-if="data.status === 'overdue'" class="el-icon-alarm-clock text-danger" />
              <i v-else class="el-icon-circle-close text-gray-400" />
              <i v-if="data.type === 'phase'"
                 class="el-icon-folder text-primary" />
              <i v-else-if="data.status === 'completed'"
                 class="el-icon-circle-check text-success" />
              <i v-else-if="data.status === 'inProgress'"
                 class="el-icon-circle-check text-primary" />
              <i v-else-if="data.status === 'overdue'"
                 class="el-icon-alarm-clock text-danger" />
              <i v-else
                 class="el-icon-circle-close text-gray-400" />
            </div>
            <!-- 节点标题和描述 -->
            <div class="node-info">
              <div class="node-title" :class="{ 'overdue-title': data.type === 'task' && data.status === 'overdue' }">
              <div class="node-title"
                   :class="{ 'overdue-title': data.type === 'task' && data.status === 'overdue' }">
                {{ node.label }}
                <span v-if="data.type === 'task' && data.priority === 'high'" class="priority-tag">高优</span>
                <span v-else-if="data.type === 'task' && data.priority === 'medium'" class="priority-tag medium">中优</span>
                <span v-if="data.type === 'task' && data.priority === 'high'"
                      class="priority-tag">高优</span>
                <span v-else-if="data.type === 'task' && data.priority === 'medium'"
                      class="priority-tag medium">中优</span>
              </div>
              <div v-if="data.description" class="node-description">{{ data.description }}</div>
              <div v-if="data.description"
                   class="node-description">{{ data.description }}</div>
              <!-- 任务元信息 -->
              <div v-if="data.type === 'task'" class="task-meta">
              <div v-if="data.type === 'task'"
                   class="task-meta">
                <span class="meta-item">
                  <i class="el-icon-user"></i>
                  {{ data.assigneeName || '未分配' }}
@@ -75,97 +104,115 @@
                </span>
              </div>
            </div>
            <!-- 任务进度条 -->
            <div v-if="data.type === 'task'" class="task-progress">
              <el-progress :percentage="data.progress || 0" :stroke-width="4" :show-text="false" />
            <div v-if="data.type === 'task'"
                 class="task-progress">
              <el-progress :percentage="data.progress || 0"
                           :stroke-width="4"
                           :show-text="false" />
            </div>
            <!-- 操作按钮 -->
            <div class="node-actions">
              <el-button
                v-if="data.type === 'task'"
              <el-button v-if="data.type === 'task'"
                type="text"
                size="small"
                icon="Edit"
                @click.stop="handleEditTask(data)"
                v-hasPermi="['oaSystem:task:edit']"
              />
              <el-button
                v-if="data.type === 'phase'"
                         v-hasPermi="['oaSystem:task:edit']" />
              <el-button v-if="data.type === 'phase'"
                type="text"
                size="small"
                icon="Plus"
                @click.stop="handleAddTaskUnderPhase(data)"
                v-hasPermi="['oaSystem:task:add']"
              />
              <el-button
                type="text"
                         v-hasPermi="['oaSystem:task:add']" />
              <el-button type="text"
                size="small"
                icon="Delete"
                @click.stop="handleDeleteNode(data)"
                v-hasPermi="['oaSystem:task:remove']"
              />
                         v-hasPermi="['oaSystem:task:remove']" />
            </div>
          </div>
        </template>
      </el-tree>
    </div>
    <!-- 右键菜单 -->
    <div v-if="showContextMenu" :style="contextMenuStyle" class="context-menu">
    <div v-if="showContextMenu"
         :style="contextMenuStyle"
         class="context-menu">
      <el-menu @select="handleContextMenuSelect">
        <el-menu-item v-if="selectedNode.type === 'task'" index="edit">编辑任务</el-menu-item>
        <el-menu-item v-if="selectedNode.type === 'phase'" index="addTask">添加子任务</el-menu-item>
        <el-menu-item v-if="selectedNode.type === 'task'"
                      index="edit">编辑任务</el-menu-item>
        <el-menu-item v-if="selectedNode.type === 'phase'"
                      index="addTask">添加子任务</el-menu-item>
        <el-menu-item index="delete">删除</el-menu-item>
        <el-menu-item index="expandAll">展开全部</el-menu-item>
        <el-menu-item index="collapseAll">收起全部</el-menu-item>
      </el-menu>
    </div>
    <!-- 任务表单对话框 -->
    <el-dialog :title="dialogTitle" v-model="dialogOpen" width="600px" append-to-body>
      <el-form ref="taskFormRef" :model="taskForm" :rules="taskRules" label-width="80px">
        <el-form-item label="任务名称" prop="taskName">
          <el-input v-model="taskForm.taskName" placeholder="请输入任务名称" />
    <el-dialog :title="dialogTitle"
               v-model="dialogOpen"
               width="600px"
               append-to-body>
      <el-form ref="taskFormRef"
               :model="taskForm"
               :rules="taskRules"
               label-width="80px">
        <el-form-item label="任务名称"
                      prop="taskName">
          <el-input v-model="taskForm.taskName"
                    placeholder="请输入任务名称" />
        </el-form-item>
        <el-form-item label="负责人" prop="assigneeId">
          <el-input v-model="taskForm.assigneeId" placeholder="请输入负责人ID" />
        <el-form-item label="负责人"
                      prop="assigneeId">
          <el-input v-model="taskForm.assigneeId"
                    placeholder="请输入负责人ID" />
        </el-form-item>
        <el-form-item label="开始日期" prop="startDate">
          <el-date-picker
            v-model="taskForm.startDate"
        <el-form-item label="开始日期"
                      prop="startDate">
          <el-date-picker v-model="taskForm.startDate"
            type="date"
            placeholder="选择开始日期"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="结束日期" prop="endDate">
          <el-date-picker
            v-model="taskForm.endDate"
        <el-form-item label="结束日期"
                      prop="endDate">
          <el-date-picker v-model="taskForm.endDate"
            type="date"
            placeholder="选择结束日期"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="优先级" prop="priority">
          <el-select v-model="taskForm.priority" placeholder="选择优先级">
            <el-option label="低" value="low" />
            <el-option label="中" value="medium" />
            <el-option label="高" value="high" />
        <el-form-item label="优先级"
                      prop="priority">
          <el-select v-model="taskForm.priority"
                     placeholder="选择优先级">
            <el-option label="低"
                       value="low" />
            <el-option label="中"
                       value="medium" />
            <el-option label="高"
                       value="high" />
          </el-select>
        </el-form-item>
        <el-form-item label="进度" prop="progress">
          <el-input-number v-model="taskForm.progress" :min="0" :max="100" style="width: 100%" />
        <el-form-item label="进度"
                      prop="progress">
          <el-input-number v-model="taskForm.progress"
                           :min="0"
                           :max="100"
                           style="width: 100%" />
        </el-form-item>
        <el-form-item label="描述" prop="description">
          <el-input v-model="taskForm.description" type="textarea" placeholder="请输入任务描述" />
        <el-form-item label="描述"
                      prop="description">
          <el-input v-model="taskForm.description"
                    type="textarea"
                    placeholder="请输入任务描述" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitTaskForm">确定</el-button>
          <el-button @click="dialogOpen = false">取消</el-button>
          <el-button type="primary" @click="submitTaskForm">确定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -173,18 +220,18 @@
</template>
<script setup>
import { ref, reactive, computed, watch, onMounted } from 'vue';
import { ElMessage, ElMessageBox, ElMenu, ElMenuItem } from 'element-plus';
  import { ref, reactive, computed, watch, onMounted } from "vue";
  import { ElMessage, ElMessageBox, ElMenu, ElMenuItem } from "element-plus";
// import { getProject, addTask, updateTask, deleteTask, deletePhase } from '@/api/oaSystem/projectManagement';
const props = defineProps({
  projectId: {
    type: String,
    required: true
  }
      required: true,
    },
});
const emit = defineEmits(['refresh']);
  const emit = defineEmits(["refresh"]);
// 组件状态
const loading = ref(false);
@@ -194,50 +241,57 @@
const selectedNode = ref({});
const showFilter = ref(false);
const dialogOpen = ref(false);
const dialogTitle = ref('');
  const dialogTitle = ref("");
const taskFormRef = ref();
// 筛选参数
const filterParams = reactive({
  status: '',
  assignee: ''
    status: "",
    assignee: "",
});
// 任务表单数据
const taskForm = reactive({
  taskId: undefined,
  taskName: '',
  description: '',
  startDate: '',
  endDate: '',
  assigneeId: '',
  assigneeName: '',
  status: 'notStarted',
    taskName: "",
    description: "",
    startDate: "",
    endDate: "",
    assigneeId: "",
    assigneeName: "",
    status: "notStarted",
  progress: 0,
  priority: 'medium',
  phaseId: '',
  projectId: props.projectId
    priority: "medium",
    phaseId: "",
    projectId: props.projectId,
});
// 表单验证规则
const taskRules = {
  taskName: [
    { required: true, message: '任务名称不能为空', trigger: 'blur' },
    { min: 2, max: 50, message: '任务名称长度在 2 到 50 个字符', trigger: 'blur' }
      { required: true, message: "任务名称不能为空", trigger: "blur" },
      {
        min: 2,
        max: 50,
        message: "任务名称长度在 2 到 50 个字符",
        trigger: "blur",
      },
  ],
  startDate: [
    { required: true, message: '开始日期不能为空', trigger: 'change' }
      { required: true, message: "开始日期不能为空", trigger: "change" },
  ],
  endDate: [
    { required: true, message: '结束日期不能为空', trigger: 'change' }
  ],
  assigneeId: [
    { required: true, message: '负责人不能为空', trigger: 'blur' }
  ],
    endDate: [{ required: true, message: "结束日期不能为空", trigger: "change" }],
    assigneeId: [{ required: true, message: "负责人不能为空", trigger: "blur" }],
  progress: [
    { required: true, message: '进度不能为空', trigger: 'blur' },
    { type: 'number', min: 0, max: 100, message: '进度必须在 0 到 100 之间', trigger: 'blur' }
  ]
      { required: true, message: "进度不能为空", trigger: "blur" },
      {
        type: "number",
        min: 0,
        max: 100,
        message: "进度必须在 0 到 100 之间",
        trigger: "blur",
      },
    ],
};
// 任务树数据
@@ -245,152 +299,152 @@
// 模拟任务数据
const mockTaskData = {
  'PRJ2023001': [
    PRJ2023001: [
    {
      phaseId: 'PHASE001',
      phaseName: '需求分析',
      startDate: '2023-11-01',
      endDate: '2023-11-15',
      status: 'completed',
        phaseId: "PHASE001",
        phaseName: "需求分析",
        startDate: "2023-11-01",
        endDate: "2023-11-15",
        status: "completed",
      tasks: [
        {
          taskId: 'TASK001',
          taskName: '需求调研',
          description: '调研用户需求和业务流程',
          startDate: '2023-11-01',
          endDate: '2023-11-05',
          assigneeId: 'USER001',
          assigneeName: '张三',
          status: 'completed',
            taskId: "TASK001",
            taskName: "需求调研",
            description: "调研用户需求和业务流程",
            startDate: "2023-11-01",
            endDate: "2023-11-05",
            assigneeId: "USER001",
            assigneeName: "张三",
            status: "completed",
          progress: 100,
          priority: 'medium'
            priority: "medium",
        },
        {
          taskId: 'TASK002',
          taskName: '需求文档编写',
          description: '编写详细的需求规格说明书',
          startDate: '2023-11-06',
          endDate: '2023-11-15',
          assigneeId: 'USER002',
          assigneeName: '李四',
          status: 'completed',
            taskId: "TASK002",
            taskName: "需求文档编写",
            description: "编写详细的需求规格说明书",
            startDate: "2023-11-06",
            endDate: "2023-11-15",
            assigneeId: "USER002",
            assigneeName: "李四",
            status: "completed",
          progress: 100,
          priority: 'high'
        }
      ]
            priority: "high",
          },
        ],
    },
    {
      phaseId: 'PHASE002',
      phaseName: '系统设计',
      startDate: '2023-11-16',
      endDate: '2023-12-10',
      status: 'completed',
        phaseId: "PHASE002",
        phaseName: "系统设计",
        startDate: "2023-11-16",
        endDate: "2023-12-10",
        status: "completed",
      tasks: [
        {
          taskId: 'TASK003',
          taskName: '系统架构设计',
          description: '设计系统整体架构',
          startDate: '2023-11-16',
          endDate: '2023-11-25',
          assigneeId: 'USER003',
          assigneeName: '王五',
          status: 'completed',
            taskId: "TASK003",
            taskName: "系统架构设计",
            description: "设计系统整体架构",
            startDate: "2023-11-16",
            endDate: "2023-11-25",
            assigneeId: "USER003",
            assigneeName: "王五",
            status: "completed",
          progress: 100,
          priority: 'high'
            priority: "high",
        },
        {
          taskId: 'TASK004',
          taskName: '数据库设计',
          description: '设计数据库表结构和关系',
          startDate: '2023-11-26',
          endDate: '2023-12-10',
          assigneeId: 'USER004',
          assigneeName: '赵六',
          status: 'completed',
            taskId: "TASK004",
            taskName: "数据库设计",
            description: "设计数据库表结构和关系",
            startDate: "2023-11-26",
            endDate: "2023-12-10",
            assigneeId: "USER004",
            assigneeName: "赵六",
            status: "completed",
          progress: 100,
          priority: 'medium'
        }
      ]
            priority: "medium",
          },
        ],
    },
    {
      phaseId: 'PHASE003',
      phaseName: '开发实现',
      startDate: '2023-12-11',
      endDate: '2024-01-31',
      status: 'inProgress',
        phaseId: "PHASE003",
        phaseName: "开发实现",
        startDate: "2023-12-11",
        endDate: "2024-01-31",
        status: "inProgress",
      tasks: [
        {
          taskId: 'TASK005',
          taskName: '前端开发',
          description: '开发用户界面和交互逻辑',
          startDate: '2023-12-11',
          endDate: '2024-01-15',
          assigneeId: 'USER005',
          assigneeName: '钱七',
          status: 'inProgress',
            taskId: "TASK005",
            taskName: "前端开发",
            description: "开发用户界面和交互逻辑",
            startDate: "2023-12-11",
            endDate: "2024-01-15",
            assigneeId: "USER005",
            assigneeName: "钱七",
            status: "inProgress",
          progress: 70,
          priority: 'high'
            priority: "high",
        },
        {
          taskId: 'TASK006',
          taskName: '后端开发',
          description: '开发业务逻辑和API接口',
          startDate: '2023-12-11',
          endDate: '2024-01-20',
          assigneeId: 'USER006',
          assigneeName: '孙八',
          status: 'inProgress',
            taskId: "TASK006",
            taskName: "后端开发",
            description: "开发业务逻辑和API接口",
            startDate: "2023-12-11",
            endDate: "2024-01-20",
            assigneeId: "USER006",
            assigneeName: "孙八",
            status: "inProgress",
          progress: 60,
          priority: 'high'
        }
      ]
    }
            priority: "high",
          },
        ],
      },
  ],
  // 默认数据
  default: [
    {
      phaseId: 'PHASE_DEFAULT1',
      phaseName: '准备阶段',
      startDate: '2023-01-01',
      endDate: '2023-03-31',
      status: 'completed',
        phaseId: "PHASE_DEFAULT1",
        phaseName: "准备阶段",
        startDate: "2023-01-01",
        endDate: "2023-03-31",
        status: "completed",
      tasks: [
        {
          taskId: 'TASK_DEFAULT1',
          taskName: '项目启动',
          description: '召开项目启动会议',
          startDate: '2023-01-01',
          endDate: '2023-01-05',
          assigneeId: 'USER_DEFAULT1',
          assigneeName: '负责人A',
          status: 'completed',
            taskId: "TASK_DEFAULT1",
            taskName: "项目启动",
            description: "召开项目启动会议",
            startDate: "2023-01-01",
            endDate: "2023-01-05",
            assigneeId: "USER_DEFAULT1",
            assigneeName: "负责人A",
            status: "completed",
          progress: 100,
          priority: 'high'
        }
      ]
            priority: "high",
          },
        ],
    },
    {
      phaseId: 'PHASE_DEFAULT2',
      phaseName: '执行阶段',
      startDate: '2023-04-01',
      endDate: '2023-09-30',
      status: 'inProgress',
        phaseId: "PHASE_DEFAULT2",
        phaseName: "执行阶段",
        startDate: "2023-04-01",
        endDate: "2023-09-30",
        status: "inProgress",
      tasks: [
        {
          taskId: 'TASK_DEFAULT2',
          taskName: '核心功能开发',
          description: '开发系统核心功能模块',
          startDate: '2023-04-01',
          endDate: '2023-06-30',
          assigneeId: 'USER_DEFAULT2',
          assigneeName: '负责人B',
          status: 'inProgress',
            taskId: "TASK_DEFAULT2",
            taskName: "核心功能开发",
            description: "开发系统核心功能模块",
            startDate: "2023-04-01",
            endDate: "2023-06-30",
            assigneeId: "USER_DEFAULT2",
            assigneeName: "负责人B",
            status: "inProgress",
          progress: 50,
          priority: 'high'
        }
      ]
    }
  ]
            priority: "high",
          },
        ],
      },
    ],
};
const taskTreeData = computed(() => {
@@ -403,12 +457,12 @@
  const filteredData = JSON.parse(JSON.stringify(rawTaskTreeData.value));
  
  // 递归筛选节点
  const filterNodes = (nodes) => {
    const filterNodes = nodes => {
    const result = [];
    
    nodes.forEach(node => {
      // 对于阶段节点,检查其子任务是否符合筛选条件
      if (node.type === 'phase' && node.children) {
        if (node.type === "phase" && node.children) {
        const filteredChildren = filterNodes(node.children);
        if (filteredChildren.length > 0) {
          // 保留至少有一个子任务符合条件的阶段
@@ -417,10 +471,13 @@
        }
      }
      // 对于任务节点,直接应用筛选条件
      else if (node.type === 'task') {
        const statusMatch = !filterParams.status || node.status === filterParams.status;
        const assigneeMatch = !filterParams.assignee ||
          (node.assigneeName && node.assigneeName.includes(filterParams.assignee));
        else if (node.type === "task") {
          const statusMatch =
            !filterParams.status || node.status === filterParams.status;
          const assigneeMatch =
            !filterParams.assignee ||
            (node.assigneeName &&
              node.assigneeName.includes(filterParams.assignee));
        
        if (statusMatch && assigneeMatch) {
          result.push(node);
@@ -436,14 +493,14 @@
// 树节点配置
const defaultProps = {
  children: 'children',
  label: (data) => {
    if (data.type === 'phase') {
    children: "children",
    label: data => {
      if (data.type === "phase") {
      return `${data.phaseName}`;
    } else {
      return `${data.taskName}`;
    }
  }
    },
};
// 加载任务树数据
@@ -466,20 +523,20 @@
    const phases = mockTaskData[props.projectId] || mockTaskData.default;
    rawTaskTreeData.value = buildTaskTree(phases);
  } catch (error) {
    ElMessage.error('加载任务树失败');
    console.error('加载任务树失败:', error);
      ElMessage.error("加载任务树失败");
      console.error("加载任务树失败:", error);
  } finally {
    loading.value = false;
  }
};
// 构建任务树
const buildTaskTree = (phases) => {
  const buildTaskTree = phases => {
  return phases.map(phase => ({
    nodeId: phase.phaseId,
    phaseId: phase.phaseId,
    phaseName: phase.phaseName,
    type: 'phase',
      type: "phase",
    children: (phase.tasks || []).map(task => ({
      nodeId: task.taskId,
      taskId: task.taskId,
@@ -494,14 +551,14 @@
      priority: task.priority,
      phaseId: task.phaseId,
      projectId: props.projectId,
      type: 'task'
    }))
        type: "task",
      })),
  }));
};
// 格式化日期范围
const formatDateRange = (startDate, endDate) => {
  if (!startDate || !endDate) return '';
    if (!startDate || !endDate) return "";
  return `${startDate} - ${endDate}`;
};
@@ -509,7 +566,7 @@
const refreshTree = () => {
  loadTaskTree();
  // 通知父组件刷新数据
  emit('refresh');
    emit("refresh");
};
// 切换筛选面板
@@ -524,14 +581,14 @@
// 重置筛选
const resetFilter = () => {
  filterParams.status = '';
  filterParams.assignee = '';
    filterParams.status = "";
    filterParams.assignee = "";
};
// 处理节点点击
const handleNodeClick = (data, node) => {
  // 切换展开/收起状态
  if (data.type === 'phase') {
    if (data.type === "phase") {
    node.expanded = !node.expanded;
  }
};
@@ -541,35 +598,35 @@
  event.preventDefault();
  selectedNode.value = data;
  contextMenuStyle.value = {
    position: 'fixed',
      position: "fixed",
    left: `${event.clientX}px`,
    top: `${event.clientY}px`,
    zIndex: 1000
      zIndex: 1000,
  };
  showContextMenu.value = true;
};
// 处理右键菜单选择
const handleContextMenuSelect = (index) => {
  const handleContextMenuSelect = index => {
  showContextMenu.value = false;
  switch (index) {
    case 'edit':
      if (selectedNode.value.type === 'task') {
      case "edit":
        if (selectedNode.value.type === "task") {
        handleEditTask(selectedNode.value);
      }
      break;
    case 'addTask':
      if (selectedNode.value.type === 'phase') {
      case "addTask":
        if (selectedNode.value.type === "phase") {
        handleAddTaskUnderPhase(selectedNode.value);
      }
      break;
    case 'delete':
      case "delete":
      handleDeleteNode(selectedNode.value);
      break;
    case 'expandAll':
      case "expandAll":
      treeRef.value?.expandAll();
      break;
    case 'collapseAll':
      case "collapseAll":
      treeRef.value?.collapseAll();
      break;
  }
@@ -578,52 +635,53 @@
// 添加任务
const handleAddTask = () => {
  resetTaskForm();
  dialogTitle.value = '添加任务';
    dialogTitle.value = "添加任务";
  dialogOpen.value = true;
};
// 在指定阶段下添加任务
const handleAddTaskUnderPhase = (phase) => {
  const handleAddTaskUnderPhase = phase => {
  resetTaskForm();
  taskForm.phaseId = phase.phaseId;
  dialogTitle.value = '添加子任务';
    dialogTitle.value = "添加子任务";
  dialogOpen.value = true;
};
// 编辑任务
const handleEditTask = (task) => {
  const handleEditTask = task => {
  resetTaskForm();
  Object.assign(taskForm, { ...task });
  dialogTitle.value = '编辑任务';
    dialogTitle.value = "编辑任务";
  dialogOpen.value = true;
};
// 删除节点
const handleDeleteNode = async (node) => {
  const confirmMessage = node.type === 'phase'
  const handleDeleteNode = async node => {
    const confirmMessage =
      node.type === "phase"
    ? `确定要删除阶段 "${node.phaseName}" 及其所有子任务吗?` 
    : `确定要删除任务 "${node.taskName}" 吗?`;
  
  await ElMessageBox.confirm(confirmMessage, '确认操作', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
    await ElMessageBox.confirm(confirmMessage, "确认操作", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).catch(() => {
    throw new Error('取消删除');
      throw new Error("取消删除");
  });
  
  try {
    if (node.type === 'phase') {
      if (node.type === "phase") {
      await deletePhase(node.phaseId);
    } else {
      await deleteTask(node.taskId);
    }
    ElMessage.success('删除成功');
      ElMessage.success("删除成功");
    refreshTree();
  } catch (error) {
    if (error.message !== '取消删除') {
      ElMessage.error('删除失败');
      console.error('删除失败:', error);
      if (error.message !== "取消删除") {
        ElMessage.error("删除失败");
        console.error("删除失败:", error);
    }
  }
};
@@ -631,16 +689,16 @@
// 重置任务表单
const resetTaskForm = () => {
  taskForm.taskId = undefined;
  taskForm.taskName = '';
  taskForm.description = '';
  taskForm.startDate = '';
  taskForm.endDate = '';
  taskForm.assigneeId = '';
  taskForm.assigneeName = '';
  taskForm.status = 'notStarted';
    taskForm.taskName = "";
    taskForm.description = "";
    taskForm.startDate = "";
    taskForm.endDate = "";
    taskForm.assigneeId = "";
    taskForm.assigneeName = "";
    taskForm.status = "notStarted";
  taskForm.progress = 0;
  taskForm.priority = 'medium';
  taskForm.phaseId = '';
    taskForm.priority = "medium";
    taskForm.phaseId = "";
  taskForm.projectId = props.projectId;
  
  if (taskFormRef.value) {
@@ -655,32 +713,35 @@
    
    if (taskForm.taskId) {
      await updateTask(taskForm);
      ElMessage.success('修改任务成功');
        ElMessage.success("修改任务成功");
    } else {
      await addTask(taskForm);
      ElMessage.success('添加任务成功');
        ElMessage.success("添加任务成功");
    }
    
    dialogOpen.value = false;
    refreshTree();
  } catch (error) {
    console.error('提交表单失败:', error);
      console.error("提交表单失败:", error);
  }
};
// 点击其他区域关闭右键菜单
document.addEventListener('click', () => {
  document.addEventListener("click", () => {
  if (showContextMenu.value) {
    showContextMenu.value = false;
  }
});
// 监听项目ID变化
watch(() => props.projectId, (newProjectId) => {
  watch(
    () => props.projectId,
    newProjectId => {
  if (newProjectId) {
    loadTaskTree();
  }
});
    }
  );
// 初始化
onMounted(() => {
src/views/oaSystem/projectManagement/index.vue
@@ -1,54 +1,59 @@
<template>
  <div class="app-container">
    <!-- 顶部搜索和操作栏 -->
    <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="80px">
      <el-form-item label="项目名称" prop="projectName">
        <el-input
          v-model="queryParams.projectName"
    <el-form :model="queryParams"
             ref="queryRef"
             :inline="true"
             label-width="80px">
      <el-form-item label="项目名称"
                    prop="projectName">
        <el-input v-model="queryParams.projectName"
          placeholder="请输入项目名称"
          clearable
          style="width: 240px"
          @keyup.enter="handleQuery"
        />
                  @keyup.enter="handleQuery" />
      </el-form-item>
      <el-form-item label="负责人" prop="managerName">
        <el-input
          v-model="queryParams.managerName"
      <el-form-item label="负责人"
                    prop="managerName">
        <el-input v-model="queryParams.managerName"
          placeholder="请输入负责人姓名"
          clearable
          style="width: 240px"
          @keyup.enter="handleQuery"
        />
                  @keyup.enter="handleQuery" />
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-select
          v-model="queryParams.status"
      <el-form-item label="状态"
                    prop="status">
        <el-select v-model="queryParams.status"
          placeholder="项目状态"
          clearable
          style="width: 150px"
        >
          <el-option label="规划中" value="planning" />
          <el-option label="进行中" value="inProgress" />
          <el-option label="已完成" value="completed" />
          <el-option label="已暂停" value="paused" />
                   style="width: 150px">
          <el-option label="规划中"
                     value="planning" />
          <el-option label="进行中"
                     value="inProgress" />
          <el-option label="已完成"
                     value="completed" />
          <el-option label="已暂停"
                     value="paused" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
        <el-button type="primary"
                   icon="Search"
                   @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh"
                   @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <!-- 工具栏 -->
    <el-row :gutter="10" class="mb8">
    <el-row :gutter="10"
            class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
        <el-button type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['oaSystem:project:add']"
        >新增项目</el-button>
                   v-hasPermi="['oaSystem:project:add']">新增项目</el-button>
      </el-col>
      <!-- <el-col :span="1.5">
        <el-button
@@ -71,125 +76,99 @@
        >删除项目</el-button>
      </el-col> -->
      <el-col :span="1.5">
        <el-button
          type="warning"
        <el-button type="warning"
          plain
          icon="Download"
          @click="handleExport"
          v-hasPermi="['oaSystem:project:export']"
        >导出项目</el-button>
                   v-hasPermi="['oaSystem:project:export']">导出项目</el-button>
      </el-col>
    </el-row>
    <!-- 项目列表表格 -->
    <el-table
      v-loading="loading"
    <el-table v-loading="loading"
      :data="projectList"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="50" align="center" />
      <el-table-column
        label="项目编号"
              @selection-change="handleSelectionChange">
      <el-table-column type="selection"
                       width="50"
                       align="center" />
      <el-table-column label="项目编号"
        align="center"
        prop="projectId"
        width="100"
      />
      <el-table-column
        label="项目名称"
                       width="100" />
      <el-table-column label="项目名称"
        align="center"
        prop="projectName"
        :show-overflow-tooltip="true"
      />
      <el-table-column
        label="负责人"
                       :show-overflow-tooltip="true" />
      <el-table-column label="负责人"
        align="center"
        prop="managerName"
      />
      <el-table-column
        label="开始日期"
                       prop="managerName" />
      <el-table-column label="开始日期"
        align="center"
        prop="startDate"
        width="120"
      />
      <el-table-column
        label="结束日期"
                       width="120" />
      <el-table-column label="结束日期"
        align="center"
        prop="endDate"
        width="120"
      />
      <el-table-column
        label="状态"
                       width="120" />
      <el-table-column label="状态"
        align="center"
        prop="status"
        width="90"
      >
                       width="90">
        <template #default="scope">
          <el-tag :type="getStatusType(scope.row.status)">{{ getStatusText(scope.row.status) }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column
        label="完成度"
      <el-table-column label="完成度"
        align="center"
        prop="completionRate"
        width="100"
      >
                       width="100">
        <template #default="scope">
          <el-progress :percentage="scope.row.completionRate" :stroke-width="6" />
          <el-progress :percentage="scope.row.completionRate"
                       :stroke-width="6" />
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
      <el-table-column label="操作"
        align="center"
        width="180"
        class-name="small-padding fixed-width"
      >
                       class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button
            link
          <el-button link
            type="primary"
            icon="Search"
            @click="handleView(scope.row)"
            v-hasPermi="['oaSystem:project:query']"
          >详情</el-button>
          <el-button
            link
                     v-hasPermi="['oaSystem:project:query']">详情</el-button>
          <el-button link
            type="primary"
            icon="Edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['oaSystem:project:edit']"
          >编辑</el-button>
          <el-button
            link
                     v-hasPermi="['oaSystem:project:edit']">编辑</el-button>
          <el-button link
            type="danger"
            icon="Delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['oaSystem:project:remove']"
          >删除</el-button>
                     v-hasPermi="['oaSystem:project:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页组件 -->
    <pagination
      v-show="total > 0"
    <pagination v-show="total > 0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />
                @pagination="getList" />
    <!-- 项目表单对话框 -->
    <el-dialog :title="title" v-model="open" width="600px" append-to-body>
      <project-form
        ref="projectFormRef"
    <el-dialog :title="title"
               v-model="open"
               width="600px"
               append-to-body>
      <project-form ref="projectFormRef"
        :form="form"
        :rules="rules"
        :visible="open"
      />
                    :visible="open" />
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">确定</el-button>
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -197,14 +176,20 @@
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import Pagination from '@/components/Pagination';
import ProjectForm from './components/projectForm.vue';
import { useRouter } from 'vue-router';
  import { ref, reactive, computed, onMounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import Pagination from "@/components/Pagination";
  import ProjectForm from "./components/projectForm.vue";
  import { useRouter } from "vue-router";
const { proxy } = getCurrentInstance();
// 导入项目管理API接口
import { listProject, addProject, updateProject, delProject, exportProject } from '@/api/oaSystem/projectManagement';
  import {
    listProject,
    addProject,
    updateProject,
    delProject,
    exportProject,
  } from "@/api/oaSystem/projectManagement";
// import { listUser } from '@/api/system/user'; // 导入用户列表API接口
// 创建router实例
@@ -217,44 +202,45 @@
const queryParams = reactive({
  pageNum: 1,
  pageSize: 10,
  projectName: '',
  managerName: '',
  status: ''
    projectName: "",
    managerName: "",
    status: "",
});
// 表单数据
const form = reactive({
  projectId: undefined,
  projectName: '',
  description: '',
  startDate: '',
  endDate: '',
  managerId: '',
  managerName: '',
  status: 'planning',
  completionRate: 0
    projectName: "",
    description: "",
    startDate: "",
    endDate: "",
    managerId: "",
    managerName: "",
    status: "planning",
    completionRate: 0,
});
// 表单校验规则
const rules = {
  projectName: [
    { required: true, message: '项目名称不能为空', trigger: 'blur' },
    { min: 2, max: 50, message: '项目名称长度在 2 到 50 个字符', trigger: 'blur' }
      { required: true, message: "项目名称不能为空", trigger: "blur" },
      {
        min: 2,
        max: 50,
        message: "项目名称长度在 2 到 50 个字符",
        trigger: "blur",
      },
  ],
  startDate: [
    { required: true, message: '开始日期不能为空', trigger: 'change' }
      { required: true, message: "开始日期不能为空", trigger: "change" },
  ],
  endDate: [
    { required: true, message: '结束日期不能为空', trigger: 'change' }
  ],
  managerId: [
    { required: true, message: '负责人不能为空', trigger: 'blur' }
  ]
    endDate: [{ required: true, message: "结束日期不能为空", trigger: "change" }],
    managerId: [{ required: true, message: "负责人不能为空", trigger: "blur" }],
};
// 对话框状态
const open = ref(false);
const title = ref('');
  const title = ref("");
const projectFormRef = ref();
const queryRef = ref();
@@ -275,8 +261,8 @@
    projectList.value = data.records;
    total.value = data.total;
  } catch (error) {
    ElMessage.error('获取项目列表失败');
    console.error('获取项目列表失败:', error);
      ElMessage.error("获取项目列表失败");
      console.error("获取项目列表失败:", error);
  } finally {
    loading.value = false;
  }
@@ -297,7 +283,7 @@
};
// 选中行变化
const handleSelectionChange = (selection) => {
  const handleSelectionChange = selection => {
  selectedRowKeys.value = selection.map(item => item.projectId);
};
@@ -305,37 +291,40 @@
const handleAdd = () => {
  resetForm();
  open.value = true;
  title.value = '新增项目';
    title.value = "新增项目";
};
// 编辑项目 
const handleUpdate = async (row) => {
  const handleUpdate = async row => {
  resetForm();
  const projectId = row.projectId || selectedRowKeys.value[0];
    try {
    // const { data } = await getProject(projectId);
    Object.assign(form, row);
    open.value = true;
    title.value = '编辑项目';
      title.value = "编辑项目";
  } catch (error) {
    ElMessage.error('获取项目详情失败');
    console.error('获取项目详情失败:', error);
      ElMessage.error("获取项目详情失败");
      console.error("获取项目详情失败:", error);
  }
};
// 删除项目
const handleDelete = async (row) => {
  const handleDelete = async row => {
  // const projectIds = row.projectId ? [row.projectId] : selectedRowKeys.value;
  const projectNames = row.projectName ? [row.projectName] :
    projectList.value.filter(item => projectIds.includes(item.projectId)).map(item => item.projectName);
    const projectNames = row.projectName
      ? [row.projectName]
      : projectList.value
          .filter(item => projectIds.includes(item.projectId))
          .map(item => item.projectName);
  
  const confirmMessage = `确定要删除项目 "${projectNames.join('、')}" 吗?`;
  await ElMessageBox.confirm(confirmMessage, '确认操作', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
    const confirmMessage = `确定要删除项目 "${projectNames.join("、")}" 吗?`;
    await ElMessageBox.confirm(confirmMessage, "确认操作", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).catch(() => {
    throw new Error('取消删除');
      throw new Error("取消删除");
  });
  
  try {
@@ -344,12 +333,12 @@
    // } else {
    //   await delProjectBatch(projectIds);
    // }
    ElMessage.success('删除成功');
      ElMessage.success("删除成功");
    getList();
  } catch (error) {
    if (error.message !== '取消删除') {
      ElMessage.error('删除失败');
      console.error('删除项目失败:', error);
      if (error.message !== "取消删除") {
        ElMessage.error("删除失败");
        console.error("删除项目失败:", error);
    }
  }
  // try {
@@ -362,7 +351,6 @@
  //   // 模拟网络延迟
  //   await new Promise(resolve => setTimeout(resolve, 300));
   
  //   ElMessage.success('删除成功');
  //   getList();
  // } catch (error) {
@@ -373,12 +361,12 @@
};
// 查看项目详情
const handleView = (row) => {
  const handleView = row => {
  const projectId = row.projectId;
  // 跳转到项目详情页面
  router.push({
    path: `/oaSystem/projectManagement/projectDetail/${projectId}`,
    query: { projectName: row.projectName }
      query: { projectName: row.projectName },
  });
};
@@ -396,7 +384,11 @@
    type: "warning",
  })
    .then(() => {
      proxy.download(`/oA/project/export/${ids.join(',')}`, {}, "项目数据.xlsx");
        proxy.download(
          `/oA/project/export/${ids.join(",")}`,
          {},
          "项目数据.xlsx"
        );
      ElMessage.success("导出成功");
      ids = [];
    })
@@ -411,16 +403,16 @@
    if (form.projectId) {
      await updateProject(form);
      ElMessage.success('修改项目成功');
        ElMessage.success("修改项目成功");
    } else {
      console.log("form",form);
      await addProject(form);
      ElMessage.success('新增项目成功');
        ElMessage.success("新增项目成功");
    }
    open.value = false;
    getList();
  } catch (error) {
    console.error('提交表单失败:', error);
      console.error("提交表单失败:", error);
  }
};
@@ -433,13 +425,13 @@
// 重置表单
const resetForm = () => {
  form.projectId = undefined;
  form.projectName = '';
  form.description = '';
  form.startDate = '';
  form.endDate = '';
  form.managerId = '';
  form.managerName = '';
  form.status = 'planning';
    form.projectName = "";
    form.description = "";
    form.startDate = "";
    form.endDate = "";
    form.managerId = "";
    form.managerName = "";
    form.status = "planning";
  form.completionRate = 0;
  if (projectFormRef.value) {
    projectFormRef.value.resetFields();
@@ -447,23 +439,23 @@
};
// 获取状态标签类型
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusTypeMap = {
    planning: 'info',
    inProgress: 'primary',
    completed: 'success',
    paused: 'warning'
      planning: "info",
      inProgress: "primary",
      completed: "success",
      paused: "warning",
  };
  return statusTypeMap[status] || 'default';
    return statusTypeMap[status] || "default";
};
// 获取状态文本
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusTextMap = {
    planning: '规划中',
    inProgress: '进行中',
    completed: '已完成',
    paused: '已暂停'
      planning: "规划中",
      inProgress: "进行中",
      completed: "已完成",
      paused: "已暂停",
  };
  return statusTextMap[status] || status;
};
src/views/oaSystem/projectManagement/projectDetail.vue
@@ -8,7 +8,8 @@
          <span>项目基本信息</span>
        </div>
      </template>
      <el-descriptions :column="2" border>
      <el-descriptions :column="2"
                       border>
        <el-descriptions-item label="项目名称">{{ projectInfo.projectName }}</el-descriptions-item>
        <el-descriptions-item label="项目负责人">{{ projectInfo.managerName }}</el-descriptions-item>
        <el-descriptions-item label="开始日期">{{ projectInfo.startDate }}</el-descriptions-item>
@@ -17,12 +18,13 @@
          <el-tag :type="getStatusType(projectInfo.status)">{{ getStatusText(projectInfo.status) }}</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="完成度">
          <el-progress :percentage="projectInfo.completionRate" :stroke-width="6" />
          <el-progress :percentage="projectInfo.completionRate"
                       :stroke-width="6" />
        </el-descriptions-item>
        <el-descriptions-item label="项目描述" :span="2">{{ projectInfo.description || '-' }}</el-descriptions-item>
        <el-descriptions-item label="项目描述"
                              :span="2">{{ projectInfo.description || '-' }}</el-descriptions-item>
      </el-descriptions>
    </el-card>
    <!-- 项目进度概览 -->
    <el-card class="mb20">
      <template #header>
@@ -57,7 +59,6 @@
        </el-col>
      </el-row>
    </el-card>
    <!-- 阶段和任务管理 -->
    <!-- <el-card class="mb20">
      <template #header>
@@ -68,66 +69,75 @@
      </template>
      <task-tree :project-id="projectId" @refresh="getProjectDetail" />
    </el-card> -->
    <!-- 里程碑管理 -->
    <el-card class="mb20">
      <template #header>
        <div class="card-header">
          <span>项目阶段里程碑</span>
          <el-button type="primary" size="small" @click="handleAddMilestone">添加里程碑</el-button>
          <el-button type="primary"
                     size="small"
                     @click="handleAddMilestone">添加里程碑</el-button>
        </div>
      </template>
      <milestone-list :project-id="projectId" @refresh="getProjectDetail" :key="`milestone-${refreshProjectId}`"/>
      <milestone-list :project-id="projectId"
                      @refresh="getProjectDetail"
                      :key="`milestone-${refreshProjectId}`" />
    </el-card>
    <!-- 阶段目标管理 -->
    <el-card>
      <template #header>
        <div class="card-header">
          <span>阶段任务</span>
          <el-button type="primary" size="small" @click="handleAddPhaseGoal">添加阶段目标</el-button>
          <el-button type="primary"
                     size="small"
                     @click="handleAddPhaseGoal">添加阶段目标</el-button>
        </div>
      </template>
      <phase-goal-list :project-id="projectId" @refresh="getProjectDetail" @editGoal="handleEditPhaseGoal" :key="`phaseGoal-${refreshProjectId}`"/>
      <phase-goal-list :project-id="projectId"
                       @refresh="getProjectDetail"
                       @editGoal="handleEditPhaseGoal"
                       :key="`phaseGoal-${refreshProjectId}`" />
    </el-card>
    <!-- 里程碑管理弹框 -->  
    <el-dialog :title="title" v-model="open" width="600px" append-to-body>
      <el-form :model="form" ref="formRef" label-width="100px">
    <el-form-item label="项目阶段名称" prop="phaseName">
      <el-input
        v-model="form.phaseName"
    <el-dialog :title="title"
               v-model="open"
               width="600px"
               append-to-body>
      <el-form :model="form"
               ref="formRef"
               label-width="100px">
        <el-form-item label="项目阶段名称"
                      prop="phaseName">
          <el-input v-model="form.phaseName"
        placeholder="请输入项目阶段名称"
        maxlength="50"
      />
                    maxlength="50" />
    </el-form-item>
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="开始日期" prop="startDate">
          <el-date-picker
            v-model="form.startDate"
            <el-form-item label="开始日期"
                          prop="startDate">
              <el-date-picker v-model="form.startDate"
            type="date"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            placeholder="选择开始日期"
            style="width: 100%"
          />
                              style="width: 100%" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="结束日期" prop="endDate">
          <el-date-picker
            v-model="form.endDate"
            <el-form-item label="结束日期"
                          prop="endDate">
              <el-date-picker v-model="form.endDate"
            type="date"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            placeholder="选择结束日期"
            style="width: 100%"
          />
                              style="width: 100%" />
        </el-form-item>
      </el-col>
    </el-row>
    <el-form-item label="状态" prop="status">
        <el-form-item label="状态"
                      prop="status">
      <el-radio-group v-model="form.status">
        <el-radio label="notStarted">未开始</el-radio>
        <el-radio label="completed">已完成</el-radio>
@@ -137,93 +147,97 @@
  </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">确定</el-button>
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 阶段任务管理弹框 -->
    <el-dialog :title="goalTitle" v-model="goalOpen" width="600px" append-to-body>
      <el-form :model="goalForm" ref="goalFormRef" label-width="100px">
        <el-form-item label="所属阶段" prop="phaseId">
          <el-select v-model="goalForm.phaseId" placeholder="请选择所属阶段">
            <el-option
              v-for="phase in phaseList"
    <el-dialog :title="goalTitle"
               v-model="goalOpen"
               width="600px"
               append-to-body>
      <el-form :model="goalForm"
               ref="goalFormRef"
               label-width="100px">
        <el-form-item label="所属阶段"
                      prop="phaseId">
          <el-select v-model="goalForm.phaseId"
                     placeholder="请选择所属阶段">
            <el-option v-for="phase in phaseList"
              :key="phase.phaseId"
              :label="phase.phaseName"
              :value="phase.phaseId"
            />
                       :value="phase.phaseId" />
          </el-select>
        </el-form-item>
        <el-form-item label="目标名称" prop="taskName">
          <el-input
            v-model="goalForm.taskName"
        <el-form-item label="目标名称"
                      prop="taskName">
          <el-input v-model="goalForm.taskName"
            placeholder="请输入目标名称"
            maxlength="50"
          />
                    maxlength="50" />
        </el-form-item>
        <el-form-item label="目标值" prop="targetValue">
          <el-input-number
            v-model="goalForm.targetValue"
        <el-form-item label="目标值"
                      prop="targetValue">
          <el-input-number v-model="goalForm.targetValue"
            :min="0"
            :precision="2"
            placeholder="请输入目标值"
            style="width: 100%"
          />
                           style="width: 100%" />
        </el-form-item>
        <el-form-item label="当前值" prop="currentValue">
          <el-input-number
            v-model="goalForm.currentValue"
        <el-form-item label="当前值"
                      prop="currentValue">
          <el-input-number v-model="goalForm.currentValue"
            :min="0"
            :precision="2"
            placeholder="请输入当前值"
            style="width: 100%"
          />
                           style="width: 100%" />
        </el-form-item>
        <el-form-item label="单位" prop="unit">
          <el-input
            v-model="goalForm.unit"
        <el-form-item label="单位"
                      prop="unit">
          <el-input v-model="goalForm.unit"
            placeholder="请输入单位"
            maxlength="10"
          />
                    maxlength="10" />
        </el-form-item>
        <el-form-item label="任务完成日期" prop="targetDate">
          <el-date-picker
            v-model="goalForm.targetDate"
        <el-form-item label="任务完成日期"
                      prop="targetDate">
          <el-date-picker v-model="goalForm.targetDate"
            type="date"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            placeholder="选择目标日期"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="开始日期" prop="startDate">
          <el-date-picker
            v-model="goalForm.startDate"
        <el-form-item label="开始日期"
                      prop="startDate">
          <el-date-picker v-model="goalForm.startDate"
            type="date"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            placeholder="选择目标日期"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="结束日期" prop="endDate">
          <el-date-picker
            v-model="goalForm.endDate"
        <el-form-item label="结束日期"
                      prop="endDate">
          <el-date-picker v-model="goalForm.endDate"
            type="date"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            placeholder="选择目标日期"
            style="width: 100%"
          />
                          style="width: 100%" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select v-model="goalForm.status" placeholder="请选择状态">
            <el-option label="未开始" value="notStarted" />
            <el-option label="进行中" value="inProgress" />
            <el-option label="已完成" value="completed" />
            <el-option label="已延迟" value="delayed" />
        <el-form-item label="状态"
                      prop="status">
          <el-select v-model="goalForm.status"
                     placeholder="请选择状态">
            <el-option label="未开始"
                       value="notStarted" />
            <el-option label="进行中"
                       value="inProgress" />
            <el-option label="已完成"
                       value="completed" />
            <el-option label="已延迟"
                       value="delayed" />
          </el-select>
        </el-form-item>
        <!-- <el-form-item label="完成度" prop="completionRate">
@@ -239,8 +253,9 @@
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitGoalForm">确定</el-button>
          <el-button @click="cancelGoal">取消</el-button>
          <el-button type="primary" @click="submitGoalForm">确定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -248,19 +263,25 @@
</template>
<script setup>
import { ref, reactive, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import TaskTree from './components/taskTree.vue';
import MilestoneList from './components/milestoneList.vue';
import ProjectForm from './components/projectForm.vue';
import PhaseGoalList from './components/phaseGoalList.vue';
import { getProject, addProjectPhase, listProjectPhase, addProjectTask, updateProjectTask } from '@/api/oaSystem/projectManagement';
  import { ref, reactive, onMounted, watch } from "vue";
  import { useRoute, useRouter } from "vue-router";
  import { ElMessage } from "element-plus";
  import TaskTree from "./components/taskTree.vue";
  import MilestoneList from "./components/milestoneList.vue";
  import ProjectForm from "./components/projectForm.vue";
  import PhaseGoalList from "./components/phaseGoalList.vue";
  import {
    getProject,
    addProjectPhase,
    listProjectPhase,
    addProjectTask,
    updateProjectTask,
  } from "@/api/oaSystem/projectManagement";
const route = useRoute();
const router = useRouter();
const open = ref(false);
const title = ref('');
  const title = ref("");
const projectFormRef = ref();
const formRef = ref();
// 项目ID
@@ -271,56 +292,56 @@
// 项目信息
const projectInfo = reactive({
  projectId: '',
  projectName: '',
  description: '',
  startDate: '',
  endDate: '',
  managerId: '',
  managerName: '',
  status: 'planning',
  completionRate: 0
    projectId: "",
    projectName: "",
    description: "",
    startDate: "",
    endDate: "",
    managerId: "",
    managerName: "",
    status: "planning",
    completionRate: 0,
});
// 统计信息
const statistics = reactive({
  totalPhases: 0,
  totalTasks: 0,
  completedTasks: 0
    completedTasks: 0,
});
const form = reactive({
  phaseId: '',
  phaseName: '',
  startDate: '',
  endDate: '',
  status: 'planning',
    phaseId: "",
    phaseName: "",
    startDate: "",
    endDate: "",
    status: "planning",
  oaProjectId: projectId.value,
})
  });
// 阶段目标相关
const goalOpen = ref(false);
const goalTitle = ref('');
  const goalTitle = ref("");
const goalFormRef = ref();
const phaseList = ref([]);
const goalForm = reactive({
  taskId: '',
  phaseId: '',
  taskName: '',
    taskId: "",
    phaseId: "",
    taskName: "",
  targetValue: 100,
  currentValue: 0,
  unit: '%',
  targetDate: '',
  startDate: '',
  endDate: '',
  status: 'notStarted',
  completionRate: 0
    unit: "%",
    targetDate: "",
    startDate: "",
    endDate: "",
    status: "notStarted",
    completionRate: 0,
});
// 获取项目详情
const getProjectDetail = async () => {
  try {
    getProject().then((res)=>{
      console.log("项目详情",res)
      getProject().then(res => {
        console.log("项目详情", res);
      const projectData = res.data[projectId.value];
      // 更新项目信息
      Object.assign(projectInfo, projectData);
@@ -331,21 +352,22 @@
      // 强制更新DOM以确保子组件能正确刷新
      // 这里通过触发refreshProjectId事件来强制刷新子组件
      refreshProjectId.value++;
    })
      });
  } catch (error) {
    ElMessage.error('获取项目详情失败');
    console.error('获取项目详情失败:', error);
      ElMessage.error("获取项目详情失败");
      console.error("获取项目详情失败:", error);
  }
};
// 更新统计信息
const updateStatistics = (projectData) => {
  const updateStatistics = projectData => {
  // 这里假设projectData中包含了统计信息
  // 如果没有,需要单独请求统计数据
  statistics.totalPhases = projectData.phases ? projectData.phases.length : 0;
  statistics.totalTasks = projectData.tasks ? projectData.tasks.length : 0;
  statistics.completedTasks = projectData.tasks ?
    projectData.tasks.filter(task => task.status === 'completed').length : 0;
    statistics.completedTasks = projectData.tasks
      ? projectData.tasks.filter(task => task.status === "completed").length
      : 0;
};
// 获取项目阶段列表
@@ -354,15 +376,18 @@
    const { data } = await listProjectPhase(projectId.value);
    phaseList.value = data.rows || data;
  } catch (error) {
    ElMessage.error('获取项目阶段列表失败');
    console.error('获取项目阶段列表失败:', error);
      ElMessage.error("获取项目阶段列表失败");
      console.error("获取项目阶段列表失败:", error);
  }
};
// 计算完成度
const calculateCompletionRate = () => {
  if (goalForm.targetValue > 0) {
    goalForm.completionRate = Math.min(Math.round((goalForm.currentValue / goalForm.targetValue) * 100), 100);
      goalForm.completionRate = Math.min(
        Math.round((goalForm.currentValue / goalForm.targetValue) * 100),
        100
      );
  } else {
    goalForm.completionRate = 0;
  }
@@ -371,34 +396,34 @@
// 添加阶段
const handleAddPhase = () => {
  // resetForm();
  ElMessage.info('添加阶段功能待实现');
    ElMessage.info("添加阶段功能待实现");
};
// 添加里程碑
const handleAddMilestone = () => {
  resetForm();
  open.value = true;
  title.value = '新增项目阶段';
    title.value = "新增项目阶段";
};
// 添加阶段任务
const handleAddPhaseGoal = () => {
  goalForm.taskId = '';
  goalForm.phaseId = '';
  goalForm.taskName = '';
    goalForm.taskId = "";
    goalForm.phaseId = "";
    goalForm.taskName = "";
  goalForm.targetValue = 0;
  goalForm.currentValue = 0;
  goalForm.unit = '%';
  goalForm.targetDate = '';
  goalForm.startDate = '';
  goalForm.endDate = '';
  goalForm.status = 'notStarted';
    goalForm.unit = "%";
    goalForm.targetDate = "";
    goalForm.startDate = "";
    goalForm.endDate = "";
    goalForm.status = "notStarted";
  goalForm.completionRate = 0;
  if (goalFormRef.value) {
    goalFormRef.value.resetFields();
  }
  getPhaseList();
  goalTitle.value = '新增阶段目标';
    goalTitle.value = "新增阶段目标";
  goalOpen.value = true;
};
@@ -413,12 +438,12 @@
    } else {
      console.log("form",form);
      await addProjectPhase(form);
      ElMessage.success('新增项目阶段成功');
        ElMessage.success("新增项目阶段成功");
      getProjectDetail();
    }
    open.value = false;
  } catch (error) {
    console.error('提交表单失败:', error);
      console.error("提交表单失败:", error);
  }
};
@@ -430,34 +455,31 @@
    
    const goalData = {
      ...goalForm,
      oaProjectId: projectId.value
        oaProjectId: projectId.value,
    };
    
    if (goalForm.taskId) {
      await updateProjectTask(goalData);
      ElMessage.success('修改阶段目标成功');
        ElMessage.success("修改阶段目标成功");
    } else {
      await addProjectTask(goalData);
      ElMessage.success('新增阶段目标成功');
        ElMessage.success("新增阶段目标成功");
    }
    // 调用getProjectDetail刷新所有相关数据
    getProjectDetail();
    goalOpen.value = false;
  } catch (error) {
    console.error('提交阶段目标表单失败:', error);
      console.error("提交阶段目标表单失败:", error);
  }
};
// 重置里程碑表单
const resetForm = () => {
  form.phaseId = '';
  form.phaseName = '';
  form.startDate = '';
  form.endDate = '';
  form.status = 'planning';
    form.phaseId = "";
    form.phaseName = "";
    form.startDate = "";
    form.endDate = "";
    form.status = "planning";
  form.oaProjectId = projectId.value;
  if (formRef.value) {
    formRef.value.resetFields();
@@ -474,7 +496,7 @@
  open.value = false;
};
// 编辑阶段任务
const handleEditPhaseGoal = async (goal) => {
  const handleEditPhaseGoal = async goal => {
  // 复制目标数据到表单
  Object.assign(goalForm, goal);
  
@@ -482,44 +504,50 @@
  await getPhaseList();
  
  // 打开编辑弹窗
  goalTitle.value = '编辑阶段目标';
    goalTitle.value = "编辑阶段目标";
  goalOpen.value = true;
};
// 获取状态标签类型
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusTypeMap = {
    planning: 'info',
    inProgress: 'primary',
    completed: 'success',
    paused: 'warning'
      planning: "info",
      inProgress: "primary",
      completed: "success",
      paused: "warning",
  };
  return statusTypeMap[status] || 'default';
    return statusTypeMap[status] || "default";
};
// 获取状态文本
const getStatusText = (status) => {
  const getStatusText = status => {
  const statusTextMap = {
    planning: '规划中',
    inProgress: '进行中',
    completed: '已完成',
    paused: '已暂停'
      planning: "规划中",
      inProgress: "进行中",
      completed: "已完成",
      paused: "已暂停",
  };
  return statusTextMap[status] || status;
};
// 监听路由参数变化
watch(() => route.params.projectId, (newProjectId) => {
  watch(
    () => route.params.projectId,
    newProjectId => {
  // console.log('路由参数变化:', projectId);
  if (newProjectId) {
    projectId.value = newProjectId;
    getProjectDetail();
  }
});
    }
  );
// 监听当前值和目标值变化,重新计算完成度
watch(() => [goalForm.currentValue, goalForm.targetValue], () => {
  watch(
    () => [goalForm.currentValue, goalForm.targetValue],
    () => {
  calculateCompletionRate();
});
    }
  );
// 初始化
onMounted(() => {
src/views/procurementManagement/procurementPlan/index.vue
@@ -1,137 +1,179 @@
<template>
  <div class="app-container">
    <!-- 搜索区域 -->
    <el-card class="search-card" shadow="never">
      <el-form :model="searchForm" :inline="true" class="search-form">
    <el-card class="search-card"
             shadow="never">
      <el-form :model="searchForm"
               :inline="true"
               class="search-form">
        <el-form-item label="计划名称">
          <el-input v-model="searchForm.planName" placeholder="请输入计划名称" clearable />
          <el-input v-model="searchForm.planName"
                    placeholder="请输入计划名称"
                    clearable />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchForm.status" placeholder="请选择状态" clearable style="width: 150px">
            <el-option label="启用" value="active" />
            <el-option label="禁用" value="disabled" />
          <el-select v-model="searchForm.status"
                     placeholder="请选择状态"
                     clearable
                     style="width: 150px">
            <el-option label="启用"
                       value="active" />
            <el-option label="禁用"
                       value="disabled" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">
            <el-icon><Search /></el-icon>
          <el-button type="primary"
                     @click="handleSearch">
            <el-icon>
              <Search />
            </el-icon>
            搜索
          </el-button>
          <el-button @click="handleReset">
            <el-icon><Refresh /></el-icon>
            <el-icon>
              <Refresh />
            </el-icon>
            重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- 操作按钮 -->
    <el-card class="table-card" shadow="never">
    <el-card class="table-card"
             shadow="never">
      <div class="table-header">
        <div class="table-title">采购计划列表</div>
        <div class="table-actions">
          <el-button type="primary" @click="handleAdd">
            <el-icon><Plus /></el-icon>
          <el-button type="primary"
                     @click="handleAdd">
            <el-icon>
              <Plus />
            </el-icon>
            新增计划
          </el-button>
          <el-button type="info" @click="handleExport">
            <el-icon><Download /></el-icon>
          <el-button type="info"
                     @click="handleExport">
            <el-icon>
              <Download />
            </el-icon>
            导出
          </el-button>
        </div>
      </div>
      <!-- 数据表格 -->
      <el-table
        v-loading="loading"
      <el-table v-loading="loading"
        :data="tableData"
        stripe
        border
        style="width: 100%"
      >
        <el-table-column prop="planName" label="计划名称" min-width="150" />
        <el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
        <el-table-column prop="formula" label="计算公式" min-width="200" show-overflow-tooltip>
                style="width: 100%">
        <el-table-column prop="planName"
                         label="计划名称"
                         min-width="150" />
        <el-table-column prop="description"
                         label="描述"
                         min-width="200"
                         show-overflow-tooltip />
        <el-table-column prop="formula"
                         label="计算公式"
                         min-width="200"
                         show-overflow-tooltip>
          <template #default="{ row }">
            <el-tag type="info" size="small">{{ row.formula }}</el-tag>
            <el-tag type="info"
                    size="small">{{ row.formula }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="80" align="center">
        <el-table-column prop="status"
                         label="状态"
                         width="80"
                         align="center">
          <template #default="{ row }">
            <el-tag :type="row.status === 'active' ? 'success' : 'info'" size="small">
            <el-tag :type="row.status === 'active' ? 'success' : 'info'"
                    size="small">
              {{ row.status === 'active' ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="updateTime" label="最后计算时间" width="160" />
        <el-table-column label="操作" width="200" fixed="right" align="center">
        <el-table-column prop="updateTime"
                         label="最后计算时间"
                         width="160" />
        <el-table-column label="操作"
                         width="200"
                         fixed="right"
                         align="center">
          <template #default="{ row }">
            <el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
            <el-button type="success" link @click="handleCalculate(row)">计算</el-button>
            <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
            <el-button type="primary"
                       link
                       @click="handleEdit(row)">编辑</el-button>
            <el-button type="success"
                       link
                       @click="handleCalculate(row)">计算</el-button>
            <el-button type="danger"
                       link
                       @click="handleDelete(row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <div class="pagination-container">
        <el-pagination
          v-model:current-page="pagination.current"
        <el-pagination v-model:current-page="pagination.current"
          v-model:page-size="pagination.size"
          :page-sizes="[10, 20, 50, 100]"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
                       @current-change="handleCurrentChange" />
      </div>
    </el-card>
    <!-- 新增/编辑对话框 -->
    <el-dialog
      v-model="dialogVisible"
    <el-dialog v-model="dialogVisible"
      :title="dialogType === 'add' ? '新增采购计划' : '编辑采购计划'"
      width="1000px"
      :close-on-click-modal="false"
    >
               :close-on-click-modal="false">
      <div class="form-container">
        <!-- 基本信息 -->
        <div class="form-section">
          <div class="section-title">基本信息</div>
          <el-form
            ref="formRef"
          <el-form ref="formRef"
            :model="formData"
            :rules="formRules"
            label-width="120px"
          >
                   label-width="120px">
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="编码" prop="code">
                  <el-input v-model="formData.code" placeholder="系统自动生成" disabled />
                <el-form-item label="编码"
                              prop="code">
                  <el-input v-model="formData.code"
                            placeholder="系统自动生成"
                            disabled />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="名称" prop="planName" required>
                  <el-input v-model="formData.planName" placeholder="请输入计划名称" />
                <el-form-item label="名称"
                              prop="planName"
                              required>
                  <el-input v-model="formData.planName"
                            placeholder="请输入计划名称" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-form-item label="描述" prop="description">
              <el-input
                v-model="formData.description"
            <el-form-item label="描述"
                          prop="description">
              <el-input v-model="formData.description"
                type="textarea"
                :rows="3"
                placeholder="请输入计划描述"
              />
                        placeholder="请输入计划描述" />
            </el-form-item>
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="状态" prop="status">
                  <el-select v-model="formData.status" placeholder="请选择状态" style="width: 100%">
                    <el-option label="启用" value="active" />
                    <el-option label="禁用" value="disabled" />
                <el-form-item label="状态"
                              prop="status">
                  <el-select v-model="formData.status"
                             placeholder="请选择状态"
                             style="width: 100%">
                    <el-option label="启用"
                               value="active" />
                    <el-option label="禁用"
                               value="disabled" />
                  </el-select>
                </el-form-item>
              </el-col>
@@ -143,12 +185,13 @@
            </el-row>
          </el-form>
        </div>
        <!-- 计算参数 -->
        <div class="form-section">
          <div class="section-title">计算参数</div>
          <el-tabs v-model="activeTab" class="param-tabs">
            <el-tab-pane label="需求参数" name="demand">
          <el-tabs v-model="activeTab"
                   class="param-tabs">
            <el-tab-pane label="需求参数"
                         name="demand">
              <div class="checkbox-group">
                <el-checkbox v-model="formData.considerExistingStock">考虑现有库存</el-checkbox>
                <el-checkbox v-model="formData.warehouseControl">仓库运行MRP的控制</el-checkbox>
@@ -159,7 +202,8 @@
                <el-checkbox v-model="formData.negativeStockAsDemand">负库存作为需求</el-checkbox>
              </div>
            </el-tab-pane>
            <el-tab-pane label="计算参数" name="calculation">
            <el-tab-pane label="计算参数"
                         name="calculation">
              <div class="checkbox-group">
                <el-checkbox v-model="formData.considerExistingStock">考虑现有库存</el-checkbox>
                <el-checkbox v-model="formData.warehouseControl">仓库运行MRP的控制</el-checkbox>
@@ -172,7 +216,6 @@
            </el-tab-pane>
          </el-tabs>
        </div>
        <!-- 汇总合并选项 -->
        <div class="form-section">
          <div class="section-title">汇总合并选项</div>
@@ -182,129 +225,161 @@
            <el-checkbox v-model="formData.summaryDemandDate">需求日期</el-checkbox>
          </div>
        </div>
        <!-- 计算公式 -->
        <div class="form-section">
          <div class="section-title">计算公式</div>
          <div class="formula-input-section">
            <el-form-item label="计算公式" prop="formula" required>
              <el-input
                v-model="formData.formula"
            <el-form-item label="计算公式"
                          prop="formula"
                          required>
              <el-input v-model="formData.formula"
                placeholder="例如: 预计出库数量 - 现有库存 + 安全库存 - 预计入库数量"
                @input="validateFormula"
              />
                        @input="validateFormula" />
            </el-form-item>
            <div class="formula-help">
              <el-text type="info" size="small">
              <el-text type="info"
                       size="small">
                支持变量:预计出库数量、现有库存、安全库存、预计入库数量
              </el-text>
            </div>
          </div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleSubmit"
                     :loading="submitLoading">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 产品选择对话框 -->
    <el-dialog
      v-model="productSelectDialogVisible"
    <el-dialog v-model="productSelectDialogVisible"
      title="选择产品"
      width="800px"
      :close-on-click-modal="false"
    >
               :close-on-click-modal="false">
      <div class="product-select">
        <el-alert
          title="请选择要计算的产品"
        <el-alert title="请选择要计算的产品"
          type="info"
          :closable="false"
          show-icon
        >
                  show-icon>
          <template #default>
            <p>选择产品后,系统将根据当前计算公式和产品库存情况进行计算。</p>
          </template>
        </el-alert>
        <el-table
          v-loading="productLoading"
        <el-table v-loading="productLoading"
          :data="productList"
          @selection-change="handleProductSelectionChange"
          stripe
          border
          style="width: 100%; margin-top: 20px;"
        >
          <el-table-column type="selection" width="55" />
          <el-table-column prop="productCategory" label="产品大类" min-width="150" />
          <el-table-column prop="specificationModel" label="产品规格" width="120" />
          <el-table-column prop="inboundNum0" label="现有库存" width="100" align="right" />
          <el-table-column prop="inboundNum" label="安全库存" width="100" align="right" />
          <el-table-column prop="inboundNum" label="预计出库" width="100" align="right" />
          <el-table-column prop="inboundNum0" label="预计入库" width="100" align="right" />
                  style="width: 100%; margin-top: 20px;">
          <el-table-column type="selection"
                           width="55" />
          <el-table-column prop="productCategory"
                           label="产品大类"
                           min-width="150" />
          <el-table-column prop="specificationModel"
                           label="产品规格"
                           width="120" />
          <el-table-column prop="inboundNum0"
                           label="现有库存"
                           width="100"
                           align="right" />
          <el-table-column prop="inboundNum"
                           label="安全库存"
                           width="100"
                           align="right" />
          <el-table-column prop="inboundNum"
                           label="预计出库"
                           width="100"
                           align="right" />
          <el-table-column prop="inboundNum0"
                           label="预计入库"
                           width="100"
                           align="right" />
        </el-table>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="productSelectDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleConfirmProductSelection" :disabled="selectedProducts.length === 0">
          <el-button type="primary"
                     @click="handleConfirmProductSelection"
                     :disabled="selectedProducts.length === 0">
            确认计算
          </el-button>
          <el-button @click="productSelectDialogVisible = false">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 计算结果对话框 -->
    <el-dialog
      v-model="calculateDialogVisible"
    <el-dialog v-model="calculateDialogVisible"
      title="采购计算结果"
      width="1000px"
      :close-on-click-modal="false"
    >
               :close-on-click-modal="false">
      <div class="calculate-result">
        <el-alert
          title="计算结果"
        <el-alert title="计算结果"
          type="success"
          :closable="false"
          show-icon
        >
                  show-icon>
          <template #default>
            <p>基于当前配置的计算公式和库存情况,系统已计算出各产品的采购需求。</p>
          </template>
        </el-alert>
        <el-table :data="calculateResult" stripe border style="width: 100%; margin-top: 20px;">
          <el-table-column prop="productCategory" label="产品大类" min-width="150" />
          <el-table-column prop="specificationModel" label="产品规格" width="120" />
          <el-table-column prop="inboundNum0" label="现有库存" width="100" align="right" />
          <el-table-column prop="inboundNum" label="安全库存" width="100" align="right" />
          <el-table-column prop="inboundNum" label="预计出库数量" width="120" align="right" />
          <el-table-column prop="inboundNum0" label="预计入库数量" width="120" align="right" />
          <el-table-column prop="weeklyNetDemand" label="按周净需求" width="120" align="right">
        <el-table :data="calculateResult"
                  stripe
                  border
                  style="width: 100%; margin-top: 20px;">
          <el-table-column prop="productCategory"
                           label="产品大类"
                           min-width="150" />
          <el-table-column prop="specificationModel"
                           label="产品规格"
                           width="120" />
          <el-table-column prop="inboundNum0"
                           label="现有库存"
                           width="100"
                           align="right" />
          <el-table-column prop="inboundNum"
                           label="安全库存"
                           width="100"
                           align="right" />
          <el-table-column prop="inboundNum"
                           label="预计出库数量"
                           width="120"
                           align="right" />
          <el-table-column prop="inboundNum0"
                           label="预计入库数量"
                           width="120"
                           align="right" />
          <el-table-column prop="weeklyNetDemand"
                           label="按周净需求"
                           width="120"
                           align="right">
            <template #default="{ row }">
              <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'" size="small">
              <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'"
                      size="small">
                {{ row.weeklyNetDemand }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="suggestedPurchase" label="建议采购" width="100" align="right">
          <el-table-column prop="suggestedPurchase"
                           label="建议采购"
                           width="100"
                           align="right">
            <template #default="{ row }">
              <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'" size="small">
              <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'"
                      size="small">
                {{ row.suggestedPurchase }}
              </el-tag>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleCreatePurchaseOrder">确认</el-button>
          <el-button @click="calculateDialogVisible = false">关闭</el-button>
          <el-button type="primary" @click="handleCreatePurchaseOrder">确认</el-button>
        </div>
      </template>
    </el-dialog>
@@ -312,42 +387,48 @@
</template>
<script setup>
import {ref, reactive, onMounted, getCurrentInstance} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Refresh, Plus, Download } from '@element-plus/icons-vue'
import {listPage,add,update,del,listPageCopy} from "@/api/procurementManagement/procurementPlan.js"
  import { ref, reactive, onMounted, getCurrentInstance } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Search, Refresh, Plus, Download } from "@element-plus/icons-vue";
  import {
    listPage,
    add,
    update,
    del,
    listPageCopy,
  } from "@/api/procurementManagement/procurementPlan.js";
// 响应式数据
const loading = ref(false)
const submitLoading = ref(false)
const dialogVisible = ref(false)
const productSelectDialogVisible = ref(false)
const calculateDialogVisible = ref(false)
const dialogType = ref('add')
const productLoading = ref(false)
const selectedProducts = ref([])
const currentPlan = ref(null)
  const loading = ref(false);
  const submitLoading = ref(false);
  const dialogVisible = ref(false);
  const productSelectDialogVisible = ref(false);
  const calculateDialogVisible = ref(false);
  const dialogType = ref("add");
  const productLoading = ref(false);
  const selectedProducts = ref([]);
  const currentPlan = ref(null);
// 搜索表单
const searchForm = reactive({
  planName: '',
  status: ''
})
    planName: "",
    status: "",
  });
// 分页数据
const pagination = reactive({
  current: 1,
  size: 20
})
    size: 20,
  });
// 表单数据
const formData = reactive({
  code: '',
  planName: '',
  description: '',
  status: '',
    code: "",
    planName: "",
    description: "",
    status: "",
  isSystemPreset: false,
  formula: '',
    formula: "",
  // 计算参数
  considerExistingStock: false,
  warehouseControl: false,
@@ -359,166 +440,158 @@
  // 汇总合并选项
  summaryMaterial: false,
  summaryAuxAttributes: false,
  summaryDemandDate: false
})
    summaryDemandDate: false,
  });
// 当前激活的标签页
const activeTab = ref('demand')
  const activeTab = ref("demand");
// 表单验证规则
const formRules = {
  planName: [
    { required: true, message: '请输入计划名称', trigger: 'blur' }
  ],
  status: [
    { required: true, message: '请选择状态', trigger: 'change' }
  ],
  formula: [
    { required: true, message: '请输入计算公式', trigger: 'blur' }
  ]
}
    planName: [{ required: true, message: "请输入计划名称", trigger: "blur" }],
    status: [{ required: true, message: "请选择状态", trigger: "change" }],
    formula: [{ required: true, message: "请输入计算公式", trigger: "blur" }],
  };
// 表格数据
const tableData = ref([])
  const tableData = ref([]);
// 产品列表数据
const productList = ref([
  {
    id: 4,
    productName: '产品D',
    productCode: 'PD004',
      productName: "产品D",
      productCode: "PD004",
    existingStock: 90,
    safetyStock: 40,
    expectedOutbound: 160,
    expectedInbound: 35
  }
])
      expectedInbound: 35,
    },
  ]);
// 计算结果数据
const calculateResult = ref([
  {
    productName: '产品A',
      productName: "产品A",
    existingStock: 100,
    safetyStock: 50,
    expectedOutbound: 200,
    expectedInbound: 30,
    weeklyNetDemand: 120,
    suggestedPurchase: 150
      suggestedPurchase: 150,
  },
  {
    productName: '产品B',
      productName: "产品B",
    existingStock: 80,
    safetyStock: 30,
    expectedOutbound: 150,
    expectedInbound: 20,
    weeklyNetDemand: 100,
    suggestedPurchase: 120
  }
])
const total = ref(0)
      suggestedPurchase: 120,
    },
  ]);
  const total = ref(0);
// 方法
const handleSearch = () => {
  pagination.current = 1
  loadData()
}
    pagination.current = 1;
    loadData();
  };
const handleReset = () => {
  Object.assign(searchForm, {
    planName: '',
    status: ''
  })
  handleSearch()
}
      planName: "",
      status: "",
    });
    handleSearch();
  };
const loadData = () => {
  loading.value = true
    loading.value = true;
  listPage({...searchForm,...pagination}).then(res => {
    if(res.code === 200){
      tableData.value = res.data.records
      total.value = res.data.total
      loading.value = false
        tableData.value = res.data.records;
        total.value = res.data.total;
        loading.value = false;
    }
  })
}
    });
  };
const handleAdd = () => {
  dialogType.value = 'add'
  resetForm()
    dialogType.value = "add";
    resetForm();
  // 自动生成编码
  formData.code = 'CGJH' + String(Date.now()).slice(-4)
  dialogVisible.value = true
}
    formData.code = "CGJH" + String(Date.now()).slice(-4);
    dialogVisible.value = true;
  };
const handleEdit = (row) => {
  dialogType.value = 'edit'
  Object.assign(formData, row)
  dialogVisible.value = true
}
  const handleEdit = row => {
    dialogType.value = "edit";
    Object.assign(formData, row);
    dialogVisible.value = true;
  };
const handleDelete = async (row) => {
  const handleDelete = async row => {
  try {
    await ElMessageBox.confirm('确定要删除这个采购计划吗?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    let ids = [row.id]
      await ElMessageBox.confirm("确定要删除这个采购计划吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      });
      let ids = [row.id];
    del(ids).then(res =>{
     if(res.code === 200){
      ElMessage.success('删除成功')
      loadData()
          ElMessage.success("删除成功");
          loadData();
    }
   })
      });
  } catch {
    // 用户取消删除
  }
}
  };
const handleSubmit = async () => {
  try {
    // 表单验证
    if (!formData.planName || !formData.formula) {
      ElMessage.error('请填写必填项')
      return
        ElMessage.error("请填写必填项");
        return;
    }
    submitLoading.value = true
      submitLoading.value = true;
    if (dialogType.value === 'add') {
      if (dialogType.value === "add") {
      add(formData).then(res => {
        if(res.code === 200){
          ElMessage.success('新增成功')
          dialogVisible.value = false
          loadData()
            ElMessage.success("新增成功");
            dialogVisible.value = false;
            loadData();
        }
      })
        });
    } else {
      // 编辑
      update(formData).then(res => {
        if(res.code === 200){
          ElMessage.success('编辑成功')
          dialogVisible.value = false
          loadData()
            ElMessage.success("编辑成功");
            dialogVisible.value = false;
            loadData();
        }
      })
        });
    }
  } catch (error) {
    ElMessage.error('操作失败')
      ElMessage.error("操作失败");
  } finally {
    submitLoading.value = false
      submitLoading.value = false;
  }
}
  };
const resetForm = () => {
  Object.assign(formData, {
    code: '',
    planName: '',
    description: '',
    status: '',
      code: "",
      planName: "",
      description: "",
      status: "",
    isSystemPreset: false,
    formula: '预计出库数量 - 现有库存 + 安全库存 - 预计入库数量',
      formula: "预计出库数量 - 现有库存 + 安全库存 - 预计入库数量",
    // 计算参数
    considerExistingStock: false,
    warehouseControl: false,
@@ -530,52 +603,52 @@
    // 汇总合并选项
    summaryMaterial: false,
    summaryAuxAttributes: false,
    summaryDemandDate: false
  })
  activeTab.value = 'demand'
}
      summaryDemandDate: false,
    });
    activeTab.value = "demand";
  };
const validateFormula = () => {
  // 简单的公式验证
  const formula = formData.formula
    const formula = formData.formula;
  if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) {
    ElMessage.warning('公式格式可能不正确,请检查')
      ElMessage.warning("公式格式可能不正确,请检查");
  }
}
  };
const handleCalculate = (row) => {
  currentPlan.value = row
  productSelectDialogVisible.value = true
  loadProductList()
}
  const handleCalculate = row => {
    currentPlan.value = row;
    productSelectDialogVisible.value = true;
    loadProductList();
  };
const loadProductList = () => {
  productLoading.value = true
    productLoading.value = true;
  // 模拟加载产品数据
  listPageCopy({size:-1}).then(res => {
    if(res.code === 200){
      productList.value = res.data.records
      productLoading.value = false
        productList.value = res.data.records;
        productLoading.value = false;
    }
  })
}
    });
  };
const handleProductSelectionChange = (selection) => {
  selectedProducts.value = selection
}
  const handleProductSelectionChange = selection => {
    selectedProducts.value = selection;
  };
const handleConfirmProductSelection = () => {
  if (selectedProducts.value.length === 0) {
    ElMessage.warning('请选择要计算的产品')
    return
      ElMessage.warning("请选择要计算的产品");
      return;
  }
  
  ElMessage.success(`正在计算 ${currentPlan.value.planName} 的采购需求...`)
  productSelectDialogVisible.value = false
    ElMessage.success(`正在计算 ${currentPlan.value.planName} 的采购需求...`);
    productSelectDialogVisible.value = false;
  
  // 根据选择的产品和计算公式进行计算
  calculateWithSelectedProducts()
}
    calculateWithSelectedProducts();
  };
const calculateWithSelectedProducts = () => {
  // 模拟计算过程
@@ -583,8 +656,12 @@
  const result = selectedProducts.value.map(product => {
    // 这里应该根据实际的计算公式进行计算
    // 示例:预计出库数量 - 现有库存 + 安全库存 - 预计入库数量
    const weeklyNetDemand = product.inboundNum - product.inboundNum0 + product.inboundNum - product.inboundNum0
    const suggestedPurchase = Math.max(0, weeklyNetDemand)
      const weeklyNetDemand =
        product.inboundNum -
        product.inboundNum0 +
        product.inboundNum -
        product.inboundNum0;
      const suggestedPurchase = Math.max(0, weeklyNetDemand);
    return {
      productCategory: product.productCategory,
@@ -592,18 +669,17 @@
      inboundNum0: product.inboundNum0,
      inboundNum: product.inboundNum,
      weeklyNetDemand: weeklyNetDemand,
      suggestedPurchase: suggestedPurchase
    }
  })
        suggestedPurchase: suggestedPurchase,
      };
    });
  calculateResult.value = result
  calculateDialogVisible.value = true
}
    calculateResult.value = result;
    calculateDialogVisible.value = true;
  };
const handleCreatePurchaseOrder = () => {
  calculateDialogVisible.value = false
}
    calculateDialogVisible.value = false;
  };
const { proxy } = getCurrentInstance();
const handleExport = () => {
  ElMessageBox.confirm("内容将被导出,是否确认导出?", "导出", {
@@ -617,23 +693,22 @@
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
}
  };
  const handleSizeChange = size => {
    pagination.size = size;
    loadData();
  };
const handleSizeChange = (size) => {
  pagination.size = size
  loadData()
}
const handleCurrentChange = (current) => {
  pagination.current = current
  loadData()
}
  const handleCurrentChange = current => {
    pagination.current = current;
    loadData();
  };
// 生命周期
onMounted(() => {
  loadData()
})
    loadData();
  });
</script>
<style scoped>
src/views/productManagement/productIdentifier/index.vue
@@ -2,158 +2,230 @@
  <div class="app-container">
    <el-card class="box-card">
             <!-- 搜索区域 -->
       <el-row :gutter="20" class="search-row">
      <el-row :gutter="20"
              class="search-row">
         <el-col :span="6">
           <el-input
             v-model="searchForm.productName"
          <el-input v-model="searchForm.productName"
             placeholder="请输入产品名称"
             clearable
             @keyup.enter="handleSearch"
           >
                    @keyup.enter="handleSearch">
             <template #prefix>
               <el-icon><Search /></el-icon>
              <el-icon>
                <Search />
              </el-icon>
             </template>
           </el-input>
         </el-col>
         <el-col :span="6">
           <el-select v-model="searchForm.identifierType" placeholder="请选择标识类型" clearable>
             <el-option label="二维码" value="二维码"></el-option>
             <el-option label="防伪码" value="防伪码"></el-option>
          <el-select v-model="searchForm.identifierType"
                     placeholder="请选择标识类型"
                     clearable>
            <el-option label="二维码"
                       value="二维码"></el-option>
            <el-option label="防伪码"
                       value="防伪码"></el-option>
           </el-select>
         </el-col>
         <el-col :span="6">
           <el-select v-model="searchForm.status" placeholder="请选择状态" clearable>
             <el-option label="已生成" value="已生成"></el-option>
             <el-option label="已分配" value="已分配"></el-option>
             <el-option label="已使用" value="已使用"></el-option>
             <el-option label="已作废" value="已作废"></el-option>
          <el-select v-model="searchForm.status"
                     placeholder="请选择状态"
                     clearable>
            <el-option label="已生成"
                       value="已生成"></el-option>
            <el-option label="已分配"
                       value="已分配"></el-option>
            <el-option label="已使用"
                       value="已使用"></el-option>
            <el-option label="已作废"
                       value="已作废"></el-option>
           </el-select>
         </el-col>
         <el-col :span="6">
           <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
           <el-button @click="resetSearch">重置</el-button>
           <el-button style="float: right;" type="primary" @click="handleAdd">
          <el-button style="float: right;"
                     type="primary"
                     @click="handleAdd">
             新增标识
           </el-button>
         </el-col>
       </el-row>
      <!-- 产品标识列表 -->
      <el-table
        :data="filteredList"
      <el-table :data="filteredList"
        style="width: 100%"
        v-loading="loading"
        border
        stripe
        height="calc(100vh - 22em)"
      >
        <el-table-column prop="id" label="ID" width="80" align="center"/>
        <el-table-column prop="productName" label="产品名称" width="150" />
        <el-table-column prop="productCode" label="产品编码" width="120" />
        <el-table-column prop="batchNo" label="批次号" width="120" />
        <el-table-column prop="identifierType" label="标识类型" width="100">
                height="calc(100vh - 22em)">
        <el-table-column prop="id"
                         label="ID"
                         width="80"
                         align="center" />
        <el-table-column prop="productName"
                         label="产品名称"
                         width="150" />
        <el-table-column prop="productCode"
                         label="产品编码"
                         width="120" />
        <el-table-column prop="batchNo"
                         label="批次号"
                         width="120" />
        <el-table-column prop="identifierType"
                         label="标识类型"
                         width="100">
          <template #default="scope">
            <el-tag :type="getIdentifierTypeType(scope.row.identifierType)">
              {{ scope.row.identifierType }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="identifierCode" label="标识码" />
        <el-table-column prop="status" label="状态" width="100">
        <el-table-column prop="identifierCode"
                         label="标识码" />
        <el-table-column prop="status"
                         label="状态"
                         width="100">
          <template #default="scope">
            <el-tag :type="getStatusType(scope.row.status)">
              {{ scope.row.status }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="generateTime" label="生成时间" width="160" />
        <el-table-column label="操作" fixed="right" align="center" width="280">
        <el-table-column prop="generateTime"
                         label="生成时间"
                         width="160" />
        <el-table-column label="操作"
                         fixed="right"
                         align="center"
                         width="280">
          <template #default="scope">
            <el-button link type="primary" @click="handleView(scope.row)">查看</el-button>
            <el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="success" @click="generateQRCode(scope.row)">生成二维码</el-button>
            <el-button link type="primary" @click="handleExport(scope.row)">导出</el-button>
            <el-button link type="primary" @click="handleReassign(scope.row)" v-if="scope.row.status === '已分配'">重新分配</el-button>
            <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
            <el-button link
                       type="primary"
                       @click="handleView(scope.row)">查看</el-button>
            <el-button link
                       type="primary"
                       @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link
                       type="success"
                       @click="generateQRCode(scope.row)">生成二维码</el-button>
            <el-button link
                       type="primary"
                       @click="handleExport(scope.row)">导出</el-button>
            <el-button link
                       type="primary"
                       @click="handleReassign(scope.row)"
                       v-if="scope.row.status === '已分配'">重新分配</el-button>
            <el-button link
                       type="danger"
                       @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
        :total="pagination.total"
      <pagination :total="pagination.total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="pagination.currentPage"
        :limit="pagination.pageSize"
        @pagination="handleCurrentChange"
      />
                  @pagination="handleCurrentChange" />
    </el-card>
    <!-- 新增/编辑对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
    <el-dialog v-model="dialogVisible"
               :title="dialogTitle"
               width="700px">
      <el-form :model="form"
               :rules="rules"
               ref="formRef"
               label-width="100px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="产品名称" prop="productName">
              <el-input v-model="form.productName" placeholder="请输入产品名称"></el-input>
            <el-form-item label="产品名称"
                          prop="productName">
              <el-input v-model="form.productName"
                        placeholder="请输入产品名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="产品编码" prop="productCode">
              <el-input v-model="form.productCode" placeholder="请输入产品编码"></el-input>
            <el-form-item label="产品编码"
                          prop="productCode">
              <el-input v-model="form.productCode"
                        placeholder="请输入产品编码"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="批次号" prop="batchNo">
              <el-input v-model="form.batchNo" placeholder="请输入批次号"></el-input>
            <el-form-item label="批次号"
                          prop="batchNo">
              <el-input v-model="form.batchNo"
                        placeholder="请输入批次号"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="标识类型" prop="identifierType">
              <el-select v-model="form.identifierType" placeholder="请选择标识类型" style="width: 100%">
                <el-option label="二维码" value="二维码"></el-option>
                <el-option label="防伪码" value="防伪码"></el-option>
            <el-form-item label="标识类型"
                          prop="identifierType">
              <el-select v-model="form.identifierType"
                         placeholder="请选择标识类型"
                         style="width: 100%">
                <el-option label="二维码"
                           value="二维码"></el-option>
                <el-option label="防伪码"
                           value="防伪码"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="生成数量" prop="quantity">
              <el-input-number v-model="form.quantity" :min="1" :max="10000" style="width: 100%"></el-input-number>
            <el-form-item label="生成数量"
                          prop="quantity">
              <el-input-number v-model="form.quantity"
                               :min="1"
                               :max="10000"
                               style="width: 100%"></el-input-number>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="状态" prop="status">
              <el-select v-model="form.status" placeholder="请选择状态" style="width: 100%">
                <el-option label="已生成" value="已生成"></el-option>
                <el-option label="已分配" value="已分配"></el-option>
                <el-option label="已使用" value="已使用"></el-option>
                <el-option label="已作废" value="已作废"></el-option>
            <el-form-item label="状态"
                          prop="status">
              <el-select v-model="form.status"
                         placeholder="请选择状态"
                         style="width: 100%">
                <el-option label="已生成"
                           value="已生成"></el-option>
                <el-option label="已分配"
                           value="已分配"></el-option>
                <el-option label="已使用"
                           value="已使用"></el-option>
                <el-option label="已作废"
                           value="已作废"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="备注" prop="remark">
              <el-input type="textarea" v-model="form.remark" placeholder="请输入备注信息" rows="3"></el-input>
            <el-form-item label="备注"
                          prop="remark">
              <el-input type="textarea"
                        v-model="form.remark"
                        placeholder="请输入备注信息"
                        rows="3"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleSubmit">确 定</el-button>
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 标识生成对话框 -->
    <el-dialog v-model="generateDialogVisible" title="标识生成" width="500px">
    <el-dialog v-model="generateDialogVisible"
               title="标识生成"
               width="500px">
      <el-form label-width="100px">
        <el-form-item label="产品名称">
          <span>{{ currentProduct.productName }}</span>
@@ -167,30 +239,45 @@
        <el-form-item label="标识类型">
          <span>{{ currentProduct.identifierType }}</span>
        </el-form-item>
        <el-form-item label="生成数量" prop="generateQuantity">
          <el-input-number v-model="generateQuantity" :min="1" :max="10000" style="width: 100%"></el-input-number>
        <el-form-item label="生成数量"
                      prop="generateQuantity">
          <el-input-number v-model="generateQuantity"
                           :min="1"
                           :max="10000"
                           style="width: 100%"></el-input-number>
        </el-form-item>
        <el-form-item label="编码规则" prop="codeRule">
          <el-select v-model="codeRule" placeholder="请选择编码规则" style="width: 100%">
            <el-option label="产品编码+批次号+序号" value="产品编码+批次号+序号"></el-option>
            <el-option label="时间戳+随机数" value="时间戳+随机数"></el-option>
            <el-option label="自定义规则" value="自定义规则"></el-option>
        <el-form-item label="编码规则"
                      prop="codeRule">
          <el-select v-model="codeRule"
                     placeholder="请选择编码规则"
                     style="width: 100%">
            <el-option label="产品编码+批次号+序号"
                       value="产品编码+批次号+序号"></el-option>
            <el-option label="时间戳+随机数"
                       value="时间戳+随机数"></el-option>
            <el-option label="自定义规则"
                       value="自定义规则"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="自定义前缀" prop="customPrefix" v-if="codeRule === '自定义规则'">
          <el-input v-model="customPrefix" placeholder="请输入自定义前缀"></el-input>
        <el-form-item label="自定义前缀"
                      prop="customPrefix"
                      v-if="codeRule === '自定义规则'">
          <el-input v-model="customPrefix"
                    placeholder="请输入自定义前缀"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="generateIdentifiers">生 成</el-button>
          <el-button @click="generateDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="generateIdentifiers">生 成</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 重新分配对话框 -->
    <el-dialog v-model="reassignDialogVisible" title="重新分配标识" width="500px">
    <el-dialog v-model="reassignDialogVisible"
               title="重新分配标识"
               width="500px">
      <el-form label-width="100px">
        <el-form-item label="产品名称">
          <span>{{ currentProduct.productName }}</span>
@@ -198,26 +285,38 @@
        <el-form-item label="标识码">
          <span>{{ currentProduct.identifierCode }}</span>
        </el-form-item>
        <el-form-item label="新批次号" prop="newBatchNo">
          <el-input v-model="newBatchNo" placeholder="请输入新批次号"></el-input>
        <el-form-item label="新批次号"
                      prop="newBatchNo">
          <el-input v-model="newBatchNo"
                    placeholder="请输入新批次号"></el-input>
        </el-form-item>
        <el-form-item label="分配原因" prop="reassignReason">
          <el-input type="textarea" v-model="reassignReason" rows="3" placeholder="请输入重新分配原因"></el-input>
        <el-form-item label="分配原因"
                      prop="reassignReason">
          <el-input type="textarea"
                    v-model="reassignReason"
                    rows="3"
                    placeholder="请输入重新分配原因"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="saveReassign">确 定</el-button>
          <el-button @click="reassignDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveReassign">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 二维码预览对话框 -->
    <el-dialog v-model="qrCodeDialogVisible" title="二维码预览" width="500px" center>
    <el-dialog v-model="qrCodeDialogVisible"
               title="二维码预览"
               width="500px"
               center>
      <div class="qr-preview-container">
        <div v-if="qrCodeUrl" class="qr-image-container">
          <img :src="qrCodeUrl" alt="二维码" class="qr-image" />
        <div v-if="qrCodeUrl"
             class="qr-image-container">
          <img :src="qrCodeUrl"
               alt="二维码"
               class="qr-image" />
          <div class="qr-info">
            <p><strong>产品名称:</strong>{{ currentQRProduct.productName }}</p>
            <p><strong>产品编码:</strong>{{ currentQRProduct.productCode }}</p>
@@ -226,29 +325,27 @@
            <p><strong>标识类型:</strong>{{ currentQRProduct.identifierType }}</p>
          </div>
        </div>
        <div v-else class="qr-loading">
          <el-icon class="is-loading"><Loading /></el-icon>
        <div v-else
             class="qr-loading">
          <el-icon class="is-loading">
            <Loading />
          </el-icon>
          <p>正在生成二维码...</p>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="qrCodeDialogVisible = false">关闭</el-button>
          <el-button
            v-if="qrCodeUrl"
          <el-button v-if="qrCodeUrl"
            type="primary" 
            @click="copyQRContent" 
            icon="CopyDocument"
          >
                     icon="CopyDocument">
            复制内容
          </el-button>
          <el-button
            v-if="qrCodeUrl"
          <el-button v-if="qrCodeUrl"
            type="success" 
            @click="downloadQRCode" 
            icon="Download"
          >
                     icon="Download">
            下载二维码
          </el-button>
        </div>
@@ -258,219 +355,225 @@
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search, Loading, Download } from '@element-plus/icons-vue'
import Pagination from '@/components/PIMTable/Pagination.vue'
import QRCode from 'qrcode'
  import { ref, reactive, computed } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus, Search, Loading, Download } from "@element-plus/icons-vue";
  import Pagination from "@/components/PIMTable/Pagination.vue";
  import QRCode from "qrcode";
// 响应式数据
const loading = ref(false)
  const loading = ref(false);
const searchForm = reactive({
  productName: '',
  identifierType: '',
  status: ''
})
    productName: "",
    identifierType: "",
    status: "",
  });
const identifierList = ref([
  {
    id: 1,
    productName: '工业传感器A型',
    productCode: 'SENSOR001',
    batchNo: 'B202312001',
    identifierType: '二维码',
    identifierCode: 'QR_SENSOR001_B202312001_001',
    status: '已分配',
    generateTime: '2023-12-01 10:00:00',
    remark: '重要产品标识'
      productName: "工业传感器A型",
      productCode: "SENSOR001",
      batchNo: "B202312001",
      identifierType: "二维码",
      identifierCode: "QR_SENSOR001_B202312001_001",
      status: "已分配",
      generateTime: "2023-12-01 10:00:00",
      remark: "重要产品标识",
  },
  {
    id: 2,
    productName: '控制面板B型',
    productCode: 'PANEL002',
    batchNo: 'B202312002',
    identifierType: '防伪码',
    identifierCode: 'SEC_PANEL002_B202312002_001',
    status: '已生成',
    generateTime: '2023-12-02 14:30:00',
    remark: '常规产品标识'
      productName: "控制面板B型",
      productCode: "PANEL002",
      batchNo: "B202312002",
      identifierType: "防伪码",
      identifierCode: "SEC_PANEL002_B202312002_001",
      status: "已生成",
      generateTime: "2023-12-02 14:30:00",
      remark: "常规产品标识",
  },
  {
    id: 3,
    productName: '数据采集器C型',
    productCode: 'COLLECTOR003',
    batchNo: 'B202312003',
    identifierType: '防伪码',
    identifierCode: 'SEC_COLLECTOR003_B202312003_001',
    status: '已使用',
    generateTime: '2023-12-03 09:15:00',
    remark: '测试产品标识'
  }
])
      productName: "数据采集器C型",
      productCode: "COLLECTOR003",
      batchNo: "B202312003",
      identifierType: "防伪码",
      identifierCode: "SEC_COLLECTOR003_B202312003_001",
      status: "已使用",
      generateTime: "2023-12-03 09:15:00",
      remark: "测试产品标识",
    },
  ]);
const pagination = reactive({
  total: 3,
  currentPage: 1,
  pageSize: 10
})
    pageSize: 10,
  });
const dialogVisible = ref(false)
const dialogTitle = ref('新增标识')
  const dialogVisible = ref(false);
  const dialogTitle = ref("新增标识");
const form = reactive({
  productName: '',
  productCode: '',
  batchNo: '',
  identifierType: '',
    productName: "",
    productCode: "",
    batchNo: "",
    identifierType: "",
  quantity: 1,
  status: '已生成',
  remark: ''
})
    status: "已生成",
    remark: "",
  });
const rules = {
  productName: [{ required: true, message: '请输入产品名称', trigger: 'blur' }],
  productCode: [{ required: true, message: '请输入产品编码', trigger: 'blur' }],
  batchNo: [{ required: true, message: '请输入批次号', trigger: 'blur' }],
  identifierType: [{ required: true, message: '请选择标识类型', trigger: 'change' }],
  quantity: [{ required: true, message: '请输入生成数量', trigger: 'blur' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
}
    productName: [{ required: true, message: "请输入产品名称", trigger: "blur" }],
    productCode: [{ required: true, message: "请输入产品编码", trigger: "blur" }],
    batchNo: [{ required: true, message: "请输入批次号", trigger: "blur" }],
    identifierType: [
      { required: true, message: "请选择标识类型", trigger: "change" },
    ],
    quantity: [{ required: true, message: "请输入生成数量", trigger: "blur" }],
    status: [{ required: true, message: "请选择状态", trigger: "change" }],
  };
const isEdit = ref(false)
const editId = ref(null)
const generateDialogVisible = ref(false)
const reassignDialogVisible = ref(false)
const currentProduct = ref({})
const generateQuantity = ref(1)
const codeRule = ref('')
const customPrefix = ref('')
const newBatchNo = ref('')
const reassignReason = ref('')
const formRef = ref()
  const isEdit = ref(false);
  const editId = ref(null);
  const generateDialogVisible = ref(false);
  const reassignDialogVisible = ref(false);
  const currentProduct = ref({});
  const generateQuantity = ref(1);
  const codeRule = ref("");
  const customPrefix = ref("");
  const newBatchNo = ref("");
  const reassignReason = ref("");
  const formRef = ref();
// 二维码相关变量
const qrCodeDialogVisible = ref(false)
const qrCodeUrl = ref('')
const currentQRProduct = ref({})
  const qrCodeDialogVisible = ref(false);
  const qrCodeUrl = ref("");
  const currentQRProduct = ref({});
// 计算属性
const filteredList = computed(() => {
  let list = identifierList.value
    let list = identifierList.value;
  if (searchForm.productName) {
    list = list.filter(item => item.productName.includes(searchForm.productName))
      list = list.filter(item =>
        item.productName.includes(searchForm.productName)
      );
  }
  if (searchForm.identifierType) {
    list = list.filter(item => item.identifierType === searchForm.identifierType)
      list = list.filter(
        item => item.identifierType === searchForm.identifierType
      );
  }
  if (searchForm.status) {
    list = list.filter(item => item.status === searchForm.status)
      list = list.filter(item => item.status === searchForm.status);
  }
  return list
})
    return list;
  });
// 方法
const getIdentifierTypeType = (type) => {
  const getIdentifierTypeType = type => {
  const typeMap = {
    '二维码': 'success',
    '防伪码': 'warning'
  }
  return typeMap[type] || 'info'
}
      二维码: "success",
      防伪码: "warning",
    };
    return typeMap[type] || "info";
  };
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    '已生成': 'info',
    '已分配': 'primary',
    '已使用': 'success',
    '已作废': 'danger'
  }
  return statusMap[status] || 'info'
}
      已生成: "info",
      已分配: "primary",
      已使用: "success",
      已作废: "danger",
    };
    return statusMap[status] || "info";
  };
const handleSearch = () => {
  // 搜索逻辑已在computed中处理
}
  };
const resetSearch = () => {
  searchForm.productName = ''
  searchForm.identifierType = ''
  searchForm.status = ''
}
    searchForm.productName = "";
    searchForm.identifierType = "";
    searchForm.status = "";
  };
const handleAdd = () => {
  dialogTitle.value = '新增标识'
  isEdit.value = false
  form.productName = ''
  form.productCode = ''
  form.batchNo = ''
  form.identifierType = ''
  form.quantity = 1
  form.status = '已生成'
  form.remark = ''
  dialogVisible.value = true
}
    dialogTitle.value = "新增标识";
    isEdit.value = false;
    form.productName = "";
    form.productCode = "";
    form.batchNo = "";
    form.identifierType = "";
    form.quantity = 1;
    form.status = "已生成";
    form.remark = "";
    dialogVisible.value = true;
  };
const handleView = (row) => {
  const handleView = row => {
  // 查看标识详情
  ElMessage.info('查看标识详情功能待实现')
}
    ElMessage.info("查看标识详情功能待实现");
  };
const handleEdit = (row) => {
  dialogTitle.value = '编辑标识'
  isEdit.value = true
  editId.value = row.id
  Object.assign(form, row)
  dialogVisible.value = true
}
  const handleEdit = row => {
    dialogTitle.value = "编辑标识";
    isEdit.value = true;
    editId.value = row.id;
    Object.assign(form, row);
    dialogVisible.value = true;
  };
const handleExport = (row) => {
  const handleExport = row => {
  // 导出标识
  ElMessage.success(`已导出标识: ${row.identifierCode}`)
}
    ElMessage.success(`已导出标识: ${row.identifierCode}`);
  };
const handleReassign = (row) => {
  currentProduct.value = row
  newBatchNo.value = ''
  reassignReason.value = ''
  reassignDialogVisible.value = true
}
  const handleReassign = row => {
    currentProduct.value = row;
    newBatchNo.value = "";
    reassignReason.value = "";
    reassignDialogVisible.value = true;
  };
const handleDelete = (row) => {
  ElMessageBox.confirm('确认删除该标识吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const handleDelete = row => {
    ElMessageBox.confirm("确认删除该标识吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    const index = identifierList.value.findIndex(item => item.id === row.id)
      const index = identifierList.value.findIndex(item => item.id === row.id);
    if (index > -1) {
      identifierList.value.splice(index, 1)
      pagination.total--
      ElMessage.success('删除成功')
        identifierList.value.splice(index, 1);
        pagination.total--;
        ElMessage.success("删除成功");
    }
  })
}
    });
  };
// 生成二维码
const generateQRCode = async (row) => {
  const generateQRCode = async row => {
  try {
    // 检查必要字段
    if (!row.productName || !row.productCode || !row.batchNo) {
      ElMessage.warning('产品信息不完整,无法生成二维码')
      return
        ElMessage.warning("产品信息不完整,无法生成二维码");
        return;
    }
    
    currentQRProduct.value = row
    qrCodeUrl.value = ''
    qrCodeDialogVisible.value = true
      currentQRProduct.value = row;
      qrCodeUrl.value = "";
      qrCodeDialogVisible.value = true;
    
    // 构建二维码内容
    let qrContent = ''
    if (row.identifierType === '二维码') {
      qrContent = `${row.productName}|${row.productCode}|${row.batchNo}|${row.identifierCode}`
    } else if (row.identifierType === '防伪码') {
      let qrContent = "";
      if (row.identifierType === "二维码") {
        qrContent = `${row.productName}|${row.productCode}|${row.batchNo}|${row.identifierCode}`;
      } else if (row.identifierType === "防伪码") {
      // 防伪码格式:SEC_产品编码_批次号_时间戳_随机数
      const timestamp = Date.now()
      const random = Math.random().toString(36).substr(2, 8)
      qrContent = `SEC_${row.productCode}_${row.batchNo}_${timestamp}_${random}`
        const timestamp = Date.now();
        const random = Math.random().toString(36).substr(2, 8);
        qrContent = `SEC_${row.productCode}_${row.batchNo}_${timestamp}_${random}`;
    }
    
    // 生成二维码
@@ -478,84 +581,87 @@
      width: 256,
      margin: 2,
      color: {
        dark: '#000000',
        light: '#FFFFFF'
          dark: "#000000",
          light: "#FFFFFF",
      },
      errorCorrectionLevel: row.identifierType === '防伪码' ? 'H' : 'M'
    })
        errorCorrectionLevel: row.identifierType === "防伪码" ? "H" : "M",
      });
    
    ElMessage.success('二维码生成成功!')
      ElMessage.success("二维码生成成功!");
  } catch (error) {
    console.error('生成二维码失败:', error)
    ElMessage.error('生成二维码失败:' + error.message)
    qrCodeDialogVisible.value = false
      console.error("生成二维码失败:", error);
      ElMessage.error("生成二维码失败:" + error.message);
      qrCodeDialogVisible.value = false;
  }
}
  };
// 下载二维码
const downloadQRCode = () => {
  if (!qrCodeUrl.value) {
    ElMessage.warning('请先生成二维码')
    return
      ElMessage.warning("请先生成二维码");
      return;
  }
  
  const a = document.createElement('a')
  a.href = qrCodeUrl.value
  a.download = `${currentQRProduct.value.productName}_${currentQRProduct.value.identifierType}_${new Date().getTime()}.png`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  ElMessage.success('下载成功!')
}
    const a = document.createElement("a");
    a.href = qrCodeUrl.value;
    a.download = `${currentQRProduct.value.productName}_${
      currentQRProduct.value.identifierType
    }_${new Date().getTime()}.png`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    ElMessage.success("下载成功!");
  };
// 复制二维码内容
const copyQRContent = async () => {
  if (!currentQRProduct.value) {
    ElMessage.warning('没有可复制的内容')
    return
      ElMessage.warning("没有可复制的内容");
      return;
  }
  
  try {
    let content = ''
    if (currentQRProduct.value.identifierType === '二维码') {
      content = `${currentQRProduct.value.productName}|${currentQRProduct.value.productCode}|${currentQRProduct.value.batchNo}|${currentQRProduct.value.identifierCode}`
    } else if (currentQRProduct.value.identifierType === '防伪码') {
      const timestamp = Date.now()
      const random = Math.random().toString(36).substr(2, 8)
      content = `SEC_${currentQRProduct.value.productCode}_${currentQRProduct.value.batchNo}_${timestamp}_${random}`
      let content = "";
      if (currentQRProduct.value.identifierType === "二维码") {
        content = `${currentQRProduct.value.productName}|${currentQRProduct.value.productCode}|${currentQRProduct.value.batchNo}|${currentQRProduct.value.identifierCode}`;
      } else if (currentQRProduct.value.identifierType === "防伪码") {
        const timestamp = Date.now();
        const random = Math.random().toString(36).substr(2, 8);
        content = `SEC_${currentQRProduct.value.productCode}_${currentQRProduct.value.batchNo}_${timestamp}_${random}`;
    }
    
    await navigator.clipboard.writeText(content)
    ElMessage.success('内容已复制到剪贴板')
      await navigator.clipboard.writeText(content);
      ElMessage.success("内容已复制到剪贴板");
  } catch (error) {
    // 降级方案
    const textArea = document.createElement('textarea')
    textArea.value = content
    document.body.appendChild(textArea)
    textArea.select()
    document.execCommand('copy')
    document.body.removeChild(textArea)
    ElMessage.success('内容已复制到剪贴板')
      const textArea = document.createElement("textarea");
      textArea.value = content;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand("copy");
      document.body.removeChild(textArea);
      ElMessage.success("内容已复制到剪贴板");
  }
}
  };
const generateIdentifiers = () => {
  if (!codeRule.value) {
    ElMessage.warning('请选择编码规则')
    return
      ElMessage.warning("请选择编码规则");
      return;
  }
  
  // 生成标识的逻辑
  const newIdentifiers = []
    const newIdentifiers = [];
  for (let i = 1; i <= generateQuantity.value; i++) {
    let identifierCode = ''
    if (codeRule.value === '产品编码+批次号+序号') {
      identifierCode = `${currentProduct.value.productCode}_${currentProduct.value.batchNo}_${String(i).padStart(3, '0')}`
    } else if (codeRule.value === '时间戳+随机数') {
      identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`
    } else if (codeRule.value === '自定义规则') {
      identifierCode = `${customPrefix.value || 'CUSTOM'}_${Date.now()}_${i}`
      let identifierCode = "";
      if (codeRule.value === "产品编码+批次号+序号") {
        identifierCode = `${currentProduct.value.productCode}_${
          currentProduct.value.batchNo
        }_${String(i).padStart(3, "0")}`;
      } else if (codeRule.value === "时间戳+随机数") {
        identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
      } else if (codeRule.value === "自定义规则") {
        identifierCode = `${customPrefix.value || "CUSTOM"}_${Date.now()}_${i}`;
    }
    
    newIdentifiers.push({
@@ -565,73 +671,78 @@
      batchNo: currentProduct.value.batchNo,
      identifierType: currentProduct.value.identifierType,
      identifierCode: identifierCode,
      status: '已生成',
        status: "已生成",
      generateTime: new Date().toLocaleString(),
      remark: '批量生成'
    })
        remark: "批量生成",
      });
  }
  
  identifierList.value.push(...newIdentifiers)
  pagination.total += newIdentifiers.length
  ElMessage.success(`成功生成 ${newIdentifiers.length} 个标识`)
  generateDialogVisible.value = false
}
    identifierList.value.push(...newIdentifiers);
    pagination.total += newIdentifiers.length;
    ElMessage.success(`成功生成 ${newIdentifiers.length} 个标识`);
    generateDialogVisible.value = false;
  };
const saveReassign = () => {
  if (!newBatchNo.value) {
    ElMessage.warning('请输入新批次号')
    return
      ElMessage.warning("请输入新批次号");
      return;
  }
  
  const index = identifierList.value.findIndex(item => item.id === currentProduct.value.id)
    const index = identifierList.value.findIndex(
      item => item.id === currentProduct.value.id
    );
  if (index > -1) {
    identifierList.value[index].batchNo = newBatchNo.value
    identifierList.value[index].status = '已分配'
    ElMessage.success('标识重新分配成功')
    reassignDialogVisible.value = false
      identifierList.value[index].batchNo = newBatchNo.value;
      identifierList.value[index].status = "已分配";
      ElMessage.success("标识重新分配成功");
      reassignDialogVisible.value = false;
  }
}
  };
const handleSubmit = () => {
  formRef.value.validate((valid) => {
    formRef.value.validate(valid => {
    if (valid) {
      if (isEdit.value) {
        // 编辑
        const index = identifierList.value.findIndex(item => item.id === editId.value)
          const index = identifierList.value.findIndex(
            item => item.id === editId.value
          );
        if (index > -1) {
          identifierList.value[index] = { ...form, id: editId.value }
          ElMessage.success('编辑成功')
            identifierList.value[index] = { ...form, id: editId.value };
            ElMessage.success("编辑成功");
        }
             } else {
         // 新增
         const newId = Math.max(...identifierList.value.map(item => item.id)) + 1
          const newId =
            Math.max(...identifierList.value.map(item => item.id)) + 1;
         
         // 根据标识类型生成不同的标识码
         let identifierCode = ''
         if (form.identifierType === '二维码') {
           identifierCode = `QR_${form.productCode}_${form.batchNo}_001`
         } else if (form.identifierType === '防伪码') {
           identifierCode = `SEC_${form.productCode}_${form.batchNo}_001`
          let identifierCode = "";
          if (form.identifierType === "二维码") {
            identifierCode = `QR_${form.productCode}_${form.batchNo}_001`;
          } else if (form.identifierType === "防伪码") {
            identifierCode = `SEC_${form.productCode}_${form.batchNo}_001`;
         }
         
         identifierList.value.push({
           ...form,
           id: newId,
           identifierCode: identifierCode,
           generateTime: new Date().toLocaleString()
         })
         pagination.total++
         ElMessage.success('新增成功')
            generateTime: new Date().toLocaleString(),
          });
          pagination.total++;
          ElMessage.success("新增成功");
       }
      dialogVisible.value = false
        dialogVisible.value = false;
    }
  })
}
    });
  };
const handleCurrentChange = (val) => {
  pagination.currentPage = val.page
  pagination.pageSize = val.limit
}
  const handleCurrentChange = val => {
    pagination.currentPage = val.page;
    pagination.pageSize = val.limit;
  };
</script>
<style scoped>
@@ -698,7 +809,7 @@
.qr-loading .el-icon {
  font-size: 32px;
  color: #409EFF;
    color: #409eff;
}
.qr-loading p {
src/views/productionManagement/productStructure/StructureEdit.vue
@@ -1,227 +1,207 @@
<template>
  <el-dialog
      v-model="visible"
  <el-dialog v-model="visible"
      title="结构"
      width="1200"
      close-on-click-modal
      @close="visible = false"
  >
    <el-button
        v-if="dataValue.isEdit"
             @close="visible = false">
    <el-button v-if="dataValue.isEdit"
        type="primary"
        @click="addItem"
        style="margin-bottom: 10px"
    >添加
               style="margin-bottom: 10px">添加
    </el-button>
    <el-button
        v-if="!dataValue.isEdit"
    <el-button v-if="!dataValue.isEdit"
        type="primary"
        @click="dataValue.isEdit = true"
        style="margin-bottom: 10px"
    >编辑
               style="margin-bottom: 10px">编辑
    </el-button>
    <el-button
        v-if="dataValue.isEdit"
    <el-button v-if="dataValue.isEdit"
        type="primary"
        @click="cancelEdit"
        style="margin-bottom: 10px"
    >取消
               style="margin-bottom: 10px">取消
    </el-button>
    <el-form
        ref="form"
        :model="dataValue"
    >
      <el-table :data="dataValue.dataList" style="width: 100%">
        <el-table-column prop="productName" label="产品" width="150"/>
        <el-table-column prop="model" label="规格" width="150">
    <el-form ref="form"
             :model="dataValue">
      <el-table :data="dataValue.dataList"
                style="width: 100%">
        <el-table-column prop="productName"
                         label="产品"
                         width="150" />
        <el-table-column prop="model"
                         label="规格"
                         width="150">
          <template #default="{ row, $index }">
            <el-form-item
                v-if="dataValue.isEdit"
            <el-form-item v-if="dataValue.isEdit"
                :prop="`dataList.${$index}.model`"
                :rules="[{ required: true, message: '请选择规格', trigger: ['blur','change'] }]"
                style="margin: 0"
            >
              <el-select
                  v-model="row.model"
                          style="margin: 0">
              <el-select v-model="row.model"
                  placeholder="请选择产品"
                  clearable
                  :disabled="!dataValue.isEdit"
                  style="width: 100%"
                  @visible-change="(v) => { if (v) openDialog($index) }"
              >
                <el-option v-if="row.model" :label="row.model" :value="row.model" />
                         @visible-change="(v) => { if (v) openDialog($index) }">
                <el-option v-if="row.model"
                           :label="row.model"
                           :value="row.model" />
              </el-select>
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column prop="processId" label="消耗工序" width="150">
        <el-table-column prop="processId"
                         label="消耗工序"
                         width="150">
          <template #default="{ row, $index }">
            <el-form-item
                :prop="`dataList.${$index}.processId`"
            <el-form-item :prop="`dataList.${$index}.processId`"
                :rules="[{ required: true, message: '请选择消耗工序', trigger: 'change' }]"
                style="margin: 0"
            >
              <el-select
                  v-model="row.processId"
                          style="margin: 0">
              <el-select v-model="row.processId"
                  placeholder="请选择"
                  filterable
                  clearable
                  style="width: 100%"
                  :disabled="!dataValue.isEdit"
              >
                <el-option
                    v-for="item in dataValue.processOptions"
                         :disabled="!dataValue.isEdit">
                <el-option v-for="item in dataValue.processOptions"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                />
                           :value="item.id" />
              </el-select>
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column prop="unitQuantity" label="单位产出所需数量" width="150">
        <el-table-column prop="unitQuantity"
                         label="单位产出所需数量"
                         width="150">
          <template #default="{ row, $index }">
            <el-form-item
                :prop="`dataList.${$index}.unitQuantity`"
            <el-form-item :prop="`dataList.${$index}.unitQuantity`"
                :rules="[{ required: true, message: '请输入单位产出所需数量', trigger: ['blur','change'] }]"
                style="margin: 0"
            >
              <el-input-number
                  v-model="row.unitQuantity"
                          style="margin: 0">
              <el-input-number v-model="row.unitQuantity"
                  :min="0"
                  :precision="2"
                  :step="1"
                  controls-position="right"
                  style="width: 100%"
                  :disabled="!dataValue.isEdit"
              />
                               :disabled="!dataValue.isEdit" />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column prop="demandedQuantity" label="需求总量" width="150">
        <el-table-column prop="demandedQuantity"
                         label="需求总量"
                         width="150">
          <template #default="{ row, $index }">
            <el-form-item
                :prop="`dataList.${$index}.demandedQuantity`"
            <el-form-item :prop="`dataList.${$index}.demandedQuantity`"
                :rules="[{ required: true, message: '请输入需求总量', trigger: ['blur','change'] }]"
                style="margin: 0"
            >
              <el-input-number
                  v-model="row.demandedQuantity"
                          style="margin: 0">
              <el-input-number v-model="row.demandedQuantity"
                  :min="0"
                  :precision="2"
                  :step="1"
                  controls-position="right"
                  style="width: 100%"
                  :disabled="!dataValue.isEdit"
              />
                               :disabled="!dataValue.isEdit" />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column prop="unit" label="单位" width="150">
        <el-table-column prop="unit"
                         label="单位"
                         width="150">
          <template #default="{ row, $index }">
            <el-form-item
                :prop="`dataList.${$index}.unit`"
            <el-form-item :prop="`dataList.${$index}.unit`"
                :rules="[{ required: true, message: '请输入单位', trigger: ['blur','change'] }]"
                style="margin: 0"
            >
              <el-input
                  v-model="row.unit"
                          style="margin: 0">
              <el-input v-model="row.unit"
                  placeholder="请输入单位"
                  clearable
                  :disabled="!dataValue.isEdit"
              />
                        :disabled="!dataValue.isEdit" />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column prop="diskQuantity" label="盘数(盘)" width="150">
        <el-table-column prop="diskQuantity"
                         label="盘数(盘)"
                         width="150">
          <template #default="{ row, $index }">
            <el-form-item
                :prop="`dataList.${$index}.diskQuantity`"
            <el-form-item :prop="`dataList.${$index}.diskQuantity`"
                :rules="[{ required: true, message: '请输入盘数', trigger: ['blur','change'] }]"
                style="margin: 0"
            >
              <el-input-number
                  v-model="row.diskQuantity"
                          style="margin: 0">
              <el-input-number v-model="row.diskQuantity"
                  :min="0"
                  :precision="0"
                  :step="1"
                  controls-position="right"
                  style="width: 100%"
                  :disabled="!dataValue.isEdit"
              />
                               :disabled="!dataValue.isEdit" />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template #default="{ row, $index }">
            <el-button
                type="danger"
            <el-button type="danger"
                text
                @click="dataValue.dataList.splice($index, 1)"
            >删除
                       @click="dataValue.dataList.splice($index, 1)">删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-form>
    <product-select-dialog
        v-if="dataValue.showProductDialog"
    <product-select-dialog v-if="dataValue.showProductDialog"
        v-model:model-value="dataValue.showProductDialog"
        @confirm="handleProduct"/>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="visible = false">取消</el-button>
        <el-button type="primary" :loading="dataValue.loading" @click="submit" :disabled="!dataValue.isEdit">
        <el-button type="primary"
                   :loading="dataValue.loading"
                   @click="submit"
                   :disabled="!dataValue.isEdit">
          确认
        </el-button>
        <el-button @click="visible = false">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
import {computed, defineAsyncComponent, defineComponent, onMounted, reactive, ref} from "vue";
import {queryList, add} from '@/api/productionManagement/productStructure.js'
import {list} from '@/api/productionManagement/productionProcess'
  import {
    computed,
    defineAsyncComponent,
    defineComponent,
    onMounted,
    reactive,
    ref,
  } from "vue";
  import { queryList, add } from "@/api/productionManagement/productStructure.js";
  import { list } from "@/api/productionManagement/productionProcess";
import {ElMessage} from "element-plus";
defineComponent({
  name: "StructureEdit",
})
  });
const ProductSelectDialog = defineAsyncComponent(() => import('@/views/basicData/product/ProductSelectDialog.vue'))
const form = ref()
  const ProductSelectDialog = defineAsyncComponent(
    () => import("@/views/basicData/product/ProductSelectDialog.vue")
  );
  const form = ref();
const props = defineProps({
  showModel: {
    type: Boolean,
    default: false
      default: false,
  },
  productModelId: {
    type: Number,
    required: true
  }
})
      required: true,
    },
  });
const emits = defineEmits(['update:showModel'])
  const emits = defineEmits(["update:showModel"]);
const visible = computed({
  get() {
    return props.showModel
      return props.showModel;
  },
  set(val) {
    emits('update:showModel', val)
  }
})
      emits("update:showModel", val);
    },
  });
const dataValue = reactive({
  dataList: [],
@@ -233,72 +213,73 @@
  isEdit: false,
});
const openDialog = (index) => {
  dataValue.currentRowIndex = index
  dataValue.showProductDialog = true
}
  const openDialog = index => {
    dataValue.currentRowIndex = index;
    dataValue.showProductDialog = true;
  };
const fetchData = async () => {
  const {data} = await queryList(props.productModelId)
  dataValue.dataList = data
}
    const { data } = await queryList(props.productModelId);
    dataValue.dataList = data;
  };
const fetchProcessOptions = async () => {
  const {data} = await list(props.productModelId)
  dataValue.processOptions = data
}
    const { data } = await list(props.productModelId);
    dataValue.processOptions = data;
  };
const handleProduct = (row) => {
  const handleProduct = row => {
  if (row?.length > 1) {
    ElMessage.error('只能选择一个产品')
      ElMessage.error("只能选择一个产品");
  }
  dataValue.dataList[dataValue.currentRowIndex].productName = row[0].productName
  dataValue.dataList[dataValue.currentRowIndex].model = row[0].model
  dataValue.dataList[dataValue.currentRowIndex].productModelId = row[0].id
  dataValue.showProductDialog = false
}
    dataValue.dataList[dataValue.currentRowIndex].productName =
      row[0].productName;
    dataValue.dataList[dataValue.currentRowIndex].model = row[0].model;
    dataValue.dataList[dataValue.currentRowIndex].productModelId = row[0].id;
    dataValue.showProductDialog = false;
  };
const submit = () => {
  form.value.validate(valid => {
    dataValue.loading = true
    form.value
      .validate(valid => {
        dataValue.loading = true;
    if (valid) {
      add({
        parentId: props.productModelId,
        productStructureList: dataValue.dataList || []
            productStructureList: dataValue.dataList || [],
      }).then(res => {
        ElMessage.success('保存成功')
        visible.value = false
        dataValue.loading = false
      })
            ElMessage.success("保存成功");
            visible.value = false;
            dataValue.loading = false;
          });
    }
  }).finally(() => {
    dataValue.loading = false
  })
}
      .finally(() => {
        dataValue.loading = false;
      });
  };
const addItem = () => {
  dataValue.dataList.push({
    productName: '',
    productId: '',
      productName: "",
      productId: "",
    model: undefined,
    productModelId: undefined,
    processId: '',
      processId: "",
    unitQuantity: 0,
    demandedQuantity: 0,
    unit: '',
      unit: "",
    diskQuantity: 0,
  })
}
    });
  };
const cancelEdit = () => {
  dataValue.isEdit = false
  dataValue.dataList = dataValue.dataList.filter(item => item.id !== undefined)
}
    dataValue.isEdit = false;
    dataValue.dataList = dataValue.dataList.filter(item => item.id !== undefined);
  };
onMounted(() => {
  fetchData()
  fetchProcessOptions()
})
    fetchData();
    fetchProcessOptions();
  });
</script>
src/views/productionManagement/workOrder/index.vue
@@ -61,9 +61,9 @@
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="editDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleUpdate">确定</el-button>
          <el-button @click="editDialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
@@ -184,9 +184,9 @@
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="reportDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleReport">确定</el-button>
          <el-button @click="reportDialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
@@ -214,6 +214,11 @@
      width: "140",
    },
    {
      label: "生产订单号",
      prop: "productOrderNpsNo",
      width: "140",
    },
    {
      label: "产品名称",
      prop: "productName",
      width: "140",
src/views/salesManagement/customerManagement/index.vue
@@ -2,156 +2,229 @@
  <div class="app-container">
    <el-card class="box-card">
      <!-- 搜索区域 -->
      <el-row :gutter="20" class="search-row">
      <el-row :gutter="20"
              class="search-row">
        <el-col :span="6">
          <el-input
            v-model="searchForm.name"
          <el-input v-model="searchForm.name"
            placeholder="请输入客户名称"
            clearable
            @keyup.enter="handleSearch"
          >
                    @keyup.enter="handleSearch">
            <template #prefix>
              <el-icon><Search /></el-icon>
              <el-icon>
                <Search />
              </el-icon>
            </template>
          </el-input>
        </el-col>
        <el-col :span="6">
          <el-select v-model="searchForm.region" placeholder="请选择区域" clearable>
            <el-option label="华东区" value="华东区"></el-option>
            <el-option label="华南区" value="华南区"></el-option>
            <el-option label="华北区" value="华北区"></el-option>
            <el-option label="西南区" value="西南区"></el-option>
          <el-select v-model="searchForm.region"
                     placeholder="请选择区域"
                     clearable>
            <el-option label="华东区"
                       value="华东区"></el-option>
            <el-option label="华南区"
                       value="华南区"></el-option>
            <el-option label="华北区"
                       value="华北区"></el-option>
            <el-option label="西南区"
                       value="西南区"></el-option>
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-select v-model="searchForm.level" placeholder="请选择客户等级" clearable>
            <el-option label="VIP客户" value="VIP客户"></el-option>
            <el-option label="重要客户" value="重要客户"></el-option>
            <el-option label="普通客户" value="普通客户"></el-option>
          <el-select v-model="searchForm.level"
                     placeholder="请选择客户等级"
                     clearable>
            <el-option label="VIP客户"
                       value="VIP客户"></el-option>
            <el-option label="重要客户"
                       value="重要客户"></el-option>
            <el-option label="普通客户"
                       value="普通客户"></el-option>
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
          <el-button style="float: right;" type="primary" @click="handleAdd">
          <el-button style="float: right;"
                     type="primary"
                     @click="handleAdd">
            新增客户
          </el-button>
        </el-col>
      </el-row>
      <!-- 客户列表 -->
      <el-table
        :data="filteredList"
      <el-table :data="filteredList"
        style="width: 100%"
        v-loading="loading"
        border
        stripe
        height="calc(100vh - 22em)"
      >
        <el-table-column prop="id" label="ID" width="80" align="center"/>
        <el-table-column prop="name" label="客户名称" width="150" />
        <el-table-column prop="contactPerson" label="联系人" width="100" />
        <el-table-column prop="phone" label="联系电话" width="140" />
        <el-table-column prop="email" label="邮箱" />
        <el-table-column prop="region" label="区域" width="100" />
        <el-table-column prop="level" label="客户等级" width="100">
                height="calc(100vh - 22em)">
        <el-table-column prop="id"
                         label="ID"
                         width="80"
                         align="center" />
        <el-table-column prop="name"
                         label="客户名称"
                         width="150" />
        <el-table-column prop="contactPerson"
                         label="联系人"
                         width="100" />
        <el-table-column prop="phone"
                         label="联系电话"
                         width="140" />
        <el-table-column prop="email"
                         label="邮箱" />
        <el-table-column prop="region"
                         label="区域"
                         width="100" />
        <el-table-column prop="level"
                         label="客户等级"
                         width="100">
          <template #default="scope">
            <el-tag :type="getLevelType(scope.row.level)">
              {{ scope.row.level }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="salesperson" label="负责业务员" width="120" />
        <el-table-column prop="status" label="状态" width="80">
        <el-table-column prop="salesperson"
                         label="负责业务员"
                         width="120" />
        <el-table-column prop="status"
                         label="状态"
                         width="80">
          <template #default="scope">
            <el-tag :type="getStatusType(scope.row.status)">
              {{ scope.row.status }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" fixed="right" align="center">
        <el-table-column label="操作"
                         width="200"
                         fixed="right"
                         align="center">
          <template #default="scope">
            <el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="primary" @click="handleAllocation(scope.row)">分配</el-button>
            <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
            <el-button link
                       type="primary"
                       @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link
                       type="primary"
                       @click="handleAllocation(scope.row)">分配</el-button>
            <el-button link
                       type="danger"
                       @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
        :total="pagination.total"
      <pagination :total="pagination.total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="pagination.currentPage"
        :limit="pagination.pageSize"
        @pagination="handleCurrentChange"
      />
                  @pagination="handleCurrentChange" />
    </el-card>
    <!-- 新增/编辑对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
    <el-dialog v-model="dialogVisible"
               :title="dialogTitle"
               width="600px">
      <el-form :model="form"
               :rules="rules"
               ref="formRef"
               label-width="100px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="客户名称" prop="name">
              <el-input v-model="form.name" placeholder="请输入客户名称"></el-input>
            <el-form-item label="客户名称"
                          prop="name">
              <el-input v-model="form.name"
                        placeholder="请输入客户名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="联系人" prop="contactPerson">
              <el-input v-model="form.contactPerson" placeholder="请输入联系人"></el-input>
            <el-form-item label="联系人"
                          prop="contactPerson">
              <el-input v-model="form.contactPerson"
                        placeholder="请输入联系人"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="联系电话" prop="phone">
              <el-input v-model="form.phone" placeholder="请输入联系电话"></el-input>
            <el-form-item label="联系电话"
                          prop="phone">
              <el-input v-model="form.phone"
                        placeholder="请输入联系电话"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="邮箱" prop="email">
              <el-input v-model="form.email" placeholder="请输入邮箱"></el-input>
            <el-form-item label="邮箱"
                          prop="email">
              <el-input v-model="form.email"
                        placeholder="请输入邮箱"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="区域" prop="region">
              <el-select v-model="form.region" placeholder="请选择区域" style="width: 100%">
                <el-option label="华东区" value="华东区"></el-option>
                <el-option label="华南区" value="华南区"></el-option>
                <el-option label="华北区" value="华北区"></el-option>
                <el-option label="西南区" value="西南区"></el-option>
            <el-form-item label="区域"
                          prop="region">
              <el-select v-model="form.region"
                         placeholder="请选择区域"
                         style="width: 100%">
                <el-option label="华东区"
                           value="华东区"></el-option>
                <el-option label="华南区"
                           value="华南区"></el-option>
                <el-option label="华北区"
                           value="华北区"></el-option>
                <el-option label="西南区"
                           value="西南区"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户等级" prop="level">
              <el-select v-model="form.level" placeholder="请选择客户等级" style="width: 100%">
                <el-option label="VIP客户" value="VIP客户"></el-option>
                <el-option label="重要客户" value="重要客户"></el-option>
                <el-option label="普通客户" value="普通客户"></el-option>
            <el-form-item label="客户等级"
                          prop="level">
              <el-select v-model="form.level"
                         placeholder="请选择客户等级"
                         style="width: 100%">
                <el-option label="VIP客户"
                           value="VIP客户"></el-option>
                <el-option label="重要客户"
                           value="重要客户"></el-option>
                <el-option label="普通客户"
                           value="普通客户"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="负责业务员" prop="salesperson">
              <el-select v-model="form.salesperson" placeholder="请选择业务员" style="width: 100%">
                <el-option label="陈志强" value="陈志强"></el-option>
                <el-option label="刘雅婷" value="刘雅婷"></el-option>
                <el-option label="王建国" value="王建国"></el-option>
            <el-form-item label="负责业务员"
                          prop="salesperson">
              <el-select v-model="form.salesperson"
                         placeholder="请选择业务员"
                         style="width: 100%">
                <el-option label="陈志强"
                           value="陈志强"></el-option>
                <el-option label="刘雅婷"
                           value="刘雅婷"></el-option>
                <el-option label="王建国"
                           value="王建国"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="状态" prop="status">
              <el-select v-model="form.status" placeholder="请选择状态" style="width: 100%">
                <el-option label="活跃" value="活跃"></el-option>
                <el-option label="潜在" value="潜在"></el-option>
                <el-option label="流失" value="流失"></el-option>
            <el-form-item label="状态"
                          prop="status">
              <el-select v-model="form.status"
                         placeholder="请选择状态"
                         style="width: 100%">
                <el-option label="活跃"
                           value="活跃"></el-option>
                <el-option label="潜在"
                           value="潜在"></el-option>
                <el-option label="流失"
                           value="流失"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
@@ -159,14 +232,16 @@
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleSubmit">确 定</el-button>
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 客户分配对话框 -->
    <el-dialog v-model="allocationDialogVisible" title="客户分配" width="500px">
    <el-dialog v-model="allocationDialogVisible"
               title="客户分配"
               width="500px">
      <el-form label-width="100px">
        <el-form-item label="客户名称">
          <span>{{ currentCustomer.name }}</span>
@@ -175,20 +250,29 @@
          <span>{{ currentCustomer.salesperson }}</span>
        </el-form-item>
        <el-form-item label="重新分配">
          <el-select v-model="newSalesperson" placeholder="请选择新业务员" style="width: 100%">
            <el-option label="陈志强" value="陈志强"></el-option>
            <el-option label="刘雅婷" value="刘雅婷"></el-option>
            <el-option label="王建国" value="王建国"></el-option>
          <el-select v-model="newSalesperson"
                     placeholder="请选择新业务员"
                     style="width: 100%">
            <el-option label="陈志强"
                       value="陈志强"></el-option>
            <el-option label="刘雅婷"
                       value="刘雅婷"></el-option>
            <el-option label="王建国"
                       value="王建国"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="分配原因">
          <el-input v-model="allocationReason" type="textarea" rows="3" placeholder="请输入分配原因"></el-input>
          <el-input v-model="allocationReason"
                    type="textarea"
                    rows="3"
                    placeholder="请输入分配原因"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="saveAllocation">确 定</el-button>
          <el-button @click="allocationDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveAllocation">确 定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -196,224 +280,228 @@
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search } from '@element-plus/icons-vue'
import Pagination from '@/components/PIMTable/Pagination.vue'
  import { ref, reactive, computed } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus, Search } from "@element-plus/icons-vue";
  import Pagination from "@/components/PIMTable/Pagination.vue";
// 响应式数据
const loading = ref(false)
  const loading = ref(false);
const searchForm = reactive({
  name: '',
  region: '',
  level: ''
})
    name: "",
    region: "",
    level: "",
  });
const customerList = ref([
  {
    id: 1,
    name: '上海科技有限公司',
    contactPerson: '陈志强',
    phone: '021-12345678',
    email: 'zhang@shanghai-tech.com',
    region: '华东区',
    level: 'VIP客户',
    salesperson: '陈志强',
    status: '活跃'
      name: "上海科技有限公司",
      contactPerson: "陈志强",
      phone: "021-12345678",
      email: "zhang@shanghai-tech.com",
      region: "华东区",
      level: "VIP客户",
      salesperson: "陈志强",
      status: "活跃",
  },
  {
    id: 2,
    name: '深圳电子有限公司',
    contactPerson: '刘雅婷',
    phone: '0755-87654321',
    email: 'li@shenzhen-elec.com',
    region: '华南区',
    level: '重要客户',
    salesperson: '刘雅婷',
    status: '活跃'
      name: "深圳电子有限公司",
      contactPerson: "刘雅婷",
      phone: "0755-87654321",
      email: "li@shenzhen-elec.com",
      region: "华南区",
      level: "重要客户",
      salesperson: "刘雅婷",
      status: "活跃",
  },
  {
    id: 3,
    name: '北京贸易公司',
    contactPerson: '王建国',
    phone: '010-11223344',
    email: 'wang@beijing-trade.com',
    region: '华北区',
    level: '普通客户',
    salesperson: '王建国',
    status: '潜在'
  }
])
      name: "北京贸易公司",
      contactPerson: "王建国",
      phone: "010-11223344",
      email: "wang@beijing-trade.com",
      region: "华北区",
      level: "普通客户",
      salesperson: "王建国",
      status: "潜在",
    },
  ]);
const pagination = reactive({
  total: 3,
  currentPage: 1,
  pageSize: 10
})
    pageSize: 10,
  });
const dialogVisible = ref(false)
const dialogTitle = ref('新增客户')
  const dialogVisible = ref(false);
  const dialogTitle = ref("新增客户");
const form = reactive({
  name: '',
  contactPerson: '',
  phone: '',
  email: '',
  region: '',
  level: '',
  salesperson: '',
  status: '活跃'
})
    name: "",
    contactPerson: "",
    phone: "",
    email: "",
    region: "",
    level: "",
    salesperson: "",
    status: "活跃",
  });
const rules = {
  name: [{ required: true, message: '请输入客户名称', trigger: 'blur' }],
  contactPerson: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
  phone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
  email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }],
  region: [{ required: true, message: '请选择区域', trigger: 'change' }],
  level: [{ required: true, message: '请选择客户等级', trigger: 'change' }],
  salesperson: [{ required: true, message: '请选择业务员', trigger: 'change' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
}
    name: [{ required: true, message: "请输入客户名称", trigger: "blur" }],
    contactPerson: [{ required: true, message: "请输入联系人", trigger: "blur" }],
    phone: [{ required: true, message: "请输入联系电话", trigger: "blur" }],
    email: [{ required: true, message: "请输入邮箱", trigger: "blur" }],
    region: [{ required: true, message: "请选择区域", trigger: "change" }],
    level: [{ required: true, message: "请选择客户等级", trigger: "change" }],
    salesperson: [{ required: true, message: "请选择业务员", trigger: "change" }],
    status: [{ required: true, message: "请选择状态", trigger: "change" }],
  };
const isEdit = ref(false)
const editId = ref(null)
const allocationDialogVisible = ref(false)
const currentCustomer = ref({})
const newSalesperson = ref('')
const allocationReason = ref('')
const formRef = ref()
  const isEdit = ref(false);
  const editId = ref(null);
  const allocationDialogVisible = ref(false);
  const currentCustomer = ref({});
  const newSalesperson = ref("");
  const allocationReason = ref("");
  const formRef = ref();
// 计算属性
const filteredList = computed(() => {
  let list = customerList.value
    let list = customerList.value;
  if (searchForm.name) {
    list = list.filter(item => item.name.includes(searchForm.name))
      list = list.filter(item => item.name.includes(searchForm.name));
  }
  if (searchForm.region) {
    list = list.filter(item => item.region === searchForm.region)
      list = list.filter(item => item.region === searchForm.region);
  }
  if (searchForm.level) {
    list = list.filter(item => item.level === searchForm.level)
      list = list.filter(item => item.level === searchForm.level);
  }
  return list
})
    return list;
  });
// 方法
const getLevelType = (level) => {
  const getLevelType = level => {
  const levelMap = {
    'VIP客户': 'danger',
    '重要客户': 'warning',
    '普通客户': 'info'
  }
  return levelMap[level] || 'info'
}
      VIP客户: "danger",
      重要客户: "warning",
      普通客户: "info",
    };
    return levelMap[level] || "info";
  };
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    '活跃': 'success',
    '潜在': 'warning',
    '流失': 'danger'
  }
  return statusMap[status] || 'info'
}
      活跃: "success",
      潜在: "warning",
      流失: "danger",
    };
    return statusMap[status] || "info";
  };
const handleSearch = () => {
  // 搜索逻辑已在computed中处理
}
  };
const resetSearch = () => {
  searchForm.name = ''
  searchForm.region = ''
  searchForm.level = ''
}
    searchForm.name = "";
    searchForm.region = "";
    searchForm.level = "";
  };
const handleAdd = () => {
  dialogTitle.value = '新增客户'
  isEdit.value = false
  form.name = ''
  form.contactPerson = ''
  form.phone = ''
  form.email = ''
  form.region = ''
  form.level = ''
  form.salesperson = ''
  form.status = '活跃'
  dialogVisible.value = true
}
    dialogTitle.value = "新增客户";
    isEdit.value = false;
    form.name = "";
    form.contactPerson = "";
    form.phone = "";
    form.email = "";
    form.region = "";
    form.level = "";
    form.salesperson = "";
    form.status = "活跃";
    dialogVisible.value = true;
  };
const handleEdit = (row) => {
  dialogTitle.value = '编辑客户'
  isEdit.value = true
  editId.value = row.id
  Object.assign(form, row)
  dialogVisible.value = true
}
  const handleEdit = row => {
    dialogTitle.value = "编辑客户";
    isEdit.value = true;
    editId.value = row.id;
    Object.assign(form, row);
    dialogVisible.value = true;
  };
const handleDelete = (row) => {
  ElMessageBox.confirm('确认删除该客户吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const handleDelete = row => {
    ElMessageBox.confirm("确认删除该客户吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    const index = customerList.value.findIndex(item => item.id === row.id)
      const index = customerList.value.findIndex(item => item.id === row.id);
    if (index > -1) {
      customerList.value.splice(index, 1)
      pagination.total--
      ElMessage.success('删除成功')
        customerList.value.splice(index, 1);
        pagination.total--;
        ElMessage.success("删除成功");
    }
  })
}
    });
  };
const handleAllocation = (row) => {
  currentCustomer.value = row
  newSalesperson.value = ''
  allocationReason.value = ''
  allocationDialogVisible.value = true
}
  const handleAllocation = row => {
    currentCustomer.value = row;
    newSalesperson.value = "";
    allocationReason.value = "";
    allocationDialogVisible.value = true;
  };
const saveAllocation = () => {
  if (!newSalesperson.value) {
    ElMessage.warning('请选择新业务员')
    return
      ElMessage.warning("请选择新业务员");
      return;
  }
  
  const index = customerList.value.findIndex(item => item.id === currentCustomer.value.id)
    const index = customerList.value.findIndex(
      item => item.id === currentCustomer.value.id
    );
  if (index > -1) {
    customerList.value[index].salesperson = newSalesperson.value
    ElMessage.success('客户分配成功')
    allocationDialogVisible.value = false
      customerList.value[index].salesperson = newSalesperson.value;
      ElMessage.success("客户分配成功");
      allocationDialogVisible.value = false;
  }
}
  };
const handleSubmit = () => {
  formRef.value.validate((valid) => {
    formRef.value.validate(valid => {
    if (valid) {
      if (isEdit.value) {
        // 编辑
        const index = customerList.value.findIndex(item => item.id === editId.value)
          const index = customerList.value.findIndex(
            item => item.id === editId.value
          );
        if (index > -1) {
          customerList.value[index] = { ...form, id: editId.value }
          ElMessage.success('编辑成功')
            customerList.value[index] = { ...form, id: editId.value };
            ElMessage.success("编辑成功");
        }
      } else {
        // 新增
        const newId = Math.max(...customerList.value.map(item => item.id)) + 1
          const newId = Math.max(...customerList.value.map(item => item.id)) + 1;
        customerList.value.push({
          ...form,
          id: newId
        })
        pagination.total++
        ElMessage.success('新增成功')
            id: newId,
          });
          pagination.total++;
          ElMessage.success("新增成功");
      }
      dialogVisible.value = false
        dialogVisible.value = false;
    }
  })
}
    });
  };
const handleCurrentChange = (val) => {
  pagination.currentPage = val.page
  pagination.pageSize = val.limit
}
  const handleCurrentChange = val => {
    pagination.currentPage = val.page;
    pagination.pageSize = val.limit;
  };
</script>
<style scoped>
src/views/salesManagement/orderManagement/index.vue
@@ -2,164 +2,238 @@
  <div class="app-container">
    <el-card class="box-card">
      <!-- 搜索区域 -->
      <el-row :gutter="20" class="search-row">
      <el-row :gutter="20"
              class="search-row">
        <el-col :span="6">
          <el-input
            v-model="searchForm.orderNo"
          <el-input v-model="searchForm.orderNo"
            placeholder="请输入订单号"
            clearable
            @keyup.enter="handleSearch"
          >
                    @keyup.enter="handleSearch">
            <template #prefix>
              <el-icon><Search /></el-icon>
              <el-icon>
                <Search />
              </el-icon>
            </template>
          </el-input>
        </el-col>
        <el-col :span="6">
          <el-select v-model="searchForm.customer" placeholder="请选择客户" clearable>
            <el-option label="上海科技有限公司" value="上海科技有限公司"></el-option>
            <el-option label="深圳电子有限公司" value="深圳电子有限公司"></el-option>
            <el-option label="北京贸易公司" value="北京贸易公司"></el-option>
          <el-select v-model="searchForm.customer"
                     placeholder="请选择客户"
                     clearable>
            <el-option label="上海科技有限公司"
                       value="上海科技有限公司"></el-option>
            <el-option label="深圳电子有限公司"
                       value="深圳电子有限公司"></el-option>
            <el-option label="北京贸易公司"
                       value="北京贸易公司"></el-option>
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-select v-model="searchForm.status" placeholder="请选择订单状态" clearable>
            <el-option label="待审核" value="待审核"></el-option>
            <el-option label="已审核" value="已审核"></el-option>
            <el-option label="已发货" value="已发货"></el-option>
            <el-option label="已完成" value="已完成"></el-option>
            <el-option label="已取消" value="已取消"></el-option>
          <el-select v-model="searchForm.status"
                     placeholder="请选择订单状态"
                     clearable>
            <el-option label="待审核"
                       value="待审核"></el-option>
            <el-option label="已审核"
                       value="已审核"></el-option>
            <el-option label="已发货"
                       value="已发货"></el-option>
            <el-option label="已完成"
                       value="已完成"></el-option>
            <el-option label="已取消"
                       value="已取消"></el-option>
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
          <el-button style="float: right;" type="primary" @click="handleAdd">
          <el-button style="float: right;"
                     type="primary"
                     @click="handleAdd">
            新增订单
          </el-button>
        </el-col>
      </el-row>
      <!-- 订单列表 -->
      <el-table
        :data="filteredList"
      <el-table :data="filteredList"
        style="width: 100%"
        v-loading="loading"
        border
        stripe
        height="calc(100vh - 22em)"
      >
        <el-table-column prop="id" label="ID" width="80" align="center"/>
        <el-table-column prop="orderNo" label="订单号" width="150" />
        <el-table-column prop="customer" label="客户名称" />
        <el-table-column prop="salesperson" label="业务员" width="100" />
        <el-table-column prop="orderDate" label="下单日期" width="120" />
        <el-table-column prop="amount" label="订单金额" width="120">
                height="calc(100vh - 22em)">
        <el-table-column prop="id"
                         label="ID"
                         width="80"
                         align="center" />
        <el-table-column prop="orderNo"
                         label="订单号"
                         width="150" />
        <el-table-column prop="customer"
                         label="客户名称" />
        <el-table-column prop="salesperson"
                         label="业务员"
                         width="100" />
        <el-table-column prop="orderDate"
                         label="下单日期"
                         width="120" />
        <el-table-column prop="amount"
                         label="订单金额"
                         width="120">
          <template #default="scope">
            ¥{{ scope.row.amount.toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column prop="status" label="订单状态" width="100">
        <el-table-column prop="status"
                         label="订单状态"
                         width="100">
          <template #default="scope">
            <el-tag :type="getStatusType(scope.row.status)">
              {{ scope.row.status }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="250" fixed="right" align="center">
        <el-table-column label="操作"
                         width="250"
                         fixed="right"
                         align="center">
          <template #default="scope">
            <el-button link type="primary" @click="handleView(scope.row)">查看</el-button>
            <el-button link type="primary" @click="handleEdit(scope.row)" v-if="scope.row.status === '待审核'">编辑</el-button>
            <el-button link type="primary" @click="handleReview(scope.row)" v-if="scope.row.status === '待审核'">审核</el-button>
            <el-button link type="primary" @click="handleTransfer(scope.row)" v-if="scope.row.status === '已审核'">转单</el-button>
            <el-button link type="danger" @click="handleCancel(scope.row)" v-if="scope.row.status === '待审核'">取消</el-button>
            <el-button link
                       type="primary"
                       @click="handleView(scope.row)">查看</el-button>
            <el-button link
                       type="primary"
                       @click="handleEdit(scope.row)"
                       v-if="scope.row.status === '待审核'">编辑</el-button>
            <el-button link
                       type="primary"
                       @click="handleReview(scope.row)"
                       v-if="scope.row.status === '待审核'">审核</el-button>
            <el-button link
                       type="primary"
                       @click="handleTransfer(scope.row)"
                       v-if="scope.row.status === '已审核'">转单</el-button>
            <el-button link
                       type="danger"
                       @click="handleCancel(scope.row)"
                       v-if="scope.row.status === '待审核'">取消</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
        :total="pagination.total"
      <pagination :total="pagination.total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="pagination.currentPage"
        :limit="pagination.pageSize"
        @pagination="handleCurrentChange"
      />
                  @pagination="handleCurrentChange" />
    </el-card>
    <!-- 新增/编辑对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
    <el-dialog v-model="dialogVisible"
               :title="dialogTitle"
               width="700px">
      <el-form :model="form"
               :rules="rules"
               ref="formRef"
               label-width="100px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="客户名称" prop="customer">
              <el-select v-model="form.customer" placeholder="请选择客户" style="width: 100%">
                <el-option label="上海科技有限公司" value="上海科技有限公司"></el-option>
                <el-option label="深圳电子有限公司" value="深圳电子有限公司"></el-option>
                <el-option label="北京贸易公司" value="北京贸易公司"></el-option>
            <el-form-item label="客户名称"
                          prop="customer">
              <el-select v-model="form.customer"
                         placeholder="请选择客户"
                         style="width: 100%">
                <el-option label="上海科技有限公司"
                           value="上海科技有限公司"></el-option>
                <el-option label="深圳电子有限公司"
                           value="深圳电子有限公司"></el-option>
                <el-option label="北京贸易公司"
                           value="北京贸易公司"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="业务员" prop="salesperson">
              <el-select v-model="form.salesperson" placeholder="请选择业务员" style="width: 100%">
                <el-option label="陈志强" value="陈志强"></el-option>
                <el-option label="刘雅婷" value="刘雅婷"></el-option>
                <el-option label="王建国" value="王建国"></el-option>
            <el-form-item label="业务员"
                          prop="salesperson">
              <el-select v-model="form.salesperson"
                         placeholder="请选择业务员"
                         style="width: 100%">
                <el-option label="陈志强"
                           value="陈志强"></el-option>
                <el-option label="刘雅婷"
                           value="刘雅婷"></el-option>
                <el-option label="王建国"
                           value="王建国"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="订单日期" prop="orderDate">
              <el-date-picker
                v-model="form.orderDate"
            <el-form-item label="订单日期"
                          prop="orderDate">
              <el-date-picker v-model="form.orderDate"
                type="date"
                placeholder="选择订单日期"
                style="width: 100%"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
              />
                              value-format="YYYY-MM-DD" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="订单金额" prop="amount">
              <el-input-number v-model="form.amount" :precision="2" :min="0" style="width: 100%"></el-input-number>
            <el-form-item label="订单金额"
                          prop="amount">
              <el-input-number v-model="form.amount"
                               :precision="2"
                               :min="0"
                               style="width: 100%"></el-input-number>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="订单状态" prop="status">
              <el-select v-model="form.status" placeholder="请选择状态" style="width: 100%">
                <el-option label="待审核" value="待审核"></el-option>
                <el-option label="已审核" value="已审核"></el-option>
                <el-option label="已发货" value="已发货"></el-option>
                <el-option label="已完成" value="已完成"></el-option>
                <el-option label="已取消" value="已取消"></el-option>
            <el-form-item label="订单状态"
                          prop="status">
              <el-select v-model="form.status"
                         placeholder="请选择状态"
                         style="width: 100%">
                <el-option label="待审核"
                           value="待审核"></el-option>
                <el-option label="已审核"
                           value="已审核"></el-option>
                <el-option label="已发货"
                           value="已发货"></el-option>
                <el-option label="已完成"
                           value="已完成"></el-option>
                <el-option label="已取消"
                           value="已取消"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="备注" prop="remark">
              <el-input type="textarea" v-model="form.remark" placeholder="请输入备注信息" rows="3"></el-input>
            <el-form-item label="备注"
                          prop="remark">
              <el-input type="textarea"
                        v-model="form.remark"
                        placeholder="请输入备注信息"
                        rows="3"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleSubmit">确 定</el-button>
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 订单审核对话框 -->
    <el-dialog v-model="reviewDialogVisible" title="订单审核" width="500px">
    <el-dialog v-model="reviewDialogVisible"
               title="订单审核"
               width="500px">
      <el-form label-width="100px">
        <el-form-item label="订单号">
          <span>{{ currentOrder.orderNo }}</span>
@@ -170,26 +244,33 @@
        <el-form-item label="订单金额">
          <span>¥{{ currentOrder.amount.toFixed(2) }}</span>
        </el-form-item>
        <el-form-item label="审核结果" prop="reviewResult">
        <el-form-item label="审核结果"
                      prop="reviewResult">
          <el-radio-group v-model="reviewResult">
            <el-radio label="通过">通过</el-radio>
            <el-radio label="拒绝">拒绝</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="审核意见" prop="reviewComment">
          <el-input type="textarea" v-model="reviewComment" rows="3" placeholder="请输入审核意见"></el-input>
        <el-form-item label="审核意见"
                      prop="reviewComment">
          <el-input type="textarea"
                    v-model="reviewComment"
                    rows="3"
                    placeholder="请输入审核意见"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="saveReview">确 定</el-button>
          <el-button @click="reviewDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveReview">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 订单转单对话框 -->
    <el-dialog v-model="transferDialogVisible" title="订单转单" width="500px">
    <el-dialog v-model="transferDialogVisible"
               title="订单转单"
               width="500px">
      <el-form label-width="100px">
        <el-form-item label="订单号">
          <span>{{ currentOrder.orderNo }}</span>
@@ -197,21 +278,32 @@
        <el-form-item label="当前业务员">
          <span>{{ currentOrder.salesperson }}</span>
        </el-form-item>
        <el-form-item label="转单给" prop="newSalesperson">
          <el-select v-model="newSalesperson" placeholder="请选择新业务员" style="width: 100%">
            <el-option label="陈志强" value="陈志强"></el-option>
            <el-option label="刘雅婷" value="刘雅婷"></el-option>
            <el-option label="王建国" value="王建国"></el-option>
        <el-form-item label="转单给"
                      prop="newSalesperson">
          <el-select v-model="newSalesperson"
                     placeholder="请选择新业务员"
                     style="width: 100%">
            <el-option label="陈志强"
                       value="陈志强"></el-option>
            <el-option label="刘雅婷"
                       value="刘雅婷"></el-option>
            <el-option label="王建国"
                       value="王建国"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="转单原因" prop="transferReason">
          <el-input type="textarea" v-model="transferReason" rows="3" placeholder="请输入转单原因"></el-input>
        <el-form-item label="转单原因"
                      prop="transferReason">
          <el-input type="textarea"
                    v-model="transferReason"
                    rows="3"
                    placeholder="请输入转单原因"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="saveTransfer">确 定</el-button>
          <el-button @click="transferDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveTransfer">确 定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -219,257 +311,268 @@
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search } from '@element-plus/icons-vue'
import Pagination from '@/components/PIMTable/Pagination.vue'
  import { ref, reactive, computed } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus, Search } from "@element-plus/icons-vue";
  import Pagination from "@/components/PIMTable/Pagination.vue";
// 响应式数据
const loading = ref(false)
  const loading = ref(false);
const searchForm = reactive({
  orderNo: '',
  customer: '',
  status: ''
})
    orderNo: "",
    customer: "",
    status: "",
  });
const orderList = ref([
  {
    id: 1,
    orderNo: 'ORD202312001',
    customer: '广州科技公司',
    salesperson: '张三',
    orderDate: '2023-12-01',
    amount: 50000.00,
    status: '待审核',
    remark: '重要客户订单'
      orderNo: "ORD202312001",
      customer: "广州科技公司",
      salesperson: "张三",
      orderDate: "2023-12-01",
      amount: 50000.0,
      status: "待审核",
      remark: "重要客户订单",
  },
  {
    id: 2,
    orderNo: 'ORD202312002',
    customer: '深圳电子有限公司',
    salesperson: '刘雅婷',
    orderDate: '2023-12-02',
    amount: 35000.00,
    status: '已审核',
    remark: '常规订单'
      orderNo: "ORD202312002",
      customer: "深圳电子有限公司",
      salesperson: "刘雅婷",
      orderDate: "2023-12-02",
      amount: 35000.0,
      status: "已审核",
      remark: "常规订单",
  },
  {
    id: 3,
    orderNo: 'ORD202312003',
    customer: '北京贸易公司',
    salesperson: '王建国',
    orderDate: '2023-12-03',
    amount: 28000.00,
    status: '已发货',
    remark: '新客户订单'
  }
])
      orderNo: "ORD202312003",
      customer: "北京贸易公司",
      salesperson: "王建国",
      orderDate: "2023-12-03",
      amount: 28000.0,
      status: "已发货",
      remark: "新客户订单",
    },
  ]);
const pagination = reactive({
  total: 3,
  currentPage: 1,
  pageSize: 10
})
    pageSize: 10,
  });
const dialogVisible = ref(false)
const dialogTitle = ref('新增订单')
  const dialogVisible = ref(false);
  const dialogTitle = ref("新增订单");
const form = reactive({
  customer: '',
  salesperson: '',
  orderDate: '',
    customer: "",
    salesperson: "",
    orderDate: "",
  amount: 0,
  status: '待审核',
  remark: ''
})
    status: "待审核",
    remark: "",
  });
const rules = {
  customer: [{ required: true, message: '请选择客户', trigger: 'change' }],
  salesperson: [{ required: true, message: '请选择业务员', trigger: 'change' }],
  orderDate: [{ required: true, message: '请选择订单日期', trigger: 'change' }],
  amount: [{ required: true, message: '请输入订单金额', trigger: 'blur' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
}
    customer: [{ required: true, message: "请选择客户", trigger: "change" }],
    salesperson: [{ required: true, message: "请选择业务员", trigger: "change" }],
    orderDate: [{ required: true, message: "请选择订单日期", trigger: "change" }],
    amount: [{ required: true, message: "请输入订单金额", trigger: "blur" }],
    status: [{ required: true, message: "请选择状态", trigger: "change" }],
  };
const isEdit = ref(false)
const editId = ref(null)
const reviewDialogVisible = ref(false)
const transferDialogVisible = ref(false)
const currentOrder = ref({})
const reviewResult = ref('')
const reviewComment = ref('')
const newSalesperson = ref('')
const transferReason = ref('')
const formRef = ref()
  const isEdit = ref(false);
  const editId = ref(null);
  const reviewDialogVisible = ref(false);
  const transferDialogVisible = ref(false);
  const currentOrder = ref({});
  const reviewResult = ref("");
  const reviewComment = ref("");
  const newSalesperson = ref("");
  const transferReason = ref("");
  const formRef = ref();
// 计算属性
const filteredList = computed(() => {
  let list = orderList.value
    let list = orderList.value;
  if (searchForm.orderNo) {
    list = list.filter(item => item.orderNo.includes(searchForm.orderNo))
      list = list.filter(item => item.orderNo.includes(searchForm.orderNo));
  }
  if (searchForm.customer) {
    list = list.filter(item => item.customer === searchForm.customer)
      list = list.filter(item => item.customer === searchForm.customer);
  }
  if (searchForm.status) {
    list = list.filter(item => item.status === searchForm.status)
      list = list.filter(item => item.status === searchForm.status);
  }
  return list
})
    return list;
  });
// 方法
const getStatusType = (status) => {
  const getStatusType = status => {
  const statusMap = {
    '待审核': 'warning',
    '已审核': 'primary',
    '已发货': 'success',
    '已完成': 'success',
    '已取消': 'danger'
  }
  return statusMap[status] || 'info'
}
      待审核: "warning",
      已审核: "primary",
      已发货: "success",
      已完成: "success",
      已取消: "danger",
    };
    return statusMap[status] || "info";
  };
const handleSearch = () => {
  // 搜索逻辑已在computed中处理
}
  };
const resetSearch = () => {
  searchForm.orderNo = ''
  searchForm.customer = ''
  searchForm.status = ''
}
    searchForm.orderNo = "";
    searchForm.customer = "";
    searchForm.status = "";
  };
const handleAdd = () => {
  dialogTitle.value = '新增订单'
  isEdit.value = false
  form.customer = ''
  form.salesperson = ''
  form.orderDate = ''
  form.amount = 0
  form.status = '待审核'
  form.remark = ''
  dialogVisible.value = true
}
    dialogTitle.value = "新增订单";
    isEdit.value = false;
    form.customer = "";
    form.salesperson = "";
    form.orderDate = "";
    form.amount = 0;
    form.status = "待审核";
    form.remark = "";
    dialogVisible.value = true;
  };
const handleView = (row) => {
  const handleView = row => {
  // 查看订单详情
  ElMessage.info('查看订单详情功能待实现')
}
    ElMessage.info("查看订单详情功能待实现");
  };
const handleEdit = (row) => {
  dialogTitle.value = '编辑订单'
  isEdit.value = true
  editId.value = row.id
  Object.assign(form, row)
  dialogVisible.value = true
}
  const handleEdit = row => {
    dialogTitle.value = "编辑订单";
    isEdit.value = true;
    editId.value = row.id;
    Object.assign(form, row);
    dialogVisible.value = true;
  };
const handleReview = (row) => {
  currentOrder.value = row
  reviewResult.value = ''
  reviewComment.value = ''
  reviewDialogVisible.value = true
}
  const handleReview = row => {
    currentOrder.value = row;
    reviewResult.value = "";
    reviewComment.value = "";
    reviewDialogVisible.value = true;
  };
const handleTransfer = (row) => {
  currentOrder.value = row
  newSalesperson.value = ''
  transferReason.value = ''
  transferDialogVisible.value = true
}
  const handleTransfer = row => {
    currentOrder.value = row;
    newSalesperson.value = "";
    transferReason.value = "";
    transferDialogVisible.value = true;
  };
const handleCancel = (row) => {
  ElMessageBox.confirm('确认取消该订单吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const handleCancel = row => {
    ElMessageBox.confirm("确认取消该订单吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    const index = orderList.value.findIndex(item => item.id === row.id)
      const index = orderList.value.findIndex(item => item.id === row.id);
    if (index > -1) {
      orderList.value[index].status = '已取消'
      ElMessage.success('订单已取消')
        orderList.value[index].status = "已取消";
        ElMessage.success("订单已取消");
    }
  })
}
    });
  };
const handleDelete = (row) => {
  ElMessageBox.confirm('确认删除该订单吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const handleDelete = row => {
    ElMessageBox.confirm("确认删除该订单吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    const index = orderList.value.findIndex(item => item.id === row.id)
      const index = orderList.value.findIndex(item => item.id === row.id);
    if (index > -1) {
      orderList.value.splice(index, 1)
      pagination.total--
      ElMessage.success('删除成功')
        orderList.value.splice(index, 1);
        pagination.total--;
        ElMessage.success("删除成功");
    }
  })
}
    });
  };
const saveReview = () => {
  if (!reviewResult.value) {
    ElMessage.warning('请选择审核结果')
    return
      ElMessage.warning("请选择审核结果");
      return;
  }
  
  const index = orderList.value.findIndex(item => item.id === currentOrder.value.id)
    const index = orderList.value.findIndex(
      item => item.id === currentOrder.value.id
    );
  if (index > -1) {
    if (reviewResult.value === '通过') {
      orderList.value[index].status = '已审核'
      ElMessage.success('订单审核通过')
      if (reviewResult.value === "通过") {
        orderList.value[index].status = "已审核";
        ElMessage.success("订单审核通过");
    } else {
      orderList.value[index].status = '已取消'
      ElMessage.success('订单审核拒绝')
        orderList.value[index].status = "已取消";
        ElMessage.success("订单审核拒绝");
    }
    reviewDialogVisible.value = false
      reviewDialogVisible.value = false;
  }
}
  };
const saveTransfer = () => {
  if (!newSalesperson.value) {
    ElMessage.warning('请选择新业务员')
    return
      ElMessage.warning("请选择新业务员");
      return;
  }
  
  const index = orderList.value.findIndex(item => item.id === currentOrder.value.id)
    const index = orderList.value.findIndex(
      item => item.id === currentOrder.value.id
    );
  if (index > -1) {
    orderList.value[index].salesperson = newSalesperson.value
    ElMessage.success('订单转单成功')
    transferDialogVisible.value = false
      orderList.value[index].salesperson = newSalesperson.value;
      ElMessage.success("订单转单成功");
      transferDialogVisible.value = false;
  }
}
  };
const handleSubmit = () => {
  formRef.value.validate((valid) => {
    formRef.value.validate(valid => {
    if (valid) {
      if (isEdit.value) {
        // 编辑
        const index = orderList.value.findIndex(item => item.id === editId.value)
          const index = orderList.value.findIndex(
            item => item.id === editId.value
          );
        if (index > -1) {
          orderList.value[index] = { ...form, id: editId.value }
          ElMessage.success('编辑成功')
            orderList.value[index] = { ...form, id: editId.value };
            ElMessage.success("编辑成功");
        }
      } else {
        // 新增
        const newId = Math.max(...orderList.value.map(item => item.id)) + 1
        const orderNo = `ORD${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}${String(newId).padStart(3, '0')}`
          const newId = Math.max(...orderList.value.map(item => item.id)) + 1;
          const orderNo = `ORD${new Date().getFullYear()}${String(
            new Date().getMonth() + 1
          ).padStart(2, "0")}${String(new Date().getDate()).padStart(
            2,
            "0"
          )}${String(newId).padStart(3, "0")}`;
        orderList.value.push({
          ...form,
          id: newId,
          orderNo: orderNo
        })
        pagination.total++
        ElMessage.success('新增成功')
            orderNo: orderNo,
          });
          pagination.total++;
          ElMessage.success("新增成功");
      }
      dialogVisible.value = false
        dialogVisible.value = false;
    }
  })
}
    });
  };
const handleCurrentChange = (val) => {
  pagination.currentPage = val.page
  pagination.pageSize = val.limit
}
  const handleCurrentChange = val => {
    pagination.currentPage = val.page;
    pagination.pageSize = val.limit;
  };
</script>
<style scoped>
src/views/salesManagement/paymentShipping/index.vue
@@ -2,183 +2,255 @@
  <div class="app-container">
    <el-card class="box-card">
      <!-- 搜索区域 -->
      <el-row :gutter="20" class="search-row">
      <el-row :gutter="20"
              class="search-row">
        <el-col :span="6">
          <el-input
            v-model="searchForm.orderNo"
          <el-input v-model="searchForm.orderNo"
            placeholder="请输入订单号"
            clearable
            @keyup.enter="handleSearch"
          >
                    @keyup.enter="handleSearch">
            <template #prefix>
              <el-icon><Search /></el-icon>
              <el-icon>
                <Search />
              </el-icon>
            </template>
          </el-input>
        </el-col>
        <el-col :span="6">
          <el-select v-model="searchForm.paymentStatus" placeholder="请选择付款状态" clearable>
            <el-option label="未付款" value="未付款"></el-option>
            <el-option label="已付款" value="已付款"></el-option>
            <el-option label="部分付款" value="部分付款"></el-option>
          <el-select v-model="searchForm.paymentStatus"
                     placeholder="请选择付款状态"
                     clearable>
            <el-option label="未付款"
                       value="未付款"></el-option>
            <el-option label="已付款"
                       value="已付款"></el-option>
            <el-option label="部分付款"
                       value="部分付款"></el-option>
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-select v-model="searchForm.shippingStatus" placeholder="请选择发货状态" clearable>
            <el-option label="待发货" value="待发货"></el-option>
            <el-option label="已发货" value="已发货"></el-option>
            <el-option label="已签收" value="已签收"></el-option>
          <el-select v-model="searchForm.shippingStatus"
                     placeholder="请选择发货状态"
                     clearable>
            <el-option label="待发货"
                       value="待发货"></el-option>
            <el-option label="已发货"
                       value="已发货"></el-option>
            <el-option label="已签收"
                       value="已签收"></el-option>
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button type="primary"
                     @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
          <el-button style="float: right;" type="primary" @click="handleAdd">
          <el-button style="float: right;"
                     type="primary"
                     @click="handleAdd">
            新增记录
          </el-button>
        </el-col>
      </el-row>
      <!-- 支付与发货列表 -->
      <el-table
        :data="recordList"
      <el-table :data="recordList"
        style="width: 100%"
        v-loading="loading"
        border
        stripe
        height="calc(100vh - 22em)"
      >
        <el-table-column prop="id" label="ID" width="80" align="center"/>
        <el-table-column prop="orderNo" label="订单号" />
        <el-table-column prop="customer" label="客户名称" />
        <el-table-column prop="orderAmount" label="订单金额" width="120">
                height="calc(100vh - 22em)">
        <el-table-column prop="id"
                         label="ID"
                         width="80"
                         align="center" />
        <el-table-column prop="orderNo"
                         label="订单号" />
        <el-table-column prop="customer"
                         label="客户名称" />
        <el-table-column prop="orderAmount"
                         label="订单金额"
                         width="120">
          <template #default="scope">
            ¥{{ scope.row.orderAmount }}
          </template>
        </el-table-column>
        <el-table-column prop="orderAmount" label="已付款金额" width="120">
        <el-table-column prop="orderAmount"
                         label="已付款金额"
                         width="120">
          <template #default="scope">
            ¥{{ scope.row.paidAmount }}
          </template>
        </el-table-column>
        <el-table-column prop="paymentStatus" label="付款状态" width="100">
        <el-table-column prop="paymentStatus"
                         label="付款状态"
                         width="100">
          <template #default="scope">
            <el-tag :type="getPaymentStatusType(scope.row.paymentStatus)">
              {{ scope.row.paymentStatus }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="shippingStatus" label="发货状态" width="100">
        <el-table-column prop="shippingStatus"
                         label="发货状态"
                         width="100">
          <template #default="scope">
            <el-tag :type="getShippingStatusType(scope.row.shippingStatus)">
              {{ scope.row.shippingStatus }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="shippingDate" label="发货日期" width="120" />
        <el-table-column label="操作" width="250" fixed="right" align="center">
        <el-table-column prop="shippingDate"
                         label="发货日期"
                         width="120" />
        <el-table-column label="操作"
                         width="250"
                         fixed="right"
                         align="center">
          <template #default="scope">
<!--            <el-button link type="primary" @click="handleView(scope.row)">查看</el-button>-->
            <el-button link type="primary" @click="handlePayment(scope.row)" v-if="scope.row.paymentStatus !== '已付款'">付款</el-button>
            <el-button link type="primary" @click="handleShipping(scope.row)" v-if="scope.row.paymentStatus === '已付款' && scope.row.shippingStatus === '待发货'">发货</el-button>
            <el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
            <el-button link
                       type="primary"
                       @click="handlePayment(scope.row)"
                       v-if="scope.row.paymentStatus !== '已付款'">付款</el-button>
            <el-button link
                       type="primary"
                       @click="handleShipping(scope.row)"
                       v-if="scope.row.paymentStatus === '已付款' && scope.row.shippingStatus === '待发货'">发货</el-button>
            <el-button link
                       type="primary"
                       @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link
                       type="danger"
                       @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <pagination
        :total="total"
      <pagination :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="pagination.current"
        :limit="pagination.size"
        @pagination="handleCurrentChange"
      />
                  @pagination="handleCurrentChange" />
    </el-card>
    <!-- 新增/编辑对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
    <el-dialog v-model="dialogVisible"
               :title="dialogTitle"
               width="700px">
      <el-form :model="form"
               :rules="rules"
               ref="formRef"
               label-width="100px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="订单号" prop="orderNo">
              <el-input v-model="form.orderNo" placeholder="请输入订单号" disabled></el-input>
            <el-form-item label="订单号"
                          prop="orderNo">
              <el-input v-model="form.orderNo"
                        placeholder="请输入订单号"
                        disabled></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户名称" prop="customer">
              <el-select v-model="form.customer" placeholder="请选择客户" style="width: 100%">
                <el-option label="上海科技有限公司" value="上海科技有限公司"></el-option>
                <el-option label="深圳电子有限公司" value="深圳电子有限公司"></el-option>
                <el-option label="北京贸易公司" value="北京贸易公司"></el-option>
            <el-form-item label="客户名称"
                          prop="customer">
              <el-select v-model="form.customer"
                         placeholder="请选择客户"
                         style="width: 100%">
                <el-option label="上海科技有限公司"
                           value="上海科技有限公司"></el-option>
                <el-option label="深圳电子有限公司"
                           value="深圳电子有限公司"></el-option>
                <el-option label="北京贸易公司"
                           value="北京贸易公司"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="订单金额" prop="orderAmount">
              <el-input-number v-model="form.orderAmount" :precision="2" :min="0" style="width: 100%"></el-input-number>
            <el-form-item label="订单金额"
                          prop="orderAmount">
              <el-input-number v-model="form.orderAmount"
                               :precision="2"
                               :min="0"
                               style="width: 100%"></el-input-number>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="付款状态" prop="paymentStatus">
              <el-select v-model="form.paymentStatus" placeholder="请选择付款状态" style="width: 100%">
                <el-option label="未付款" value="未付款"></el-option>
                <el-option label="已付款" value="已付款"></el-option>
                <el-option label="部分付款" value="部分付款"></el-option>
            <el-form-item label="付款状态"
                          prop="paymentStatus">
              <el-select v-model="form.paymentStatus"
                         placeholder="请选择付款状态"
                         style="width: 100%">
                <el-option label="未付款"
                           value="未付款"></el-option>
                <el-option label="已付款"
                           value="已付款"></el-option>
                <el-option label="部分付款"
                           value="部分付款"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="发货状态" prop="shippingStatus">
              <el-select v-model="form.shippingStatus" placeholder="请选择发货状态" style="width: 100%">
                <el-option label="待发货" value="待发货"></el-option>
                <el-option label="已发货" value="已发货"></el-option>
                <el-option label="已签收" value="已签收"></el-option>
            <el-form-item label="发货状态"
                          prop="shippingStatus">
              <el-select v-model="form.shippingStatus"
                         placeholder="请选择发货状态"
                         style="width: 100%">
                <el-option label="待发货"
                           value="待发货"></el-option>
                <el-option label="已发货"
                           value="已发货"></el-option>
                <el-option label="已签收"
                           value="已签收"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="发货日期" prop="shippingDate">
              <el-date-picker
                v-model="form.shippingDate"
            <el-form-item label="发货日期"
                          prop="shippingDate">
              <el-date-picker v-model="form.shippingDate"
                type="date"
                placeholder="选择发货日期"
                style="width: 100%"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
              />
                              value-format="YYYY-MM-DD" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="物流单号" prop="trackingNo">
              <el-input v-model="form.trackingNo" placeholder="请输入物流单号"></el-input>
            <el-form-item label="物流单号"
                          prop="trackingNo">
              <el-input v-model="form.trackingNo"
                        placeholder="请输入物流单号"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="备注" prop="remark">
              <el-input type="textarea" v-model="form.remark" placeholder="请输入备注信息" rows="3"></el-input>
            <el-form-item label="备注"
                          prop="remark">
              <el-input type="textarea"
                        v-model="form.remark"
                        placeholder="请输入备注信息"
                        rows="3"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="handleSubmit">确 定</el-button>
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 付款对话框 -->
    <el-dialog v-model="paymentDialogVisible" title="订单付款" width="500px">
    <el-dialog v-model="paymentDialogVisible"
               title="订单付款"
               width="500px">
      <el-form label-width="100px">
        <el-form-item label="订单号">
          <span>{{ currentRecord.orderNo }}</span>
@@ -189,23 +261,34 @@
        <el-form-item label="订单金额">
          <span>¥{{ currentRecord.orderAmount }}</span>
        </el-form-item>
        <el-form-item label="付款金额" prop="paymentAmount">
          <el-input-number v-model="paymentAmount" :precision="2" :min="0" :max="currentRecord.orderAmount" style="width: 100%"></el-input-number>
        <el-form-item label="付款金额"
                      prop="paymentAmount">
          <el-input-number v-model="paymentAmount"
                           :precision="2"
                           :min="0"
                           :max="currentRecord.orderAmount"
                           style="width: 100%"></el-input-number>
        </el-form-item>
        <el-form-item label="付款备注" prop="paymentRemark">
          <el-input type="textarea" v-model="paymentRemark" rows="3" placeholder="请输入付款备注"></el-input>
        <el-form-item label="付款备注"
                      prop="paymentRemark">
          <el-input type="textarea"
                    v-model="paymentRemark"
                    rows="3"
                    placeholder="请输入付款备注"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="savePayment">确 定</el-button>
          <el-button @click="paymentDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="savePayment">确 定</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 发货对话框 -->
    <el-dialog v-model="shippingDialogVisible" title="订单发货" width="500px">
    <el-dialog v-model="shippingDialogVisible"
               title="订单发货"
               width="500px">
      <el-form label-width="100px">
        <el-form-item label="订单号">
          <span>{{ currentRecord.orderNo }}</span>
@@ -213,36 +296,50 @@
        <el-form-item label="客户名称">
          <span>{{ currentRecord.customer }}</span>
        </el-form-item>
        <el-form-item label="发货日期" prop="shippingDate">
          <el-date-picker
            v-model="shippingDate"
        <el-form-item label="发货日期"
                      prop="shippingDate">
          <el-date-picker v-model="shippingDate"
            type="date"
            placeholder="选择发货日期"
            style="width: 100%"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
          />
                          value-format="YYYY-MM-DD" />
        </el-form-item>
        <el-form-item label="物流公司" prop="logisticsCompany">
          <el-select v-model="logisticsCompany" placeholder="请选择物流公司" style="width: 100%">
            <el-option label="顺丰速运" value="顺丰速运"></el-option>
            <el-option label="圆通速递" value="圆通速递"></el-option>
            <el-option label="中通快递" value="中通快递"></el-option>
            <el-option label="申通快递" value="申通快递"></el-option>
            <el-option label="韵达速递" value="韵达速递"></el-option>
        <el-form-item label="物流公司"
                      prop="logisticsCompany">
          <el-select v-model="logisticsCompany"
                     placeholder="请选择物流公司"
                     style="width: 100%">
            <el-option label="顺丰速运"
                       value="顺丰速运"></el-option>
            <el-option label="圆通速递"
                       value="圆通速递"></el-option>
            <el-option label="中通快递"
                       value="中通快递"></el-option>
            <el-option label="申通快递"
                       value="申通快递"></el-option>
            <el-option label="韵达速递"
                       value="韵达速递"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="物流单号" prop="trackingNo">
          <el-input v-model="trackingNo" placeholder="请输入物流单号"></el-input>
        <el-form-item label="物流单号"
                      prop="trackingNo">
          <el-input v-model="trackingNo"
                    placeholder="请输入物流单号"></el-input>
        </el-form-item>
        <el-form-item label="发货备注" prop="shippingRemark">
          <el-input type="textarea" v-model="shippingRemark" rows="3" placeholder="请输入发货备注"></el-input>
        <el-form-item label="发货备注"
                      prop="shippingRemark">
          <el-input type="textarea"
                    v-model="shippingRemark"
                    rows="3"
                    placeholder="请输入发货备注"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="saveShipping">确 定</el-button>
          <el-button @click="shippingDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="saveShipping">确 定</el-button>
        </div>
      </template>
    </el-dialog>
@@ -250,228 +347,237 @@
</template>
<script setup>
import { ref, reactive, computed,onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search } from '@element-plus/icons-vue'
import {listPage,add,update,deletePaymentShipping} from "@/api/salesManagement/paymentShipping.js"
import Pagination from '@/components/PIMTable/Pagination.vue'
  import { ref, reactive, computed, onMounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus, Search } from "@element-plus/icons-vue";
  import {
    listPage,
    add,
    update,
    deletePaymentShipping,
  } from "@/api/salesManagement/paymentShipping.js";
  import Pagination from "@/components/PIMTable/Pagination.vue";
const total = ref(0)
  const total = ref(0);
onMounted(() => {
    getList()
})
    getList();
  });
const getList = () => {
  loading.value = true
    loading.value = true;
  listPage({...searchForm,...pagination}).then(res => {
    if(res.code === 200){
      recordList.value = res.data.records
      total.value = res.data.total
      loading.value = false
      console.log(recordList.value)
        recordList.value = res.data.records;
        total.value = res.data.total;
        loading.value = false;
        console.log(recordList.value);
    }
  })
}
    });
  };
// 响应式数据
const loading = ref(false)
  const loading = ref(false);
const searchForm = reactive({
  orderNo: '',
  paymentStatus: '',
  shippingStatus: ''
})
    orderNo: "",
    paymentStatus: "",
    shippingStatus: "",
  });
const recordList = ref([])
  const recordList = ref([]);
const pagination = reactive({
  current: 1,
  size: 10
})
    size: 10,
  });
const dialogVisible = ref(false)
const dialogTitle = ref('新增记录')
  const dialogVisible = ref(false);
  const dialogTitle = ref("新增记录");
const form = reactive({
  orderNo: '',
  customer: '',
    orderNo: "",
    customer: "",
  orderAmount: 0,
  paymentStatus: '未付款',
  shippingStatus: '待发货',
  shippingDate: '',
  trackingNo: '',
  remark: ''
})
    paymentStatus: "未付款",
    shippingStatus: "待发货",
    shippingDate: "",
    trackingNo: "",
    remark: "",
  });
const rules = {
  // orderNo: [{ required: true, message: '请输入订单号', trigger: 'blur' }],
  customer: [{ required: true, message: '请选择客户', trigger: 'change' }],
  orderAmount: [{ required: true, message: '请输入订单金额', trigger: 'blur' }],
  paymentStatus: [{ required: true, message: '请选择付款状态', trigger: 'change' }],
  shippingStatus: [{ required: true, message: '请选择发货状态', trigger: 'change' }]
}
    customer: [{ required: true, message: "请选择客户", trigger: "change" }],
    orderAmount: [{ required: true, message: "请输入订单金额", trigger: "blur" }],
    paymentStatus: [
      { required: true, message: "请选择付款状态", trigger: "change" },
    ],
    shippingStatus: [
      { required: true, message: "请选择发货状态", trigger: "change" },
    ],
  };
const isEdit = ref(false)
const editId = ref(null)
const paymentDialogVisible = ref(false)
const shippingDialogVisible = ref(false)
const currentRecord = ref({})
const paymentAmount = ref(0)
const paymentRemark = ref('')
const shippingDate = ref('')
const logisticsCompany = ref('')
const trackingNo = ref('')
const shippingRemark = ref('')
const formRef = ref()
  const isEdit = ref(false);
  const editId = ref(null);
  const paymentDialogVisible = ref(false);
  const shippingDialogVisible = ref(false);
  const currentRecord = ref({});
  const paymentAmount = ref(0);
  const paymentRemark = ref("");
  const shippingDate = ref("");
  const logisticsCompany = ref("");
  const trackingNo = ref("");
  const shippingRemark = ref("");
  const formRef = ref();
// 方法
const getPaymentStatusType = (status) => {
  const getPaymentStatusType = status => {
  const statusMap = {
    '未付款': 'danger',
    '已付款': 'success',
    '部分付款': 'warning'
  }
  return statusMap[status] || 'info'
}
      未付款: "danger",
      已付款: "success",
      部分付款: "warning",
    };
    return statusMap[status] || "info";
  };
const getShippingStatusType = (status) => {
  const getShippingStatusType = status => {
  const statusMap = {
    '待发货': 'warning',
    '已发货': 'primary',
    '已签收': 'success'
  }
  return statusMap[status] || 'info'
}
      待发货: "warning",
      已发货: "primary",
      已签收: "success",
    };
    return statusMap[status] || "info";
  };
const handleSearch = () => {
  // 搜索逻辑已在computed中处理
  getList()
}
    getList();
  };
const resetSearch = () => {
  searchForm.orderNo = ''
  searchForm.paymentStatus = ''
  searchForm.shippingStatus = ''
}
    searchForm.orderNo = "";
    searchForm.paymentStatus = "";
    searchForm.shippingStatus = "";
  };
const handleAdd = () => {
  dialogTitle.value = '新增记录'
  isEdit.value = false
  form.orderNo = ''
  form.customer = ''
  form.orderAmount = 0
  form.paymentStatus = '未付款'
  form.shippingStatus = '待发货'
  form.shippingDate = ''
  form.trackingNo = ''
  form.remark = ''
  dialogVisible.value = true
}
    dialogTitle.value = "新增记录";
    isEdit.value = false;
    form.orderNo = "";
    form.customer = "";
    form.orderAmount = 0;
    form.paymentStatus = "未付款";
    form.shippingStatus = "待发货";
    form.shippingDate = "";
    form.trackingNo = "";
    form.remark = "";
    dialogVisible.value = true;
  };
const handleView = (row) => {
  const handleView = row => {
  // 查看记录详情
  ElMessage.info('查看记录详情功能待实现')
}
    ElMessage.info("查看记录详情功能待实现");
  };
const handleEdit = (row) => {
  dialogTitle.value = '编辑记录'
  isEdit.value = true
  editId.value = row.id
  Object.assign(form, row)
  dialogVisible.value = true
}
  const handleEdit = row => {
    dialogTitle.value = "编辑记录";
    isEdit.value = true;
    editId.value = row.id;
    Object.assign(form, row);
    dialogVisible.value = true;
  };
const handlePayment = (row) => {
  currentRecord.value = row
  paymentAmount.value = row.orderAmount - row.paidAmount
  paymentRemark.value = ''
  paymentDialogVisible.value = true
}
  const handlePayment = row => {
    currentRecord.value = row;
    paymentAmount.value = row.orderAmount - row.paidAmount;
    paymentRemark.value = "";
    paymentDialogVisible.value = true;
  };
const handleShipping = (row) => {
  currentRecord.value = row
  shippingDate.value = ''
  logisticsCompany.value = ''
  trackingNo.value = ''
  shippingRemark.value = ''
  shippingDialogVisible.value = true
}
  const handleShipping = row => {
    currentRecord.value = row;
    shippingDate.value = "";
    logisticsCompany.value = "";
    trackingNo.value = "";
    shippingRemark.value = "";
    shippingDialogVisible.value = true;
  };
const handleDelete = (row) => {
  ElMessageBox.confirm('确认删除该记录吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  const handleDelete = row => {
    ElMessageBox.confirm("确认删除该记录吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
  }).then(() => {
    let ids = [row.id]
      let ids = [row.id];
    deletePaymentShipping(ids).then(res => {
      if(res.code === 200){
        ElMessage.success('删除成功')
        getList()
          ElMessage.success("删除成功");
          getList();
      }
    })
  })
}
      });
    });
  };
const savePayment = () => {
  currentRecord.value.paidAmount = Number(currentRecord.value.paidAmount) + paymentAmount.value
    currentRecord.value.paidAmount =
      Number(currentRecord.value.paidAmount) + paymentAmount.value;
  if(currentRecord.value.paidAmount == currentRecord.value.orderAmount){
    currentRecord.value.paymentStatus = '已付款'
      currentRecord.value.paymentStatus = "已付款";
  }else{
    currentRecord.value.paymentStatus = '部分付款'
      currentRecord.value.paymentStatus = "部分付款";
  }
  update(currentRecord.value).then(res => {
    if(res.code === 200){
      ElMessage.success('付款信息已保存')
      paymentDialogVisible.value = false
      getList()
        ElMessage.success("付款信息已保存");
        paymentDialogVisible.value = false;
        getList();
    }
  })
}
    });
  };
const saveShipping = () => {
  if (!shippingDate.value || !logisticsCompany.value || !trackingNo.value) {
    ElMessage.warning('请填写完整的发货信息')
    return
      ElMessage.warning("请填写完整的发货信息");
      return;
  }
  currentRecord.value.shippingStatus = '已发货'
    currentRecord.value.shippingStatus = "已发货";
  update(currentRecord.value).then(res => {
    if(res.code === 200){
      ElMessage.success('发货信息已保存')
      shippingDialogVisible.value = false
      getList()
        ElMessage.success("发货信息已保存");
        shippingDialogVisible.value = false;
        getList();
    }
  })
}
    });
  };
const handleSubmit = () => {
  formRef.value.validate((valid) => {
    formRef.value.validate(valid => {
    if (valid) {
      if (isEdit.value) {
        // 编辑
        update(form).then(res => {
          if(res.code === 200){
            ElMessage.success('编辑成功')
            getList()
              ElMessage.success("编辑成功");
              getList();
          }
        })
          });
      } else {
        // 新增
        add(form).then(res => {
          if(res.code === 200){
            ElMessage.success('新增成功')
            getList()
              ElMessage.success("新增成功");
              getList();
          }
        })
          });
      }
      dialogVisible.value = false
        dialogVisible.value = false;
    }
  })
}
    });
  };
const handleCurrentChange = (val) => {
  pagination.current = val.page
  pagination.size = val.limit
}
  const handleCurrentChange = val => {
    pagination.current = val.page;
    pagination.size = val.limit;
  };
</script>
<style scoped>
在上述文件截断后对比
src/views/salesManagement/salesQuotation/index.vue src/views/salesManagement/salespersonManagement/index.vue src/views/tool/gen/importTable.vue