合并河南鹤壁问题
1、客户往来没有合同金额
2、销售台账需要详情按钮查看
3、主生产计划,统一居左展示。把销售合同号移到前面展示而不是往后拉才可以看到
4、设备报修-只需要展示关键数据。新增一个详情按钮,其他数据在详情里查看
5、计量器台账-应该是叫编辑而不是查看
6、设备巡检tab页更名、表格无法拖拉问题
7、任务管理不需要巡检结果
8、 反馈登记-问题描述修改为客户诉求
已修改10个文件
2953 ■■■■ 文件已修改
src/components/Dialog/FormDialog.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/customerService/feedbackRegistration/components/formDia.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/customerService/feedbackRegistration/index.vue 825 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/index.vue 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/index.vue 630 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Modal/RepairModal.vue 332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/index.vue 506 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/productionPlan/index.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/receiptPaymentLedger/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 565 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Dialog/FormDialog.vue
@@ -55,7 +55,7 @@
})
// 详情模式不展示“确认”按钮,其它类型正常显示
const showConfirm = computed(() => props.operationType !== 'detail')
const showConfirm = computed(() => props.operationType !== 'detail' && props.operationType !== 'view')
const computedTitle = computed(() => {
  if (typeof props.title === 'function') {
src/views/customerService/feedbackRegistration/components/formDia.vue
@@ -63,10 +63,10 @@
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="问题描述:"
              <el-form-item label="客户诉求:"
                            prop="proDesc">
                <el-input v-model="form.proDesc"
                          placeholder="请输入问题描述" />
                          placeholder="请输入客户诉求" />
              </el-form-item>
            </el-col>
          </el-row>
src/views/customerService/feedbackRegistration/index.vue
@@ -1,13 +1,13 @@
<template>
  <div class="app-container">
    <div class="workorder-stats">
      <div
          v-for="(item, index) in statsList"
          :key="index"
          class="stat-card"
      >
        <div class="stat-icon" :style="{ backgroundColor: item.bgColor }">
          <el-icon :color="item.color" :size="20">
      <div v-for="(item, index) in statsList"
           :key="index"
           class="stat-card">
        <div class="stat-icon"
             :style="{ backgroundColor: item.bgColor }">
          <el-icon :color="item.color"
                   :size="20">
            <component :is="item.icon" />
          </el-icon>
        </div>
@@ -18,84 +18,64 @@
      </div>
    </div>
    <div class="search-wrapper">
      <el-form
          :model="searchForm"
          class="demo-form-inline"
      >
      <el-form :model="searchForm"
               class="demo-form-inline">
        <el-row :gutter="20">
          <el-col :span="4">
            <el-form-item>
              <el-input
                  v-model="searchForm.afterSalesServiceNo"
                  placeholder="请输入工单编号"
                  clearable
              />
              <el-input v-model="searchForm.afterSalesServiceNo"
                        placeholder="请输入工单编号"
                        clearable />
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item>
              <el-select
                  v-model="searchForm.status"
                  placeholder="请选择工单状态"
                  clearable
              >
                <el-option
                    v-for="dict in workOrderStatusOptions"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                />
              <el-select v-model="searchForm.status"
                         placeholder="请选择工单状态"
                         clearable>
                <el-option v-for="dict in workOrderStatusOptions"
                           :key="dict.value"
                           :label="dict.label"
                           :value="dict.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item>
              <el-select
                  v-model="searchForm.urgency"
                  placeholder="请选择紧急程度"
                  clearable
              >
                <el-option
                    v-for="dict in degreeOfUrgencyOptions"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                />
              <el-select v-model="searchForm.urgency"
                         placeholder="请选择紧急程度"
                         clearable>
                <el-option v-for="dict in degreeOfUrgencyOptions"
                           :key="dict.value"
                           :label="dict.label"
                           :value="dict.value" />
              </el-select>
            </el-form-item>
          </el-col>
           <el-col :span="4">
          <el-col :span="4">
            <el-form-item>
              <el-select
                  v-model="searchForm.serviceType"
                  placeholder="请选择售后类型"
                  clearable
              >
                <el-option
                    v-for="dict in classificationOptions"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                />
              <el-select v-model="searchForm.serviceType"
                         placeholder="请选择售后类型"
                         clearable>
                <el-option v-for="dict in classificationOptions"
                           :key="dict.value"
                           :label="dict.label"
                           :value="dict.value" />
              </el-select>
            </el-form-item>
          </el-col>
            <el-col :span="4">
              <el-form-item>
                <el-input
                    v-model="searchForm.orderNo"
                    placeholder="请输入销售单号"
                    clearable
                />
              </el-form-item>
            </el-col>
          <el-col :span="4">
            <el-form-item>
              <el-input v-model="searchForm.orderNo"
                        placeholder="请输入销售单号"
                        clearable />
            </el-form-item>
          </el-col>
          <!-- 按钮 -->
          <el-col :span="4">
            <el-form-item>
              <el-button type="primary" @click="handleQuery">
              <el-button type="primary"
                         @click="handleQuery">
                搜索
              </el-button>
              <el-button @click="handleReset">
@@ -107,310 +87,340 @@
      </el-form>
    </div>
    <div class="table_list">
      <div class="table_header" style="display: flex; justify-content: space-between; align-items: center;">
      <div class="table_header"
           style="display: flex; justify-content: space-between; align-items: center;">
        <div>
          <el-button type="primary" @click="openForm('add')">新增售后单</el-button>
          <el-button type="primary"
                     @click="openForm('add')">新增售后单</el-button>
        </div>
        <div>
          <el-button @click="handleOut">导出</el-button>
          <el-button type="danger" plain @click="handleDelete">删除</el-button>
          <el-button type="danger"
                     plain
                     @click="handleDelete">删除</el-button>
        </div>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :page="page"
          :height="tableHeight"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          :tableLoading="tableLoading"
          @pagination="pagination"
      ></PIMTable>
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :height="tableHeight"
                :isSelection="true"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"
                @pagination="pagination"></PIMTable>
    </div>
    <form-dia ref="formDia" @close="handleQuery"></form-dia>
    <form-dia ref="formDia"
              @close="handleQuery"></form-dia>
  </div>
</template>
<script setup>
import {onMounted, reactive, ref, toRefs, computed, getCurrentInstance, nextTick} from "vue";
import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue";
import {ElMessageBox} from "element-plus";
import {afterSalesServiceDelete, afterSalesServiceListPage, getSalesLedgerDetail} from "@/api/customerService/index.js";
import useUserStore from "@/store/modules/user.js";
const { proxy } = getCurrentInstance();
const userStore = useUserStore()
import { Document, FolderOpened, UserFilled } from "@element-plus/icons-vue"
import { markRaw } from 'vue'
  import {
    onMounted,
    reactive,
    ref,
    toRefs,
    computed,
    getCurrentInstance,
    nextTick,
  } from "vue";
  import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue";
  import { ElMessageBox } from "element-plus";
  import {
    afterSalesServiceDelete,
    afterSalesServiceListPage,
    getSalesLedgerDetail,
  } from "@/api/customerService/index.js";
  import useUserStore from "@/store/modules/user.js";
  const { proxy } = getCurrentInstance();
  const userStore = useUserStore();
  import { Document, FolderOpened, UserFilled } from "@element-plus/icons-vue";
  import { markRaw } from "vue";
const statsList = ref([
  {
    icon: markRaw(Document),
    count: 0,
    label: '全部工单',
    color: '#4080ff',
    bgColor: '#eaf2ff'
  },
  {
    icon: markRaw(FolderOpened),
    count: 0,
    label: '已处理',
    color: '#ff9a2e',
    bgColor: '#fff5e6'
  },
  {
    icon: markRaw(UserFilled),
    count: 0,
    label: '已完成',
    color: '#00b42a',
    bgColor: '#e6f7ed'
  },
])
const data = reactive({
  searchForm : {
    customerName: "",
    status: "",
    urgency: "",
    serviceType: "",
    reviewStatus: "",
    orderNo: "",
  }
});
const { searchForm } = toRefs(data);
const tableColumn = ref([
  {
    label: "工单编号",
    prop:"afterSalesServiceNo",
    width: 150,
    align: "center"
  },
  {
    label: "销售单号",
    prop:"salesContractNo",
    width: 150,
    align: "center"
  },
  {
    label: "处理状态",
    prop: "status",
    dataType: "tag",
    formatData: (params) => {
      if (params) {
        let part = String(params)
        const item = workOrderStatusOptions.value.find(item => item.value === part);
        return item?.label || params;
      }
      return null;
  const statsList = ref([
    {
      icon: markRaw(Document),
      count: 0,
      label: "全部工单",
      color: "#4080ff",
      bgColor: "#eaf2ff",
    },
    formatType: (params) => {
      if (params === 1) {
        return "danger";
      } else if (params === 2) {
        return "success";
      } else {
    {
      icon: markRaw(FolderOpened),
      count: 0,
      label: "已处理",
      color: "#ff9a2e",
      bgColor: "#fff5e6",
    },
    {
      icon: markRaw(UserFilled),
      count: 0,
      label: "已完成",
      color: "#00b42a",
      bgColor: "#e6f7ed",
    },
  ]);
  const data = reactive({
    searchForm: {
      customerName: "",
      status: "",
      urgency: "",
      serviceType: "",
      reviewStatus: "",
      orderNo: "",
    },
  });
  const { searchForm } = toRefs(data);
  const tableColumn = ref([
    {
      label: "工单编号",
      prop: "afterSalesServiceNo",
      width: 150,
      align: "center",
    },
    {
      label: "销售单号",
      prop: "salesContractNo",
      width: 150,
      align: "center",
    },
    {
      label: "处理状态",
      prop: "status",
      dataType: "tag",
      formatData: params => {
        if (params) {
          let part = String(params);
          const item = workOrderStatusOptions.value.find(
            item => item.value === part
          );
          return item?.label || params;
        }
        return null;
      }
    },
    align: "center"
  },
  {
    label: "反馈日期",
    prop: "feedbackDate",
    width: 150,
    align: "center"
  },
  {
    label: "登记人",
    prop: "checkNickName",
    align: "center"
  },
  {
    label: "紧急程度",
    prop: "urgency",
    // 根据degreeOfUrgencyOptions字典去自动匹配
    formatData: (params) => {
      if (params) {
        const item = degreeOfUrgencyOptions.value.find(item => item.value === params);
        return item?.label || params;
      }
      return null;
    },
    align: "center"
  },
  {
    label: "售后类型",
    prop: "serviceType",
    // 根据classificationOptions字典去自动匹配
    formatData: (params) => {
      if (params) {
        const item = classificationOptions.value.find(item => item.value === params);
        return item?.label || params;
      }
      return null;
    },
    align: "center"
  },
  {
    label: "问题描述",
    prop: "proDesc",
    width:300,
  },
  {
    label: "关联部门",
    prop: "deptName",
    width: 200,
    align: "center"
  },
  {
    dataType: "action",
    label: "操作",
    fixed: 'right',
    operation: [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          console.log(row)
          openForm("edit", row);
        },
        disabled: (row) => {
          return row.status !== 1
      },
      formatType: params => {
        if (params === 1) {
          return "danger";
        } else if (params === 2) {
          return "success";
        } else {
          return null;
        }
      },
    ],
    align: "center"
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
});
const selectedRows = ref([]);
const tableHeight = computed(() => "calc(100% -80px)");
const handleReset = () => {
  Object.keys(searchForm.value).forEach(key => {
    searchForm.value[key] = ""
  })
  page.current = 1;
  getList();
}
// 表格选择数据
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
const formDia = ref()
// 字典获取
/*
post_sale_waiting_list 新增的售后分类
degree_of_urgency 新增的紧急程度
work_order_status 主页的工单状态
review_status 首页的审核状态
*/
const { post_sale_waiting_list, degree_of_urgency, work_order_status, review_status } = proxy.useDict(
  "post_sale_waiting_list",
  "degree_of_urgency",
  "work_order_status",
  "review_status"
);
const classificationOptions = computed(() => post_sale_waiting_list?.value || []);
const degreeOfUrgencyOptions = computed(() => degree_of_urgency?.value || []);
const workOrderStatusOptions = computed(() => work_order_status?.value || []);
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const getList = () => {
  tableLoading.value = true;
  getSalesLedgerDetails()
  afterSalesServiceListPage({ ...searchForm.value, ...page }).then((res) => {
    tableLoading.value = false;
    tableData.value = res.data.records;
    page.total = res.data.total;
      align: "center",
    },
    {
      label: "反馈日期",
      prop: "feedbackDate",
      width: 150,
      align: "center",
    },
    {
      label: "登记人",
      prop: "checkNickName",
      align: "center",
    },
    {
      label: "紧急程度",
      prop: "urgency",
      // 根据degreeOfUrgencyOptions字典去自动匹配
      formatData: params => {
        if (params) {
          const item = degreeOfUrgencyOptions.value.find(
            item => item.value === params
          );
          return item?.label || params;
        }
        return null;
      },
      align: "center",
    },
    {
      label: "售后类型",
      prop: "serviceType",
      // 根据classificationOptions字典去自动匹配
      formatData: params => {
        if (params) {
          const item = classificationOptions.value.find(
            item => item.value === params
          );
          return item?.label || params;
        }
        return null;
      },
      align: "center",
    },
    {
      label: "客户诉求",
      prop: "proDesc",
      width: 300,
    },
    {
      label: "关联部门",
      prop: "deptName",
      width: 200,
      align: "center",
    },
    {
      dataType: "action",
      label: "操作",
      fixed: "right",
      operation: [
        {
          name: "编辑",
          type: "text",
          clickFun: row => {
            console.log(row);
            openForm("edit", row);
          },
          disabled: row => {
            return row.status !== 1;
          },
        },
      ],
      align: "center",
    },
  ]);
  const tableData = ref([]);
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
};
  const selectedRows = ref([]);
  const tableHeight = computed(() => "calc(100% -80px)");
// 打开弹框
const openForm = (type, row) => {
  nextTick(() => {
    formDia.value?.openDialog(type, row)
  })
};
  const handleReset = () => {
    Object.keys(searchForm.value).forEach(key => {
      searchForm.value[key] = "";
    });
    page.current = 1;
    getList();
  };
  // 表格选择数据
  const handleSelectionChange = selection => {
    selectedRows.value = selection;
  };
  const formDia = ref();
function handleDelete() {
  let ids = [];
  if (selectedRows.value.length > 0) {
    // 检查是否有他人维护的数据
    const unauthorizedData = selectedRows.value.filter(item => item.checkUserId !== userStore.id);
    if (unauthorizedData.length > 0) {
      proxy.$modal.msgWarning("不可删除他人维护的数据");
  // 字典获取
  /*
  post_sale_waiting_list 新增的售后分类
  degree_of_urgency 新增的紧急程度
  work_order_status 主页的工单状态
  review_status 首页的审核状态
  */
  const {
    post_sale_waiting_list,
    degree_of_urgency,
    work_order_status,
    review_status,
  } = proxy.useDict(
    "post_sale_waiting_list",
    "degree_of_urgency",
    "work_order_status",
    "review_status"
  );
  const classificationOptions = computed(
    () => post_sale_waiting_list?.value || []
  );
  const degreeOfUrgencyOptions = computed(() => degree_of_urgency?.value || []);
  const workOrderStatusOptions = computed(() => work_order_status?.value || []);
  // 查询列表
  /** 搜索按钮操作 */
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const getList = () => {
    tableLoading.value = true;
    getSalesLedgerDetails();
    afterSalesServiceListPage({ ...searchForm.value, ...page }).then(res => {
      tableLoading.value = false;
      tableData.value = res.data.records;
      page.total = res.data.total;
    });
  };
  // 打开弹框
  const openForm = (type, row) => {
    nextTick(() => {
      formDia.value?.openDialog(type, row);
    });
  };
  function handleDelete() {
    let ids = [];
    if (selectedRows.value.length > 0) {
      // 检查是否有他人维护的数据
      const unauthorizedData = selectedRows.value.filter(
        item => item.checkUserId !== userStore.id
      );
      if (unauthorizedData.length > 0) {
        proxy.$modal.msgWarning("不可删除他人维护的数据");
        return;
      }
      ids = selectedRows.value.map(item => item.id);
    } else {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        tableLoading.value = true;
        afterSalesServiceDelete(ids)
            .then(() => {
              proxy.$modal.msgSuccess("删除成功");
              getList();
            })
            .finally(() => {
              tableLoading.value = false;
            });
          .then(() => {
            proxy.$modal.msgSuccess("删除成功");
            getList();
          })
          .finally(() => {
            tableLoading.value = false;
          });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
  }
// 导出
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
  // 导出
  const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        proxy.download("/afterSalesService/export", {}, "反馈登记.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
  };
const getStatsCountByStatus = (list, status) => {
  if (!Array.isArray(list)) return 0;
  return list.find((item) => item?.status === status)?.count || 0;
};
  const getStatsCountByStatus = (list, status) => {
    if (!Array.isArray(list)) return 0;
    return list.find(item => item?.status === status)?.count || 0;
  };
  // 获取统计数据并刷新顶部卡片
  const getSalesLedgerDetails = () => {
    getSalesLedgerDetail({}).then((res) => {
    getSalesLedgerDetail({}).then(res => {
      if (res.code === 200) {
        const statsData = Array.isArray(res.data) ? res.data : [];
        statsList.value[0].count = getStatsCountByStatus(statsData, 3);
@@ -418,99 +428,96 @@
        statsList.value[2].count = getStatsCountByStatus(statsData, 1);
      }
    });
  }
  };
onMounted(() => {
  getList();
});
  onMounted(() => {
    getList();
  });
</script>
<style scoped lang="scss">
.search-wrapper {
  background: white;
  padding: 1rem 1rem 0 1rem;
  border: 8px;
  border-radius: 16px;
}
  .search-wrapper {
    background: white;
    padding: 1rem 1rem 0 1rem;
    border: 8px;
    border-radius: 16px;
  }
.expand-btn {
  width: 100%;
  padding: 20px; /* 上下左右各20px,点击这个范围都能触发事件 */
  cursor: pointer; /* 鼠标悬浮显示手型,提升体验 */
  text-align: center;
}
  .expand-btn {
    width: 100%;
    padding: 20px; /* 上下左右各20px,点击这个范围都能触发事件 */
    cursor: pointer; /* 鼠标悬浮显示手型,提升体验 */
    text-align: center;
  }
.workorder-stats {
  display: flex;
  gap: 16px;
  padding-bottom:1rem;
  border-radius: 8px;
}
  .workorder-stats {
    display: flex;
    gap: 16px;
    padding-bottom: 1rem;
    border-radius: 8px;
  }
.stat-card {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 20px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
}
  .stat-card {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 20px;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
  }
.stat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 8px;
}
  .stat-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 8px;
  }
.stat-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
  .stat-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
.stat-number {
  font-size: 24px;
  font-weight: 600;
  color: #303133;
  line-height: 1;
}
  .stat-number {
    font-size: 24px;
    font-weight: 600;
    color: #303133;
    line-height: 1;
  }
.stat-label {
  font-size: 14px;
  color: #909399;
  line-height: 1;
}
.table_header{
  padding-bottom: 10px;
}
  .stat-label {
    font-size: 14px;
    color: #909399;
    line-height: 1;
  }
  .table_header {
    padding-bottom: 10px;
  }
.table_list {
  height: calc(100vh - 380px);
  background: #fff;
  margin-top: 20px;
  display: flex;
  flex-direction: column;
}
  .table_list {
    height: calc(100vh - 380px);
    background: #fff;
    margin-top: 20px;
    display: flex;
    flex-direction: column;
  }
:deep(.table_list .pagination-container) {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  margin-top: auto;
  padding: 12px 0 0;
}
  :deep(.table_list .pagination-container) {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    margin-top: auto;
    padding: 12px 0 0;
  }
:deep(.table_list .el-pagination) {
  flex-wrap: nowrap;
  justify-content: flex-end;
  width: 100%;
}
  :deep(.table_list .el-pagination) {
    flex-wrap: nowrap;
    justify-content: flex-end;
    width: 100%;
  }
</style>
src/views/equipmentManagement/inspectionManagement/index.vue
@@ -52,7 +52,8 @@
                  total: total,
                  layout: 'total, sizes, prev, pager, next, jumper'
                }"
                  :table-style="{ width: '100%', height: 'calc(100vh - 23em)' }">
                  height="calc(100vh - 23em)"
                  :table-style="{ width: '100%' }">
          <template #inspector="{ row }">
            <div class="person-tags">
              <!-- 调试信息,上线时删除 -->
@@ -121,8 +122,8 @@
  // 单选框配置
  const activeRadio = ref("taskManage");
  const radios = reactive([
    { name: "taskManage", label: "定时任务管理" },
    { name: "task", label: "定时任务记录" },
    { name: "taskManage", label: "巡检任务" },
    { name: "task", label: "巡检记录" },
  ]);
  // 表格数据
@@ -137,10 +138,10 @@
  // 列配置
  const columns = ref([
    { prop: "taskName", label: "巡检任务名称", minWidth: 160 },
    { prop: "inspectionProject", label: "巡检项目", minWidth: 150 },
    { prop: "remarks", label: "备注", minWidth: 150 },
    { prop: "inspector", label: "执行巡检人", minWidth: 150, slot: "inspector" },
    { prop: "taskName", label: "巡检任务名称", minWidth: 200 },
    { prop: "inspectionProject", label: "巡检项目", minWidth: 180 },
    { prop: "remarks", label: "备注", minWidth: 180 },
    { prop: "inspector", label: "执行巡检人", minWidth: 180, slot: "inspector" },
    {
      prop: "isEnabled",
      label: "是否启用",
@@ -151,13 +152,7 @@
    {
      prop: "frequencyType",
      label: "频次",
      minWidth: 150,
      // formatter: (_, __, val) => ({
      //   DAILY: "每日",
      //   WEEKLY: "每周",
      //   MONTHLY: "每月",
      //   QUARTERLY: "季度"
      // }[val] || "")
      minWidth: 120,
      formatData: params => {
        return params === "DAILY"
          ? "每日"
@@ -173,7 +168,7 @@
    {
      prop: "frequencyDetail",
      label: "开始日期与时间",
      minWidth: 150,
      minWidth: 200,
      formatter: (row, column, cellValue) => {
        // 先判断是否是字符串
        if (typeof cellValue !== "string") return "";
@@ -194,11 +189,11 @@
        );
      },
    },
    { prop: "registrant", label: "登记人", minWidth: 100 },
    { prop: "registrant", label: "登记人", minWidth: 120 },
    {
      prop: "createTime",
      label: "登记日期",
      minWidth: 100,
      minWidth: 180,
      formatData: cell => {
        if (!cell) return "-";
        try {
@@ -208,19 +203,19 @@
        }
      },
    },
    {
      prop: "inspectionResult",
      label: "巡检结果",
      minWidth: 100,
      dataType: "tag",
      formatData: val => {
        return val == 1 ? "正常" : "异常";
      },
      formatType: val => {
        return val == 1 ? "success" : "danger";
      },
    },
    { prop: "abnormalDescription", label: "异常描述", minWidth: 100 },
    // {
    //   prop: "inspectionResult",
    //   label: "巡检结果",
    //   minWidth: 100,
    //   dataType: "tag",
    //   formatData: val => {
    //     return val == 1 ? "正常" : "异常";
    //   },
    //   formatType: val => {
    //     return val == 1 ? "success" : "danger";
    //   },
    // },
    { prop: "abnormalDescription", label: "异常描述", minWidth: 150 },
  ]);
  // 操作列配置
@@ -231,7 +226,7 @@
      label: "操作",
      width: operations.length > 1 ? 180 : 130,
      fixed: "right",
            align: 'center',
      align: "center",
      dataType: "action",
      operation: operations
        .map(op => {
@@ -279,7 +274,7 @@
      operationsArr.value = ["edit"];
    } else if (value === "task") {
      const operationColumn = getOperationColumn(["upload", "viewFile"]);
      // 定时任务记录不展示"是否启用"列
      // 巡检记录不展示"是否启用"列
      const taskColumns = columns.value.filter(col => col.prop !== "isEnabled");
      tableColumns.value = [
        ...taskColumns,
@@ -422,11 +417,11 @@
      .then(() => {
        // 根据当前选中的标签页调用不同的导出接口
        if (activeRadio.value === "taskManage") {
          // 定时任务管理
          proxy.download("/timingTask/export", {}, "定时任务管理.xlsx");
          // 巡检任务
          proxy.download("/timingTask/export", {}, "巡检任务.xlsx");
        } else if (activeRadio.value === "task") {
          // 定时任务记录
          proxy.download("/inspectionTask/export", {}, "定时任务记录.xlsx");
          // 巡检记录
          proxy.download("/inspectionTask/export", {}, "巡检记录.xlsx");
        }
      })
      .catch(() => {
src/views/equipmentManagement/measurementEquipment/index.vue
@@ -1,320 +1,354 @@
<template>
    <div class="app-container">
        <div class="search_form mb20">
            <div>
                <span class="search_title">录入日期:</span>
                <el-date-picker
                    v-model="searchForm.recordDate"
                    value-format="YYYY-MM-DD"
                    format="YYYY-MM-DD"
                    type="date"
                    placeholder="请选择"
                    clearable
                    style="width: 160px"
                    @change="handleQuery"
                />
                <span class="search_title ml10">计量器具编号:</span>
                <el-input v-model="searchForm.code" placeholder="请输入编号" clearable style="width: 240px" @change="handleQuery"/>
                <span class="search_title ml10">状态:</span>
                <el-select v-model="searchForm.status" placeholder="请选择状态" @change="handleQuery" style="width: 160px" clearable>
                    <el-option label="有效" :value="1"></el-option>
                    <el-option label="逾期" :value="2"></el-option>
                </el-select>
                <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
                >搜索</el-button
                >
                <el-button @click="handleReset" style="margin-left: 10px">重置</el-button>
            </div>
            <div>
                <el-button type="primary" @click="openForm('add')">新增计量器具</el-button>
                <el-button type="danger" plain @click="handleDelete">删除</el-button>
                <el-button @click="handleOut">导出</el-button>
            </div>
        </div>
        <div class="table_list">
            <PIMTable
                rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :isSelection="true"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"
                @pagination="pagination"
        :dbRowClick="dbRowClick"
        :rowClassName="rowClassName"
            ></PIMTable>
        </div>
        <form-dia ref="formDia" @close="handleQuery"></form-dia>
        <calibration-dia ref="calibrationDia" @close="handleQuery"></calibration-dia>
  <div class="app-container">
    <div class="search_form mb20">
      <div>
        <span class="search_title">录入日期:</span>
        <el-date-picker v-model="searchForm.recordDate"
                        value-format="YYYY-MM-DD"
                        format="YYYY-MM-DD"
                        type="date"
                        placeholder="请选择"
                        clearable
                        style="width: 160px"
                        @change="handleQuery" />
        <span class="search_title ml10">计量器具编号:</span>
        <el-input v-model="searchForm.code"
                  placeholder="请输入编号"
                  clearable
                  style="width: 240px"
                  @change="handleQuery" />
        <span class="search_title ml10">状态:</span>
        <el-select v-model="searchForm.status"
                   placeholder="请选择状态"
                   @change="handleQuery"
                   style="width: 160px"
                   clearable>
          <el-option label="有效"
                     :value="1"></el-option>
          <el-option label="逾期"
                     :value="2"></el-option>
        </el-select>
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">搜索</el-button>
        <el-button @click="handleReset"
                   style="margin-left: 10px">重置</el-button>
      </div>
      <div>
        <el-button type="primary"
                   @click="openForm('add')">新增计量器具</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDelete">删除</el-button>
        <el-button @click="handleOut">导出</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :isSelection="true"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"
                @pagination="pagination"
                :dbRowClick="dbRowClick"
                :rowClassName="rowClassName"></PIMTable>
    </div>
    <form-dia ref="formDia"
              @close="handleQuery"></form-dia>
    <calibration-dia ref="calibrationDia"
                     @close="handleQuery"></calibration-dia>
    <files-dia ref="filesDia"></files-dia>
    <rowClickDataForm ref="rowClickData"></rowClickDataForm>
    </div>
  </div>
</template>
<script setup>
import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
import FormDia from "@/views/equipmentManagement/measurementEquipment/components/formDia.vue";
import {ElMessageBox} from "element-plus";
import useUserStore from "@/store/modules/user.js";
import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue";
import {
  measuringInstrumentDelete,
  measuringInstrumentListPage,
} from "@/api/equipmentManagement/measurementEquipment.js";
import FilesDia from "./filesDia.vue";
import rowClickDataForm from "./components/rowClickData.vue"
const { proxy } = getCurrentInstance();
const userStore = useUserStore()
  import {
    onMounted,
    ref,
    reactive,
    toRefs,
    getCurrentInstance,
    nextTick,
  } from "vue";
  import FormDia from "@/views/equipmentManagement/measurementEquipment/components/formDia.vue";
  import { ElMessageBox } from "element-plus";
  import useUserStore from "@/store/modules/user.js";
  import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue";
  import {
    measuringInstrumentDelete,
    measuringInstrumentListPage,
  } from "@/api/equipmentManagement/measurementEquipment.js";
  import FilesDia from "./filesDia.vue";
  import rowClickDataForm from "./components/rowClickData.vue";
  const { proxy } = getCurrentInstance();
  const userStore = useUserStore();
const data = reactive({
    searchForm: {
        recordDate: "",
        code: "",
        status: "",
    },
});
const { searchForm } = toRefs(data);
  const data = reactive({
    searchForm: {
      recordDate: "",
      code: "",
      status: "",
    },
  });
  const { searchForm } = toRefs(data);
const tableColumn = ref([
    {
        label: "出厂编号",
        prop: "code",
    minWidth:150,
    align:"center"
    },
  {
    label: "计量器具名称",
    prop: "name",
    width: '160px',
    align: "center",
  },
    {
        label: "检定单位",
        prop: "unit",
        width: 200,
    align:"center"
    },
    {
        label: "证书编号",
        prop: "model",
        width:200,
    align:"center"
    },
    {
        label: "最新鉴定日期",
        prop: "mostDate",
        width: 130,
    align:"center"
    },
    {
        label: "录入人",
        prop: "userName",
        width: 130,
    align:"center"
    },
    {
        label: "录入日期",
        prop: "recordDate",
    align:"center",
    minWidth: 130
    },
    {
        label: "有效日期",
        prop: "valid",
        width: 130,
    align:"center"
    },
  {
    label: "状态",
    prop: "status",
    width: 130,
    align: "center",
    formatData: (params) => {
      if (params === 1) {
        return "有效";
      } else if (params === 2) {
        return "逾期";
      } else {
        return null;
      }
    }
  },
    {
        dataType: "action",
        label: "操作",
        align: "center",
        width: '130',
        fixed: 'right',
        operation: [
      {
          name: "附件",
          type: "text",
          clickFun: (row) => {
          openFilesFormDia(row);
          },
  const tableColumn = ref([
    {
      label: "出厂编号",
      prop: "code",
      minWidth: 150,
      align: "center",
    },
    {
      label: "计量器具名称",
      prop: "name",
      width: "160px",
      align: "center",
    },
    {
      label: "检定单位",
      prop: "unit",
      width: 200,
      align: "center",
    },
    {
      label: "证书编号",
      prop: "model",
      width: 200,
      align: "center",
    },
    {
      label: "最新鉴定日期",
      prop: "mostDate",
      width: 130,
      align: "center",
    },
    {
      label: "录入人",
      prop: "userName",
      width: 130,
      align: "center",
    },
    {
      label: "录入日期",
      prop: "recordDate",
      align: "center",
      minWidth: 130,
    },
    {
      label: "有效日期",
      prop: "valid",
      width: 130,
      align: "center",
    },
    {
      label: "状态",
      prop: "status",
      width: 130,
      align: "center",
      formatData: params => {
        if (params === 1) {
          return "有效";
        } else if (params === 2) {
          return "逾期";
        } else {
          return null;
        }
      },
            {
                name: "查看",
                type: "text",
                clickFun: (row) => {
                    openCalibrationDia("verifying", row);
                },
            },
        ],
    },
]);
const tableData = ref([]);
const tableLoading = ref(false);
const rowClickData = ref([])
const filesDia = ref()
const page = reactive({
    current: 1,
    size: 100,
    total: 0,
});
const selectedRows = ref([]);
    },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      width: "130",
      fixed: "right",
      operation: [
        {
          name: "附件",
          type: "text",
          clickFun: row => {
            openFilesFormDia(row);
          },
        },
        {
          name: "编辑",
          type: "text",
          clickFun: row => {
            openCalibrationDia("verifying", row);
          },
        },
      ],
    },
  ]);
  const tableData = ref([]);
  const tableLoading = ref(false);
  const rowClickData = ref([]);
  const filesDia = ref();
  const page = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const selectedRows = ref([]);
// 打开附件弹框
const openFilesFormDia = (row) => {
    filesDia.value?.openDialog(row,'measuring_instrument_ledger')
};
  // 打开附件弹框
  const openFilesFormDia = row => {
    filesDia.value?.openDialog(row, "measuring_instrument_ledger");
  };
const dbRowClick = (row)=>{
  rowClickData.value?.openDialog(row)
}
  const dbRowClick = row => {
    rowClickData.value?.openDialog(row);
  };
// 行样式:快到期(7天内)或逾期标红
const rowClassName = ({ row }) => {
  console.log('rowClassName called:', row);
  // valid 是有效天数,mostDate 是最新检定日期
  if (row.valid && row.mostDate) {
    const mostDate = new Date(row.mostDate);
    // 计算到期日期 = 检定日期 + 有效天数
    const validDays = parseInt(row.valid) || 0;
    const expireDate = new Date(mostDate);
    expireDate.setDate(expireDate.getDate() + validDays);
    const now = new Date();
    const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24));
    console.log('row:', row.code, 'validDays:', validDays, 'expireDate:', expireDate, 'diffDays:', diffDays);
    // 7天内到期或已逾期都标红
    if (diffDays <= 7) {
      console.log('return warning-row');
      return 'warning-row';
  // 行样式:快到期(7天内)或逾期标红
  const rowClassName = ({ row }) => {
    console.log("rowClassName called:", row);
    // valid 是有效天数,mostDate 是最新检定日期
    if (row.valid && row.mostDate) {
      const mostDate = new Date(row.mostDate);
      // 计算到期日期 = 检定日期 + 有效天数
      const validDays = parseInt(row.valid) || 0;
      const expireDate = new Date(mostDate);
      expireDate.setDate(expireDate.getDate() + validDays);
      const now = new Date();
      const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24));
      console.log(
        "row:",
        row.code,
        "validDays:",
        validDays,
        "expireDate:",
        expireDate,
        "diffDays:",
        diffDays
      );
      // 7天内到期或已逾期都标红
      if (diffDays <= 7) {
        console.log("return warning-row");
        return "warning-row";
      }
    } else {
      console.log("row missing valid or mostDate:", row.valid, row.mostDate);
    }
  } else {
    console.log('row missing valid or mostDate:', row.valid, row.mostDate);
  }
  return '';
}
    return "";
  };
// 表格选择数据
const handleSelectionChange = (selection) => {
    selectedRows.value = selection;
};
const formDia = ref()
const calibrationDia = ref()
  // 表格选择数据
  const handleSelectionChange = selection => {
    selectedRows.value = selection;
  };
  const formDia = ref();
  const calibrationDia = ref();
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
    page.current = 1;
    getList();
};
  // 查询列表
  /** 搜索按钮操作 */
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
// 重置搜索条件
const handleReset = () => {
    searchForm.value.recordDate = "";
    searchForm.value.code = "";
    searchForm.value.status = "";
    page.current = 1;
    getList();
};
const pagination = (obj) => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
};
const getList = () => {
    tableLoading.value = true;
    measuringInstrumentListPage({ ...searchForm.value, ...page }).then((res) => {
        tableLoading.value = false;
        tableData.value = res.data.records;
        page.total = res.data.total;
    }).catch((err) => {
        tableLoading.value = false;
    })
};
  // 重置搜索条件
  const handleReset = () => {
    searchForm.value.recordDate = "";
    searchForm.value.code = "";
    searchForm.value.status = "";
    page.current = 1;
    getList();
  };
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const getList = () => {
    tableLoading.value = true;
    measuringInstrumentListPage({ ...searchForm.value, ...page })
      .then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records;
        page.total = res.data.total;
      })
      .catch(err => {
        tableLoading.value = false;
      });
  };
// 打开弹框
const openForm = (type, row) => {
    nextTick(() => {
        formDia.value?.openDialog(type, row)
    })
};
// 打开检定校准弹框
const openCalibrationDia = (type, row) => {
    nextTick(() => {
        calibrationDia.value?.openDialog(type, row)
    })
}
  // 打开弹框
  const openForm = (type, row) => {
    nextTick(() => {
      formDia.value?.openDialog(type, row);
    });
  };
  // 打开检定校准弹框
  const openCalibrationDia = (type, row) => {
    nextTick(() => {
      calibrationDia.value?.openDialog(type, row);
    });
  };
const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
        ids = selectedRows.value.map((item) => item.id);
    } else {
        proxy.$modal.msgWarning("请选择数据");
        return;
    }
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => {
            tableLoading.value = true;
            measuringInstrumentDelete(ids)
                .then((res) => {
                    proxy.$modal.msgSuccess("删除成功");
                    getList();
                })
                .finally(() => {
                    tableLoading.value = false;
                });
        })
        .catch(() => {
            proxy.$modal.msg("已取消");
        });
};
// 导出
const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => {
            proxy.download("/measuringInstrumentLedger/export", {}, "计量器具台账.xlsx");
        })
        .catch(() => {
            proxy.$modal.msg("已取消");
        });
};
onMounted(() => {
    getList();
});
  const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
      ids = selectedRows.value.map(item => item.id);
    } else {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        tableLoading.value = true;
        measuringInstrumentDelete(ids)
          .then(res => {
            proxy.$modal.msgSuccess("删除成功");
            getList();
          })
          .finally(() => {
            tableLoading.value = false;
          });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  // 导出
  const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        proxy.download(
          "/measuringInstrumentLedger/export",
          {},
          "计量器具台账.xlsx"
        );
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  onMounted(() => {
    getList();
  });
</script>
<style scoped>
:deep(.el-table .warning-row) {
  background-color: #fef0f0 !important;
}
:deep(.el-table .warning-row:hover > td) {
  background-color: #f9d5d5 !important;
}
:deep(.el-table .el-table__body tr.warning-row td) {
  background-color: #fef0f0 !important;
}
  :deep(.el-table .warning-row) {
    background-color: #fef0f0 !important;
  }
  :deep(.el-table .warning-row:hover > td) {
    background-color: #f9d5d5 !important;
  }
  :deep(.el-table .el-table__body tr.warning-row td) {
    background-color: #fef0f0 !important;
  }
</style>
src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -1,111 +1,126 @@
<template>
  <FormDialog
    v-model="visible"
    :title="id ? '编辑设备报修' : '新增设备报修'"
    width="800px"
    @confirm="sendForm"
    @cancel="handleCancel"
    @close="handleClose"
  >
    <el-form :model="form" label-width="100px">
  <FormDialog v-model="visible"
              :title="computedTitle"
              :operation-type="operationType"
              width="800px"
              @confirm="sendForm"
              @cancel="handleCancel"
              @close="handleClose">
    <el-form :model="form"
             label-width="100px">
      <el-row>
        <el-col :span="12">
          <el-form-item label="设备名称">
            <el-select v-model="form.deviceLedgerId" @change="setDeviceModel" filterable>
              <el-option
                v-for="(item, index) in deviceOptions"
                :key="index"
                :label="item.deviceName"
                :value="item.id"
              ></el-option>
            <el-select v-model="form.deviceLedgerId"
                       @change="setDeviceModel"
                       filterable
                       :disabled="operationType === 'view'">
              <el-option v-for="(item, index) in deviceOptions"
                         :key="index"
                         :label="item.deviceName"
                         :value="item.id"></el-option>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="规格型号">
            <el-input
              v-model="form.deviceModel"
              placeholder="请输入规格型号"
              disabled
            />
            <el-input v-model="form.deviceModel"
                      placeholder="请输入规格型号"
                      disabled />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="报修日期">
            <el-date-picker
              v-model="form.repairTime"
              placeholder="请选择报修日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              type="date"
              clearable
              style="width: 100%"
            />
            <el-date-picker v-model="form.repairTime"
                            placeholder="请选择报修日期"
                            format="YYYY-MM-DD"
                            value-format="YYYY-MM-DD"
                            type="date"
                            clearable
                            style="width: 100%"
                            :disabled="operationType === 'view'" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="报修人">
            <el-input v-model="form.repairName" placeholder="请输入报修人" />
            <el-input v-model="form.repairName"
                      placeholder="请输入报修人"
                      :disabled="operationType === 'view'" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="报修报修项目">
            <el-input v-model="form.machineryCategory" placeholder="请输入报修报修项目" />
            <el-input v-model="form.machineryCategory"
                      placeholder="请输入报修报修项目"
                      :disabled="operationType === 'view'" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="维修人">
            <el-input v-model="form.maintenanceName" placeholder="请输入维修人姓名" />
            <el-input v-model="form.maintenanceName"
                      placeholder="请输入维修人姓名"
                      :disabled="operationType === 'view'" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row v-if="id">
        <el-col :span="12">
          <el-form-item label="报修状态">
            <el-select v-model="form.status" disabled>
              <el-option label="待维修" :value="0"></el-option>
              <el-option label="已验收" :value="1"></el-option>
              <el-option label="失败" :value="2"></el-option>
            <el-select v-model="form.status"
                       disabled>
              <el-option label="待维修"
                         :value="0"></el-option>
              <el-option label="已验收"
                         :value="1"></el-option>
              <el-option label="失败"
                         :value="2"></el-option>
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
      <!-- 验收信息展示 -->
      <el-row v-if="id && form.status === 1">
      <el-row v-if="id && (form.status === 1 || form.status === 3)">
        <el-col :span="12">
          <el-form-item label="验收人">
            <el-input v-model="form.acceptanceName" disabled />
            <el-input v-model="form.acceptanceName"
                      disabled />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="验收时间">
            <el-input v-model="form.acceptanceTime" disabled />
            <el-input v-model="form.acceptanceTime"
                      disabled />
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="验收备注">
            <el-input v-model="form.acceptanceRemark" type="textarea" :rows="2" disabled />
            <el-input v-model="form.acceptanceRemark"
                      type="textarea"
                      :rows="2"
                      disabled />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item label="故障现象">
            <el-input
              v-model="form.remark"
              :rows="2"
              type="textarea"
              placeholder="请输入故障现象"
            />
            <el-input v-model="form.remark"
                      :rows="2"
                      type="textarea"
                      placeholder="请输入故障现象"
                      :disabled="operationType === 'view'" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
      <el-row v-if="operationType !== 'view'"
              :gutter="30">
        <el-col :span="24">
          <el-form-item label="附件" prop="attachmentIds">
            <FileUpload v-model:file-list="form.storageBlobDTOs" />
          <el-form-item label="附件"
                        prop="attachmentIds">
            <FileUpload v-model:file-list="form.storageBlobDTOs"
                        :disabled="operationType === 'view'" />
          </el-form-item>
        </el-col>
      </el-row>
@@ -114,119 +129,140 @@
</template>
<script setup>
import FormDialog from "@/components/Dialog/FormDialog.vue";
import FileUpload from "@/components/AttachmentUpload/file/index.vue";
import {
  addRepair,
  editRepair,
  getRepairById,
} from "@/api/equipmentManagement/repair";
import { ElMessage } from "element-plus";
import dayjs from "dayjs";
import useFormData from "@/hooks/useFormData";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
import useUserStore from "@/store/modules/user";
  import FormDialog from "@/components/Dialog/FormDialog.vue";
  import FileUpload from "@/components/AttachmentUpload/file/index.vue";
  import {
    addRepair,
    editRepair,
    getRepairById,
  } from "@/api/equipmentManagement/repair";
  import { ElMessage } from "element-plus";
  import dayjs from "dayjs";
  import useFormData from "@/hooks/useFormData";
  import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
  import useUserStore from "@/store/modules/user";
defineOptions({
  name: "设备报修弹窗",
});
  defineOptions({
    name: "设备报修弹窗",
  });
const emits = defineEmits(["ok"]);
  const emits = defineEmits(["ok"]);
const id = ref();
const visible = ref(false);
const loading = ref(false);
  const id = ref();
  const visible = ref(false);
  const loading = ref(false);
  const operationType = ref(""); // add, edit, view
const userStore = useUserStore();
const deviceOptions = ref([]);
const fileList = ref([]);
  const computedTitle = computed(() => {
    if (operationType.value === "add") return "新增设备报修";
    if (operationType.value === "edit") return "编辑设备报修";
    if (operationType.value === "view") return "设备报修详情";
    return "";
  });
const loadDeviceName = async () => {
  const { data } = await getDeviceLedger();
  deviceOptions.value = data;
};
  const userStore = useUserStore();
  const deviceOptions = ref([]);
  const fileList = ref([]);
const { form, resetForm } = useFormData({
  deviceLedgerId: undefined, // 设备Id
  deviceName: undefined, // 设备名称
  deviceModel: undefined, // 规格型号
  repairTime: dayjs().format("YYYY-MM-DD"), // 报修日期,默认当天
  repairName: userStore.nickName, // 报修人
  remark: undefined, // 故障现象
  status: 0, // 报修状态
  machineryCategory: undefined,
  storageBlobDTOs: [],
  maintenanceName: undefined, // 维修人
});
  const loadDeviceName = async () => {
    const { data } = await getDeviceLedger();
    deviceOptions.value = data;
  };
const setDeviceModel = (deviceId) => {
  const option = deviceOptions.value.find((item) => item.id === deviceId);
  form.deviceModel = option.deviceModel;
};
  const { form, resetForm } = useFormData({
    deviceLedgerId: undefined, // 设备Id
    deviceName: undefined, // 设备名称
    deviceModel: undefined, // 规格型号
    repairTime: dayjs().format("YYYY-MM-DD"), // 报修日期,默认当天
    repairName: userStore.nickName, // 报修人
    remark: undefined, // 故障现象
    status: 0, // 报修状态
    machineryCategory: undefined,
    storageBlobDTOs: [],
    maintenanceName: undefined, // 维修人
  });
const setForm = (data) => {
  form.deviceLedgerId = data.deviceLedgerId;
  form.deviceName = data.deviceName;
  form.deviceModel = data.deviceModel;
  form.repairTime = data.repairTime;
  form.repairName = data.repairName;
  form.remark = data.remark;
  form.status = data.status;
  form.machineryCategory = data.machineryCategory;
  form.storageBlobDTOs = data.storageBlobVOs || [];
  form.maintenanceName = data.maintenanceName;
  form.acceptanceName = data.acceptanceName;
  form.acceptanceTime = data.acceptanceTime;
  form.acceptanceRemark = data.acceptanceRemark;
};
  const setDeviceModel = deviceId => {
    const option = deviceOptions.value.find(item => item.id === deviceId);
    form.deviceModel = option.deviceModel;
  };
const sendForm = async () => {
  loading.value = true;
  try {
    const { code } = id.value
      ? await editRepair({ id: unref(id), ...form })
      : await addRepair(form);
    if (code == 200) {
      ElMessage.success(`${id.value ? "编辑" : "新增"}报修成功`);
      visible.value = false;
      emits("ok");
  const setForm = data => {
    form.deviceLedgerId = data.deviceLedgerId;
    form.deviceName = data.deviceName;
    form.deviceModel = data.deviceModel;
    form.repairTime = data.repairTime;
    form.repairName = data.repairName;
    form.remark = data.remark;
    form.status = data.status;
    form.machineryCategory = data.machineryCategory;
    form.storageBlobDTOs = data.storageBlobVOs || [];
    form.maintenanceName = data.maintenanceName;
    form.acceptanceName = data.acceptanceName;
    form.acceptanceTime = data.acceptanceTime;
    form.acceptanceRemark = data.acceptanceRemark;
  };
  const sendForm = async () => {
    loading.value = true;
    try {
      const { code } = id.value
        ? await editRepair({ id: unref(id), ...form })
        : await addRepair(form);
      if (code == 200) {
        ElMessage.success(`${id.value ? "编辑" : "新增"}报修成功`);
        visible.value = false;
        emits("ok");
      }
    } finally {
      loading.value = false;
    }
  } finally {
    loading.value = false;
  }
};
  };
const handleCancel = () => {
  resetForm();
  visible.value = false;
};
  const handleCancel = () => {
    resetForm();
    visible.value = false;
  };
const handleClose = () => {
  resetForm();
  visible.value = false;
};
  const handleClose = () => {
    resetForm();
    visible.value = false;
  };
const openAdd = async () => {
  id.value = undefined;
  visible.value = true;
  fileList.value = [];
  await nextTick();
  await loadDeviceName();
};
  const openAdd = async () => {
    id.value = undefined;
    operationType.value = "add";
    visible.value = true;
    fileList.value = [];
    await nextTick();
    await loadDeviceName();
  };
const openEdit = async (editId) => {
  const { data } = await getRepairById(editId);
  id.value = editId;
  visible.value = true;
  await nextTick();
  await loadDeviceName();
  setForm(data);
};
  const openEdit = async editId => {
    const { data } = await getRepairById(editId);
    id.value = editId;
    operationType.value = "edit";
    visible.value = true;
    await nextTick();
    await loadDeviceName();
    setForm(data);
  };
defineExpose({
  openAdd,
  openEdit,
});
  const openView = async viewId => {
    const { data } = await getRepairById(viewId);
    id.value = viewId;
    operationType.value = "view";
    visible.value = true;
    await nextTick();
    await loadDeviceName();
    setForm(data);
  };
  defineExpose({
    openAdd,
    openEdit,
    openView,
  });
</script>
<style lang="scss" scoped></style>
src/views/equipmentManagement/repair/index.vue
@@ -1,193 +1,195 @@
<template>
  <div class="app-container">
    <el-form :model="filters" :inline="true">
    <el-form :model="filters"
             :inline="true">
      <el-form-item label="设备名称">
        <el-input
            v-model="filters.deviceName"
            style="width: 240px"
            placeholder="请输入设备名称"
            clearable
            :prefix-icon="Search"
            @change="getTableData"
        />
        <el-input v-model="filters.deviceName"
                  style="width: 240px"
                  placeholder="请输入设备名称"
                  clearable
                  :prefix-icon="Search"
                  @change="getTableData" />
      </el-form-item>
      <el-form-item label="规格型号">
        <el-input
            v-model="filters.deviceModel"
            style="width: 240px"
            placeholder="请选择规格型号"
            clearable
            :prefix-icon="Search"
            @change="getTableData"
        />
        <el-input v-model="filters.deviceModel"
                  style="width: 240px"
                  placeholder="请选择规格型号"
                  clearable
                  :prefix-icon="Search"
                  @change="getTableData" />
      </el-form-item>
      <el-form-item label="故障现象">
        <el-input
            v-model="filters.remark"
            style="width: 240px"
            placeholder="请输入故障现象"
            clearable
            :prefix-icon="Search"
            @change="getTableData"
        />
        <el-input v-model="filters.remark"
                  style="width: 240px"
                  placeholder="请输入故障现象"
                  clearable
                  :prefix-icon="Search"
                  @change="getTableData" />
      </el-form-item>
      <el-form-item label="维修人">
        <el-input
            v-model="filters.maintenanceName"
            style="width: 240px"
            placeholder="请输入维修人"
            clearable
            :prefix-icon="Search"
            @change="getTableData"
        />
        <el-input v-model="filters.maintenanceName"
                  style="width: 240px"
                  placeholder="请输入维修人"
                  clearable
                  :prefix-icon="Search"
                  @change="getTableData" />
      </el-form-item>
      <el-form-item label="报修日期">
        <el-date-picker
            v-model="filters.repairTimeStr"
            type="date"
            placeholder="请选择报修日期"
            size="default"
            @change="(date) => handleDateChange(date,2)"
        />
        <el-date-picker v-model="filters.repairTimeStr"
                        type="date"
                        placeholder="请选择报修日期"
                        size="default"
                        @change="(date) => handleDateChange(date,2)" />
      </el-form-item>
      <el-form-item label="维修日期">
        <el-date-picker
            v-model="filters.maintenanceTimeStr"
            type="date"
            placeholder="请选择维修日期"
            size="default"
            @change="(date) => handleDateChange(date,1)"
        />
        <el-date-picker v-model="filters.maintenanceTimeStr"
                        type="date"
                        placeholder="请选择维修日期"
                        size="default"
                        @change="(date) => handleDateChange(date,1)" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getTableData">搜索</el-button>
        <el-button type="primary"
                   @click="getTableData">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </el-form-item>
    </el-form>
    <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 type="success" icon="Van" @click="addRepair">
          <el-button type="success"
                     icon="Van"
                     @click="addRepair">
            新增报修
          </el-button>
          <el-button @click="handleOut">
            导出
          </el-button>
          <el-button
            type="danger"
            icon="Delete"
            :disabled="multipleList.length <= 0 || hasFinishedStatus"
            @click="delRepairByIds(multipleList.map((item) => item.id))"
          >
          <el-button type="danger"
                     icon="Delete"
                     :disabled="multipleList.length <= 0 || hasFinishedStatus"
                     @click="delRepairByIds(multipleList.map((item) => item.id))">
            批量删除
          </el-button>
        </div>
      </div>
      <PIMTable
          rowKey="id"
          isSelection
          :column="columns"
          :tableData="dataList"
          :page="{
      <PIMTable rowKey="id"
                isSelection
                :column="columns"
                :tableData="dataList"
                :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
          @selection-change="handleSelectionChange"
          @pagination="changePage"
      >
                @selection-change="handleSelectionChange"
                @pagination="changePage">
        <template #statusRef="{ row }">
          <el-tag v-if="row.status === 2" type="danger">失败</el-tag>
          <el-tag v-if="row.status === 1" type="success">完结</el-tag>
          <el-tag v-if="row.status === 3" type="info">待验收</el-tag>
          <el-tag v-if="row.status === 0" type="warning">待维修</el-tag>
          <el-tag v-if="row.status === 2"
                  type="danger">失败</el-tag>
          <el-tag v-if="row.status === 1"
                  type="success">完结</el-tag>
          <el-tag v-if="row.status === 3"
                  type="info">待验收</el-tag>
          <el-tag v-if="row.status === 0"
                  type="warning">待维修</el-tag>
        </template>
        <template #operation="{ row }">
          <el-button
            type="primary"
            link
            :disabled="row.status === 1 || row.status === 3"
            @click="editRepair(row.id)"
          >
          <el-button type="primary"
                     link
                     @click="viewRepair(row.id)">
            详情
          </el-button>
          <el-button type="primary"
                     link
                     :disabled="row.status === 1 || row.status === 3"
                     @click="editRepair(row.id)">
            编辑
          </el-button>
          <el-button
            type="success"
            link
            :disabled="row.status !== 0"
            @click="addMaintain(row)"
          >
          <el-button type="success"
                     link
                     :disabled="row.status !== 0"
                     @click="addMaintain(row)">
            维修
          </el-button>
          <el-button
            type="warning"
            link
            :disabled="row.status !== 3"
            @click="openAcceptance(row)"
          >
          <el-button type="warning"
                     link
                     :disabled="row.status !== 3"
                     @click="openAcceptance(row)">
            验收
          </el-button>
          <el-button
            type="danger"
            link
            :disabled="row.status === 1 || row.status === 3"
            @click="delRepairByIds(row.id)"
          >
          <el-button type="danger"
                     link
                     :disabled="row.status === 1 || row.status === 3"
                     @click="delRepairByIds(row.id)">
            删除
          </el-button>
          <el-button
              type="primary"
              link
              @click="openFileDialog(row)"
          >
          <el-button type="primary"
                     link
                     @click="openFileDialog(row)">
            附件
          </el-button>
        </template>
      </PIMTable>
    </div>
    <RepairModal ref="repairModalRef" @ok="getTableData"/>
    <MaintainModal ref="maintainModalRef" @ok="getTableData"/>
    <AcceptanceModal ref="acceptanceModalRef" @ok="getTableData"/>
    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" :record-type="'device_repair'" :record-id="recordId"  />
    <RepairModal ref="repairModalRef"
                 @ok="getTableData" />
    <MaintainModal ref="maintainModalRef"
                   @ok="getTableData" />
    <AcceptanceModal ref="acceptanceModalRef"
                     @ok="getTableData" />
    <FileList v-if="fileDialogVisible"
              v-model:visible="fileDialogVisible"
              :record-type="'device_repair'"
              :record-id="recordId" />
  </div>
</template>
<script setup>
import {onMounted, getCurrentInstance, computed, ref, defineAsyncComponent} from "vue";
import {usePaginationApi} from "@/hooks/usePaginationApi";
import {getRepairPage, delRepair} from "@/api/equipmentManagement/repair";
import RepairModal from "./Modal/RepairModal.vue";
import {ElMessageBox, ElMessage} from "element-plus";
import dayjs from "dayjs";
import MaintainModal from "./Modal/MaintainModal.vue";
import AcceptanceModal from "./Modal/AcceptanceModal.vue";
const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
  import {
    onMounted,
    getCurrentInstance,
    computed,
    ref,
    defineAsyncComponent,
  } from "vue";
  import { usePaginationApi } from "@/hooks/usePaginationApi";
  import { getRepairPage, delRepair } from "@/api/equipmentManagement/repair";
  import RepairModal from "./Modal/RepairModal.vue";
  import { ElMessageBox, ElMessage } from "element-plus";
  import dayjs from "dayjs";
  import MaintainModal from "./Modal/MaintainModal.vue";
  import AcceptanceModal from "./Modal/AcceptanceModal.vue";
  const FileList = defineAsyncComponent(() =>
    import("@/components/Dialog/FileList.vue")
  );
defineOptions({
  name: "设备报修",
});
  defineOptions({
    name: "设备报修",
  });
const {proxy} = getCurrentInstance();
  const { proxy } = getCurrentInstance();
// 模态框实例
const repairModalRef = ref();
const maintainModalRef = ref();
const acceptanceModalRef = ref();
  // 模态框实例
  const repairModalRef = ref();
  const maintainModalRef = ref();
  const acceptanceModalRef = ref();
// 表格多选框选中项
const multipleList = ref([]);
  // 表格多选框选中项
  const multipleList = ref([]);
// 表格钩子
const {
  filters,
  columns,
  dataList,
  pagination,
  getTableData,
  resetFilters,
  onCurrentChange,
} = usePaginationApi(
  // 表格钩子
  const {
    filters,
    columns,
    dataList,
    pagination,
    getTableData,
    resetFilters,
    onCurrentChange,
  } = usePaginationApi(
    getRepairPage,
    {
      deviceName: undefined,
@@ -209,52 +211,15 @@
        prop: "deviceModel",
      },
      {
        label: "报修项目",
        align: "center",
        prop: "machineryCategory",
      },
      {
        label: "报修日期",
        align: "center",
        prop: "repairTime",
        formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"),
        formatData: cell => dayjs(cell).format("YYYY-MM-DD"),
      },
      {
        label: "报修人",
        align: "center",
        prop: "repairName",
      },
      {
        label: "故障现象",
        align: "center",
        prop: "remark",
      },
      {
        label: "维修人",
        align: "center",
        prop: "maintenanceName",
      },
      {
        label: "维修结果",
        align: "center",
        prop: "maintenanceResult",
      },
      {
        label: "维修日期",
        align: "center",
        prop: "maintenanceTime",
        formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
      },
      {
        label: "验收人",
        align: "center",
        prop: "acceptanceName",
      },
      {
        label: "验收时间",
        align: "center",
        prop: "acceptanceTime",
        formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : ""),
      },
      {
        label: "状态",
@@ -269,127 +234,132 @@
        dataType: "slot",
        slot: "operation",
        align: "center",
        width: "300px",
        width: "320px",
      },
    ]
);
  );
// type === 1 维修 2报修间
const handleDateChange = (value, type) => {
  filters.maintenanceTimeStr = null
  filters.c = null
  if (type === 1) {
    if (value) {
      filters.maintenanceTimeStr = dayjs(value).format("YYYY-MM-DD");
  // type === 1 维修 2报修间
  const handleDateChange = (value, type) => {
    filters.maintenanceTimeStr = null;
    filters.c = null;
    if (type === 1) {
      if (value) {
        filters.maintenanceTimeStr = dayjs(value).format("YYYY-MM-DD");
      }
    } else {
      if (value) {
        filters.repairTimeStr = dayjs(value).format("YYYY-MM-DD");
      }
    }
  } else {
    if (value) {
      filters.repairTimeStr = dayjs(value).format("YYYY-MM-DD");
    }
  }
  getTableData();
};
    getTableData();
  };
// 打开附件弹窗
const recordId =ref(0)
const fileDialogVisible = ref(false)
  // 打开附件弹窗
  const recordId = ref(0);
  const fileDialogVisible = ref(false);
const openFileDialog = async (row) => {
  recordId.value = row.id
  fileDialogVisible.value = true
}
  const openFileDialog = async row => {
    recordId.value = row.id;
    fileDialogVisible.value = true;
  };
// 多选后做什么
const handleSelectionChange = (selectionList) => {
  multipleList.value = selectionList;
};
  // 多选后做什么
  const handleSelectionChange = selectionList => {
    multipleList.value = selectionList;
  };
// 检查选中的记录中是否有完结状态的
const hasFinishedStatus = computed(() => {
  return multipleList.value.some(item => item.status === 1)
})
// 新增报修
const addRepair = () => {
  repairModalRef.value.openAdd();
};
// 编辑报修
const editRepair = (id) => {
  repairModalRef.value.openEdit(id);
};
// 新增维修
const addMaintain = (row) => {
  maintainModalRef.value.open(row.id, row);
};
// 打开验收弹窗
const openAcceptance = (row) => {
  acceptanceModalRef.value.open(row);
};
const changePage = ({page, limit}) => {
  pagination.currentPage = page;
  pagination.pageSize = limit;
  onCurrentChange(page);
};
// 单行删除
const delRepairByIds = async (ids) => {
  // 检查是否有完结状态的记录
  const idsArray = Array.isArray(ids) ? ids : [ids];
  const hasFinished = idsArray.some(id => {
    const record = dataList.value.find(item => item.id === id);
    return record && record.status === 1;
  // 检查选中的记录中是否有完结状态的
  const hasFinishedStatus = computed(() => {
    return multipleList.value.some(item => item.status === 1);
  });
  if (hasFinished) {
    ElMessage.warning('不能删除状态为完结的记录');
    return;
  }
  // 新增报修
  const addRepair = () => {
    repairModalRef.value.openAdd();
  };
  ElMessageBox.confirm("确认删除报修数据, 此操作不可逆?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    const {code} = await delRepair(ids);
    if (code === 200) {
      ElMessage.success("删除成功");
      getTableData();
  // 详情查看
  const viewRepair = id => {
    repairModalRef.value.openView(id);
  };
  // 编辑报修
  const editRepair = id => {
    repairModalRef.value.openEdit(id);
  };
  // 新增维修
  const addMaintain = row => {
    maintainModalRef.value.open(row.id, row);
  };
  // 打开验收弹窗
  const openAcceptance = row => {
    acceptanceModalRef.value.open(row);
  };
  const changePage = ({ page, limit }) => {
    pagination.currentPage = page;
    pagination.pageSize = limit;
    onCurrentChange(page);
  };
  // 单行删除
  const delRepairByIds = async ids => {
    // 检查是否有完结状态的记录
    const idsArray = Array.isArray(ids) ? ids : [ids];
    const hasFinished = idsArray.some(id => {
      const record = dataList.value.find(item => item.id === id);
      return record && record.status === 1;
    });
    if (hasFinished) {
      ElMessage.warning("不能删除状态为完结的记录");
      return;
    }
  });
};
// 导出
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    ElMessageBox.confirm("确认删除报修数据, 此操作不可逆?", "警告", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(async () => {
      const { code } = await delRepair(ids);
      if (code === 200) {
        ElMessage.success("删除成功");
        getTableData();
      }
    });
  };
  // 导出
  const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        proxy.download("/device/repair/export", {}, "设备报修.xlsx");
      })
      .catch(() => {
        ElMessage.info("已取消");
      });
};
  };
onMounted(() => {
  getTableData();
});
  onMounted(() => {
    getTableData();
  });
</script>
<style lang="scss" scoped>
.table_list {
  margin-top: unset;
}
  .table_list {
    margin-top: unset;
  }
.actions {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
}
  .actions {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
  }
</style>
src/views/productionPlan/productionPlan/index.vue
@@ -303,6 +303,13 @@
        return params == "销售" ? "销售" : "内部";
      },
    },
    {
      label: "销售合同号",
      prop: "salesContractNo",
      width: "200px",
      dataType: "slot",
      slot: "salesContractNo",
    },
    {
      label: "产品名称",
@@ -328,7 +335,6 @@
      label: "所需数量",
      prop: "qtyRequired",
      width: "150px",
      align: "right",
      dataType: "slot",
      slot: "qtyRequired",
      className: "volume-cell",
@@ -377,13 +383,7 @@
      className: "date-cell",
      formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
    },
    {
      label: "销售合同号",
      prop: "salesContractNo",
      width: "200px",
      dataType: "slot",
      slot: "salesContractNo",
    },
    {
      label: "客户名称",
      prop: "customerName",
src/views/salesManagement/receiptPaymentLedger/index.vue
@@ -37,7 +37,7 @@
                             show-overflow-tooltip
                             width="200" />
            <el-table-column label="合同金额(元)"
                             prop="invoiceTotal"
                             prop="contractAmounts"
                             show-overflow-tooltip
                             :formatter="formattedNumber"
                             width="200" />
@@ -47,12 +47,12 @@
                             :formatter="formattedNumber"
                             width="200" />
            <el-table-column label="应收金额(元)"
                             prop="unReceiptPaymentAmount"
                             prop="receiptableAmount"
                             show-overflow-tooltip
                             width="200">
              <template #default="{ row, column }">
                <el-text type="danger">
                  {{ formattedNumber(row, column, row.unReceiptPaymentAmount) }}
                  {{ formattedNumber(row, column, row.receiptableAmount) }}
                </el-text>
              </template>
            </el-table-column>
src/views/salesManagement/salesLedger/index.vue
@@ -234,9 +234,13 @@
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         width="130"
                         width="220"
                         align="center">
          <template #default="scope">
            <el-button link
                       type="primary"
                       @click="openForm('view', scope.row)">详情
            </el-button>
            <el-button link
                       type="primary"
                       @click="openForm('edit', scope.row)"
@@ -257,7 +261,7 @@
                  @pagination="paginationChange" />
    </div>
    <FormDialog v-model="dialogFormVisible"
                :title="operationType === 'add' ? '新增销售台账页面' : '编辑销售台账页面'"
                :title="operationType === 'add' ? '新增销售台账页面' : (operationType === 'edit' ? '编辑销售台账页面' : '销售台账详情')"
                :width="'70%'"
                :operation-type="operationType"
                @close="closeDia"
@@ -291,7 +295,7 @@
                <el-input v-model="form.salesContractNo"
                          :placeholder="form.autoGenerateContractNo ? '自动生成' : '请输入'"
                          clearable
                          :disabled="form.autoGenerateContractNo" />
                          :disabled="form.autoGenerateContractNo || operationType === 'view'" />
              </div>
            </el-form-item>
          </el-col>
@@ -374,6 +378,7 @@
                         :reserve-keyword="false"
                         placeholder="请选择"
                         clearable
                         :disabled="operationType === 'view'"
                         @change="changs">
                <el-option v-for="item in userList"
                           :key="item.userId"
@@ -391,7 +396,8 @@
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
                              clearable
                              :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -405,7 +411,8 @@
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
                              clearable
                              :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -493,11 +500,13 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
        <el-row v-if="operationType !== 'view'"
                :gutter="30">
          <el-col :span="24">
            <el-form-item label="附件材料:"
                          prop="salesLedgerFiles">
              <FileUpload v-model:file-list="fileList" />
              <FileUpload v-model:file-list="fileList"
                          :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -2071,286 +2080,286 @@
    // 构建打印内容
    let printContent = `
                                                                  <!DOCTYPE html>
                                                                  <html>
                                                                  <head>
                                                                    <meta charset="UTF-8">
                                                                    <title>打印预览</title>
                                                                    <style>
                                                                      body {
                                                                        margin: 0;
                                                                        padding: 0;
                                                                        font-family: "SimSun", serif;
                                                                        background: white;
                                                                      }
                                                                                                                   .print-page {
                                                                          width: 200mm;
                                                                          height: 75mm;
                                                                          padding: 10mm;
                                                                          padding-left: 20mm;
                                                                          background: white;
                                                                          box-sizing: border-box;
                                                                          page-break-after: always;
                                                                          page-break-inside: avoid;
                                                                        }
                                                                       .print-page:last-child {
                                                                         page-break-after: avoid;
                                                                       }
                                                                      .delivery-note {
                                                                        width: 100%;
                                                                        height: 100%;
                                                                        font-size: 12px;
                                                                        line-height: 1.2;
                                                                        display: flex;
                                                                        flex-direction: column;
                                                                        color: #000;
                                                                      }
                                                                      .header {
                                                                        text-align: center;
                                                                        margin-bottom: 8px;
                                                                      }
                                                                      .company-name {
                                                                        font-size: 18px;
                                                                        font-weight: bold;
                                                                        margin-bottom: 4px;
                                                                      }
                                                                      .document-title {
                                                                        font-size: 16px;
                                                                        font-weight: bold;
                                                                      }
                                                                      .info-section {
                                                                        margin-bottom: 8px;
                                                                        display: flex;
                                                                        justify-content: space-between;
                                                                        align-items: center;
                                                                      }
                                                                      .info-row {
                                                                        line-height: 20px;
                                                                      }
                                                                      .label {
                                                                        font-weight: bold;
                                                                        width: 60px;
                                                                        font-size: 12px;
                                                                      }
                                                                      .value {
                                                                        margin-right: 20px;
                                                                        min-width: 80px;
                                                                        font-size: 12px;
                                                                      }
                                                                               .table-section {
                                                                               margin-bottom: 40px;
                                                                        //  flex: 0.6;
                                                                       }
                                                                      .product-table {
                                                                        width: 100%;
                                                                        border-collapse: collapse;
                                                                        border: 1px solid #000;
                                                                      }
                                                                               .product-table th, .product-table td {
                                                                         border: 1px solid #000;
                                                                         padding: 6px;
                                                                         text-align: center;
                                                                         font-size: 12px;
                                                                         line-height: 1.4;
                                                                       }
                                                                      .product-table th {
                                                                        font-weight: bold;
                                                                      }
                                                                      .total-value {
                                                                        font-weight: bold;
                                                                      }
                                                                      .footer-section {
                                                                        margin-top: auto;
                                                                      }
                                                                      .footer-row {
                                                                        display: flex;
                                                                        margin-bottom: 3px;
                                                                        line-height: 22px;
                                                                        justify-content: space-between;
                                                                      }
                                                                      .footer-item {
                                                                        display: flex;
                                                                        margin-right: 20px;
                                                                      }
                                                                      .footer-item .label {
                                                                        font-weight: bold;
                                                                        width: 80px;
                                                                        font-size: 12px;
                                                                      }
                                                                      .footer-item .value {
                                                                        min-width: 80px;
                                                                        font-size: 12px;
                                                                      }
                                                                      .address-item .address-value {
                                                                        min-width: 200px;
                                                                      }
                                                                      @media print {
                                                                        body {
                                                                          margin: 0;
                                                                          padding: 0;
                                                                        }
                                                                                   .print-page {
                                                                           margin: 0;
                                                                           padding: 10mm;
                                                                           /* padding-left: 20mm; */
                                                                           page-break-inside: avoid;
                                                                           page-break-after: always;
                                                                         }
                                                                         .print-page:last-child {
                                                                           page-break-after: avoid;
                                                                         }
                                                                      }
                                                                    </style>
                                                                  </head>
                                                                  <body>
                                                                `;
                                                                                  <!DOCTYPE html>
                                                                                  <html>
                                                                                  <head>
                                                                                    <meta charset="UTF-8">
                                                                                    <title>打印预览</title>
                                                                                    <style>
                                                                                      body {
                                                                                        margin: 0;
                                                                                        padding: 0;
                                                                                        font-family: "SimSun", serif;
                                                                                        background: white;
                                                                                      }
                                                                                                                                   .print-page {
                                                                                          width: 200mm;
                                                                                          height: 75mm;
                                                                                          padding: 10mm;
                                                                                          padding-left: 20mm;
                                                                                          background: white;
                                                                                          box-sizing: border-box;
                                                                                          page-break-after: always;
                                                                                          page-break-inside: avoid;
                                                                                        }
                                                                                       .print-page:last-child {
                                                                                         page-break-after: avoid;
                                                                                       }
                                                                                      .delivery-note {
                                                                                        width: 100%;
                                                                                        height: 100%;
                                                                                        font-size: 12px;
                                                                                        line-height: 1.2;
                                                                                        display: flex;
                                                                                        flex-direction: column;
                                                                                        color: #000;
                                                                                      }
                                                                                      .header {
                                                                                        text-align: center;
                                                                                        margin-bottom: 8px;
                                                                                      }
                                                                                      .company-name {
                                                                                        font-size: 18px;
                                                                                        font-weight: bold;
                                                                                        margin-bottom: 4px;
                                                                                      }
                                                                                      .document-title {
                                                                                        font-size: 16px;
                                                                                        font-weight: bold;
                                                                                      }
                                                                                      .info-section {
                                                                                        margin-bottom: 8px;
                                                                                        display: flex;
                                                                                        justify-content: space-between;
                                                                                        align-items: center;
                                                                                      }
                                                                                      .info-row {
                                                                                        line-height: 20px;
                                                                                      }
                                                                                      .label {
                                                                                        font-weight: bold;
                                                                                        width: 60px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                      .value {
                                                                                        margin-right: 20px;
                                                                                        min-width: 80px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                               .table-section {
                                                                                               margin-bottom: 40px;
                                                                                        //  flex: 0.6;
                                                                                       }
                                                                                      .product-table {
                                                                                        width: 100%;
                                                                                        border-collapse: collapse;
                                                                                        border: 1px solid #000;
                                                                                      }
                                                                                               .product-table th, .product-table td {
                                                                                         border: 1px solid #000;
                                                                                         padding: 6px;
                                                                                         text-align: center;
                                                                                         font-size: 12px;
                                                                                         line-height: 1.4;
                                                                                       }
                                                                                      .product-table th {
                                                                                        font-weight: bold;
                                                                                      }
                                                                                      .total-value {
                                                                                        font-weight: bold;
                                                                                      }
                                                                                      .footer-section {
                                                                                        margin-top: auto;
                                                                                      }
                                                                                      .footer-row {
                                                                                        display: flex;
                                                                                        margin-bottom: 3px;
                                                                                        line-height: 22px;
                                                                                        justify-content: space-between;
                                                                                      }
                                                                                      .footer-item {
                                                                                        display: flex;
                                                                                        margin-right: 20px;
                                                                                      }
                                                                                      .footer-item .label {
                                                                                        font-weight: bold;
                                                                                        width: 80px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                      .footer-item .value {
                                                                                        min-width: 80px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                      .address-item .address-value {
                                                                                        min-width: 200px;
                                                                                      }
                                                                                      @media print {
                                                                                        body {
                                                                                          margin: 0;
                                                                                          padding: 0;
                                                                                        }
                                                                                                   .print-page {
                                                                                           margin: 0;
                                                                                           padding: 10mm;
                                                                                           /* padding-left: 20mm; */
                                                                                           page-break-inside: avoid;
                                                                                           page-break-after: always;
                                                                                         }
                                                                                         .print-page:last-child {
                                                                                           page-break-after: avoid;
                                                                                         }
                                                                                      }
                                                                                    </style>
                                                                                  </head>
                                                                                  <body>
                                                                                `;
    // 为每条数据生成打印页面
    printData.value.forEach((item, index) => {
      printContent += `
                                                                    <div class="print-page">
                                                                      <div class="delivery-note">
                                                                        <div class="header">
                                                                          <div class="document-title">零售发货单</div>
                                                                        </div>
                                                                        <div class="info-section">
                                                                          <div class="info-row">
                                                                            <div>
                                                                              <span class="label">发货日期:</span>
                                                                              <span class="value">${formatDate(
                                                                                item.createTime
                                                                              )}</span>
                                                                            </div>
                                                                            <div>
                                                                              <span class="label">客户名称:</span>
                                                                              <span class="value">${
                                                                                item.customerName
                                                                              }</span>
                                                                            </div>
                                                                          </div>
                                                                          <div class="info-row">
                                                                            <span class="label">单号:</span>
                                                                            <span class="value">${
                                                                              item.salesContractNo ||
                                                                              ""
                                                                            }</span>
                                                                          </div>
                                                                        </div>
                                                                                    <div class="print-page">
                                                                                      <div class="delivery-note">
                                                                                        <div class="header">
                                                                                          <div class="document-title">零售发货单</div>
                                                                                        </div>
                                                                        <div class="table-section">
                                                                          <table class="product-table">
                                                                            <thead>
                                                                              <tr>
                                                                                <th>产品名称</th>
                                                                                <th>规格型号</th>
                                                                                <th>单位</th>
                                                                                <th>单价</th>
                                                                                <th>零售数量</th>
                                                                                <th>零售金额</th>
                                                                              </tr>
                                                                            </thead>
                                                                            <tbody>
                                                                              ${
                                                                                item.products &&
                                                                                item
                                                                                  .products
                                                                                  .length >
                                                                                  0
                                                                                  ? item.products
                                                                                      .map(
                                                                                        product => `
                                                                                  <tr>
                                                                                    <td>${
                                                                                      product.productCategory ||
                                                                                      ""
                                                                                    }</td>
                                                                                    <td>${
                                                                                      product.specificationModel ||
                                                                                      ""
                                                                                    }</td>
                                                                                    <td>${
                                                                                      product.unit ||
                                                                                      ""
                                                                                    }</td>
                                                                                    <td>${
                                                                                      product.taxInclusiveUnitPrice ||
                                                                                      "0"
                                                                                    }</td>
                                                                                    <td>${
                                                                                      product.quantity ||
                                                                                      "0"
                                                                                    }</td>
                                                                                    <td>${
                                                                                      product.taxInclusiveTotalPrice ||
                                                                                      "0"
                                                                                    }</td>
                                                                                  </tr>
                                                                                `
                                                                                      )
                                                                                      .join(
                                                                                        ""
                                                                                      )
                                                                                  : '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>'
                                                                              }
                                                                            </tbody>
                                                                            <tfoot>
                                                                              <tr>
                                                                                <td class="label">合计</td>
                                                                                <td class="total-value"></td>
                                                                                <td class="total-value"></td>
                                                                                <td class="total-value"></td>
                                                                                <td class="total-value">${getTotalQuantityForPrint(
                                                                                  item.products
                                                                                )}</td>
                                                                                <td class="total-value">${getTotalAmountForPrint(
                                                                                  item.products
                                                                                )}</td>
                                                                              </tr>
                                                                            </tfoot>
                                                                          </table>
                                                                        </div>
                                                                                        <div class="info-section">
                                                                                          <div class="info-row">
                                                                                            <div>
                                                                                              <span class="label">发货日期:</span>
                                                                                              <span class="value">${formatDate(
                                                                                                item.createTime
                                                                                              )}</span>
                                                                                            </div>
                                                                                            <div>
                                                                                              <span class="label">客户名称:</span>
                                                                                              <span class="value">${
                                                                                                item.customerName
                                                                                              }</span>
                                                                                            </div>
                                                                                          </div>
                                                                                          <div class="info-row">
                                                                                            <span class="label">单号:</span>
                                                                                            <span class="value">${
                                                                                              item.salesContractNo ||
                                                                                              ""
                                                                                            }</span>
                                                                                          </div>
                                                                                        </div>
                                                                        <div class="footer-section">
                                                                          <div class="footer-row">
                                                                            <div class="footer-item">
                                                                              <span class="label">收货电话:</span>
                                                                              <span class="value"></span>
                                                                            </div>
                                                                            <div class="footer-item">
                                                                              <span class="label">收货人:</span>
                                                                              <span class="value"></span>
                                                                            </div>
                                                                            <div class="footer-item address-item">
                                                                              <span class="label">收货地址:</span>
                                                                              <span class="value address-value"></span>
                                                                            </div>
                                                                          </div>
                                                                          <div class="footer-row">
                                                                            <div class="footer-item">
                                                                              <span class="label">操作员:</span>
                                                                              <span class="value">${
                                                                                userStore.nickName ||
                                                                                "撕开前"
                                                                              }</span>
                                                                            </div>
                                                                            <div class="footer-item">
                                                                              <span class="label">打印日期:</span>
                                                                              <span class="value">${formatDateTime(
                                                                                new Date()
                                                                              )}</span>
                                                                            </div>
                                                                          </div>
                                                                        </div>
                                                                      </div>
                                                                    </div>
                                                                  `;
                                                                                        <div class="table-section">
                                                                                          <table class="product-table">
                                                                                            <thead>
                                                                                              <tr>
                                                                                                <th>产品名称</th>
                                                                                                <th>规格型号</th>
                                                                                                <th>单位</th>
                                                                                                <th>单价</th>
                                                                                                <th>零售数量</th>
                                                                                                <th>零售金额</th>
                                                                                              </tr>
                                                                                            </thead>
                                                                                            <tbody>
                                                                                              ${
                                                                                                item.products &&
                                                                                                item
                                                                                                  .products
                                                                                                  .length >
                                                                                                  0
                                                                                                  ? item.products
                                                                                                      .map(
                                                                                                        product => `
                                                                                                  <tr>
                                                                                                    <td>${
                                                                                                      product.productCategory ||
                                                                                                      ""
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.specificationModel ||
                                                                                                      ""
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.unit ||
                                                                                                      ""
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.taxInclusiveUnitPrice ||
                                                                                                      "0"
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.quantity ||
                                                                                                      "0"
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.taxInclusiveTotalPrice ||
                                                                                                      "0"
                                                                                                    }</td>
                                                                                                  </tr>
                                                                                                `
                                                                                                      )
                                                                                                      .join(
                                                                                                        ""
                                                                                                      )
                                                                                                  : '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>'
                                                                                              }
                                                                                            </tbody>
                                                                                            <tfoot>
                                                                                              <tr>
                                                                                                <td class="label">合计</td>
                                                                                                <td class="total-value"></td>
                                                                                                <td class="total-value"></td>
                                                                                                <td class="total-value"></td>
                                                                                                <td class="total-value">${getTotalQuantityForPrint(
                                                                                                  item.products
                                                                                                )}</td>
                                                                                                <td class="total-value">${getTotalAmountForPrint(
                                                                                                  item.products
                                                                                                )}</td>
                                                                                              </tr>
                                                                                            </tfoot>
                                                                                          </table>
                                                                                        </div>
                                                                                        <div class="footer-section">
                                                                                          <div class="footer-row">
                                                                                            <div class="footer-item">
                                                                                              <span class="label">收货电话:</span>
                                                                                              <span class="value"></span>
                                                                                            </div>
                                                                                            <div class="footer-item">
                                                                                              <span class="label">收货人:</span>
                                                                                              <span class="value"></span>
                                                                                            </div>
                                                                                            <div class="footer-item address-item">
                                                                                              <span class="label">收货地址:</span>
                                                                                              <span class="value address-value"></span>
                                                                                            </div>
                                                                                          </div>
                                                                                          <div class="footer-row">
                                                                                            <div class="footer-item">
                                                                                              <span class="label">操作员:</span>
                                                                                              <span class="value">${
                                                                                                userStore.nickName ||
                                                                                                "撕开前"
                                                                                              }</span>
                                                                                            </div>
                                                                                            <div class="footer-item">
                                                                                              <span class="label">打印日期:</span>
                                                                                              <span class="value">${formatDateTime(
                                                                                                new Date()
                                                                                              )}</span>
                                                                                            </div>
                                                                                          </div>
                                                                                        </div>
                                                                                      </div>
                                                                                    </div>
                                                                                  `;
    });
    printContent += `
                                                                  </body>
                                                                  </html>
                                                                `;
                                                                                  </body>
                                                                                  </html>
                                                                                `;
    // 写入内容到新窗口
    printWindow.document.write(printContent);