From 34d10fb90ba02fa28db70e14f0673639f469789c Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期三, 03 六月 2026 13:36:43 +0800
Subject: [PATCH] 质量管理页面

---
 src/api/quality/defectiveProduct.js          |   65 ++++
 src/views/quality/defectiveProduct/audit.vue |  262 ++++++++++++++++
 src/api/quality/eipCable.js                  |   83 +++++
 src/views/quality/eipCable/index.vue         |  232 ++++++++++++++
 src/api/quality/index.js                     |    2 
 src/views/quality/defectiveProduct/index.vue |  315 +++++++++++++++++++
 6 files changed, 959 insertions(+), 0 deletions(-)

diff --git a/src/api/quality/defectiveProduct.js b/src/api/quality/defectiveProduct.js
new file mode 100644
index 0000000..c4bc731
--- /dev/null
+++ b/src/api/quality/defectiveProduct.js
@@ -0,0 +1,65 @@
+// 涓嶈壇鍝佺浉鍏虫帴鍙�
+import request from "@/utils/request";
+
+// 鏌ヨ涓嶈壇鍝佺櫥璁板垪琛�
+export function pageDefectiveProduct(query) {
+  return request({
+    url: "/defectiveProduct/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板涓嶈壇鍝佺櫥璁�
+export function addDefectiveProduct(data) {
+  return request({
+    url: "/defectiveProduct/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 淇敼涓嶈壇鍝佺櫥璁�
+export function updateDefectiveProduct(data) {
+  return request({
+    url: "/defectiveProduct/update",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍒犻櫎涓嶈壇鍝佺櫥璁�
+export function deleteDefectiveProduct(query) {
+  return request({
+    url: "/defectiveProduct/delete",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 鏌ヨ涓嶈壇鍝佸鏍稿垪琛�
+export function pageDefectiveProductAudit(query) {
+  return request({
+    url: "/defectiveProduct/audit/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 涓嶈壇鍝佸鏍�
+export function auditDefectiveProduct(data) {
+  return request({
+    url: "/defectiveProduct/audit",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇涓嶈壇鍝佽鎯�
+export function getDefectiveProduct(query) {
+  return request({
+    url: "/defectiveProduct/get",
+    method: "get",
+    params: query,
+  });
+}
diff --git a/src/api/quality/eipCable.js b/src/api/quality/eipCable.js
new file mode 100644
index 0000000..cfa5af7
--- /dev/null
+++ b/src/api/quality/eipCable.js
@@ -0,0 +1,83 @@
+// EIP绾跨紗绫绘暟鎹鎺ユ帴鍙�
+import request from "@/utils/request";
+
+// 鏌ヨ楂樺帇鐢靛姏鐢电紗璇曢獙鏁版嵁
+export function pageHighVoltageCable(query) {
+  return request({
+    url: "/eip/highVoltageCable/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ涓帇鐢靛姏鐢电紗璇曢獙鏁版嵁
+export function pageMediumVoltageCable(query) {
+  return request({
+    url: "/eip/mediumVoltageCable/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ浣庡帇绾跨紗璇曢獙鏁版嵁
+export function pageLowVoltageCable(query) {
+  return request({
+    url: "/eip/lowVoltageCable/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ涓荤綉鍙峰湴绾胯瘯楠屾暟鎹�
+export function pageMainNetworkGroundWire(query) {
+  return request({
+    url: "/eip/mainNetworkGroundWire/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ閰嶇綉鍙峰湴绾胯瘯楠屾暟鎹�
+export function pageDistributionGroundWire(query) {
+  return request({
+    url: "/eip/distributionGroundWire/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ鍏夌紗璇曢獙鏁版嵁
+export function pageOpticalFiber(query) {
+  return request({
+    url: "/eip/opticalFiber/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨOPGW鍏夌紗璇曢獙鏁版嵁
+export function pageOPGWOpticalFiber(query) {
+  return request({
+    url: "/eip/opgwOpticalFiber/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨADSS鍏夌紗璇曢獙鏁版嵁
+export function pageADSSOpticalFiber(query) {
+  return request({
+    url: "/eip/adssOpticalFiber/page",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鍚屾EIP鏁版嵁
+export function syncEIPData(data) {
+  return request({
+    url: "/eip/sync",
+    method: "post",
+    data: data,
+  });
+}
diff --git a/src/api/quality/index.js b/src/api/quality/index.js
new file mode 100644
index 0000000..d073f7a
--- /dev/null
+++ b/src/api/quality/index.js
@@ -0,0 +1,2 @@
+export * from "./defectiveProduct";
+export * from "./eipCable";
diff --git a/src/views/quality/defectiveProduct/audit.vue b/src/views/quality/defectiveProduct/audit.vue
new file mode 100644
index 0000000..8ae0278
--- /dev/null
+++ b/src/views/quality/defectiveProduct/audit.vue
@@ -0,0 +1,262 @@
+<template>
+  <div class="app-container">
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="search-form">
+      <el-form :model="searchForm" inline size="small">
+        <el-form-item label="鎶ュ憡缂栧彿">
+          <el-input v-model="searchForm.reportNo" placeholder="璇疯緭鍏ユ姤鍛婄紪鍙�" clearable></el-input>
+        </el-form-item>
+        <el-form-item label="瀹℃牳鐘舵��">
+          <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨瀹℃牳鐘舵��" clearable>
+            <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-form-item>
+          <el-button type="primary" @click="searchList">鏌ヨ</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 鏁版嵁琛ㄦ牸 -->
+    <el-table v-loading="tableLoading" :data="tableData" border>
+      <el-table-column label="鎶ュ憡缂栧彿" prop="reportNo" show-overflow-tooltip></el-table-column>
+      <el-table-column label="浜у搧鍚嶇О" prop="productName" show-overflow-tooltip></el-table-column>
+      <el-table-column label="瑙勬牸鍨嬪彿" prop="specModel" show-overflow-tooltip></el-table-column>
+      <el-table-column label="涓嶅悎鏍兼弿杩�" prop="unqualifiedDesc" show-overflow-tooltip></el-table-column>
+      <el-table-column label="妫�楠屼汉鍛�" prop="inspector" show-overflow-tooltip></el-table-column>
+      <el-table-column label="鐧昏鏃堕棿" prop="registerDate" show-overflow-tooltip></el-table-column>
+      <el-table-column label="瀹℃牳鐘舵��" prop="status">
+        <template slot-scope="scope">
+          <el-tag :type="getStatusType(scope.row.status)">
+            {{ getStatusText(scope.row.status) }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="瀹℃牳鎰忚" prop="auditOpinion" show-overflow-tooltip></el-table-column>
+      <el-table-column label="瀹℃牳浜哄憳" prop="auditor" show-overflow-tooltip></el-table-column>
+      <el-table-column label="瀹℃牳鏃堕棿" prop="auditDate" show-overflow-tooltip></el-table-column>
+      <el-table-column label="鎿嶄綔" width="200">
+        <template slot-scope="scope">
+          <el-button type="text" @click="viewDetail(scope.row)">鏌ョ湅</el-button>
+          <el-button type="text" v-if="scope.row.status === '0'" @click="openAuditDia(scope.row)">瀹℃牳</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 鍒嗛〉 -->
+    <el-pagination
+      :current-page="page.current"
+      :page-size="page.size"
+      :total="page.total"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      layout="total, sizes, prev, pager, next, jumper">
+    </el-pagination>
+
+    <!-- 瀹℃牳寮圭獥 -->
+    <el-dialog title="涓嶈壇鍝佸鏍�" :visible.sync="auditVisible" width="500px">
+      <el-form :model="auditForm" label-width="100px" size="small">
+        <el-form-item label="瀹℃牳鐘舵��">
+          <el-radio-group v-model="auditForm.status">
+            <el-radio label="1">閫氳繃</el-radio>
+            <el-radio label="2">椹冲洖</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="瀹℃牳鎰忚">
+          <el-textarea v-model="auditForm.opinion" :rows="3" placeholder="璇疯緭鍏ュ鏍告剰瑙�"></el-textarea>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="auditVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="submitAudit" :loading="submitLoading">纭畾瀹℃牳</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 璇︽儏寮圭獥 -->
+    <el-dialog title="涓嶈壇鍝佸鏍歌鎯�" :visible.sync="detailVisible" width="600px">
+      <el-form :model="detailData" label-width="120px" size="small" disabled>
+        <el-form-item label="鎶ュ憡缂栧彿">
+          <span>{{ detailData.reportNo }}</span>
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О">
+          <span>{{ detailData.productName }}</span>
+        </el-form-item>
+        <el-form-item label="瑙勬牸鍨嬪彿">
+          <span>{{ detailData.specModel }}</span>
+        </el-form-item>
+        <el-form-item label="鐢熶骇鍘傚">
+          <span>{{ detailData.manufacturer }}</span>
+        </el-form-item>
+        <el-form-item label="鍘熸潗鏂欎俊鎭�">
+          <span>{{ detailData.materialInfo }}</span>
+        </el-form-item>
+        <el-form-item label="涓嶅悎鏍兼弿杩�">
+          <span>{{ detailData.unqualifiedDesc }}</span>
+        </el-form-item>
+        <el-form-item label="妫�楠屼汉鍛�">
+          <span>{{ detailData.inspector }}</span>
+        </el-form-item>
+        <el-form-item label="鐧昏鏃堕棿">
+          <span>{{ detailData.registerDate }}</span>
+        </el-form-item>
+        <el-form-item label="瀹℃牳鐘舵��">
+          <el-tag :type="getStatusType(detailData.status)">
+            {{ getStatusText(detailData.status) }}
+          </el-tag>
+        </el-form-item>
+        <el-form-item label="瀹℃牳鎰忚">
+          <span>{{ detailData.auditOpinion || "-" }}</span>
+        </el-form-item>
+        <el-form-item label="瀹℃牳浜哄憳">
+          <span>{{ detailData.auditor || "-" }}</span>
+        </el-form-item>
+        <el-form-item label="瀹℃牳鏃堕棿">
+          <span>{{ detailData.auditDate || "-" }}</span>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="detailVisible = false">鍏抽棴</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  pageDefectiveProductAudit,
+  auditDefectiveProduct,
+  getDefectiveProduct,
+} from "@/api/quality/defectiveProduct";
+
+export default {
+  name: "DefectiveProductAudit",
+  data() {
+    return {
+      searchForm: {
+        reportNo: "",
+        status: "",
+      },
+      tableData: [],
+      tableLoading: false,
+      page: {
+        current: 1,
+        size: 20,
+        total: 0,
+      },
+      auditVisible: false,
+      auditForm: {
+        id: null,
+        status: "1",
+        opinion: "",
+      },
+      submitLoading: false,
+      detailVisible: false,
+      detailData: {},
+    };
+  },
+  mounted() {
+    this.searchList();
+  },
+  methods: {
+    searchList() {
+      this.tableLoading = true;
+      pageDefectiveProductAudit({
+        ...this.searchForm,
+        page: this.page.current,
+        size: this.page.size,
+      }).then((res) => {
+        this.tableData = res.data.records;
+        this.page.total = res.data.total;
+        this.tableLoading = false;
+      }).catch((err) => {
+        this.tableLoading = false;
+        console.error(err);
+      });
+    },
+    resetSearch() {
+      this.searchForm = {
+        reportNo: "",
+        status: "",
+      };
+      this.searchList();
+    },
+    handleSizeChange(val) {
+      this.page.size = val;
+      this.searchList();
+    },
+    handleCurrentChange(val) {
+      this.page.current = val;
+      this.searchList();
+    },
+    getStatusType(status) {
+      switch (status) {
+        case "0":
+          return "warning";
+        case "1":
+          return "success";
+        case "2":
+          return "danger";
+        default:
+          return "info";
+      }
+    },
+    getStatusText(status) {
+      switch (status) {
+        case "0":
+          return "寰呭鏍�";
+        case "1":
+          return "宸查�氳繃";
+        case "2":
+          return "宸查┏鍥�";
+        default:
+          return "鏈煡";
+      }
+    },
+    openAuditDia(row) {
+      this.auditForm = {
+        id: row.id,
+        status: "1",
+        opinion: "",
+      };
+      this.auditVisible = true;
+    },
+    submitAudit() {
+      this.submitLoading = true;
+      auditDefectiveProduct(this.auditForm).then((res) => {
+        if (res.code === 200) {
+          this.$message.success("瀹℃牳鎴愬姛");
+          this.auditVisible = false;
+          this.searchList();
+        } else {
+          this.$message.error(res.msg || "瀹℃牳澶辫触");
+        }
+        this.submitLoading = false;
+      }).catch((err) => {
+        this.submitLoading = false;
+        console.error(err);
+      });
+    },
+    viewDetail(row) {
+      getDefectiveProduct({ id: row.id }).then((res) => {
+        this.detailData = res.data;
+        this.detailVisible = true;
+      }).catch((err) => {
+        console.error(err);
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.search-form {
+  margin-bottom: 15px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+</style>
diff --git a/src/views/quality/defectiveProduct/index.vue b/src/views/quality/defectiveProduct/index.vue
new file mode 100644
index 0000000..462d3d4
--- /dev/null
+++ b/src/views/quality/defectiveProduct/index.vue
@@ -0,0 +1,315 @@
+<template>
+  <div class="app-container">
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="search-form">
+      <el-form :model="searchForm" inline size="small">
+        <el-form-item label="鎶ュ憡缂栧彿">
+          <el-input v-model="searchForm.reportNo" placeholder="璇疯緭鍏ユ姤鍛婄紪鍙�" clearable></el-input>
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О">
+          <el-input v-model="searchForm.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" clearable></el-input>
+        </el-form-item>
+        <el-form-item label="鐧昏鏃堕棿">
+          <el-date-picker v-model="searchForm.registerDate" type="date" placeholder="閫夋嫨鏃ユ湡" clearable></el-date-picker>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="searchList">鏌ヨ</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 鎿嶄綔鎸夐挳 -->
+    <div class="btn-container">
+      <el-button type="primary" icon="el-icon-plus" @click="openAddDia">鏂板鐧昏</el-button>
+      <el-button type="danger" icon="el-icon-delete" @click="handleDelete" :disabled="selectedIds.length === 0">鎵归噺鍒犻櫎</el-button>
+    </div>
+
+    <!-- 鏁版嵁琛ㄦ牸 -->
+    <el-table v-loading="tableLoading" :data="tableData" @selection-change="handleSelectionChange" border>
+      <el-table-column type="selection" width="55"></el-table-column>
+      <el-table-column label="鎶ュ憡缂栧彿" prop="reportNo" show-overflow-tooltip></el-table-column>
+      <el-table-column label="浜у搧鍚嶇О" prop="productName" show-overflow-tooltip></el-table-column>
+      <el-table-column label="瑙勬牸鍨嬪彿" prop="specModel" show-overflow-tooltip></el-table-column>
+      <el-table-column label="涓嶅悎鏍兼弿杩�" prop="unqualifiedDesc" show-overflow-tooltip></el-table-column>
+      <el-table-column label="妫�楠屼汉鍛�" prop="inspector" show-overflow-tooltip></el-table-column>
+      <el-table-column label="鐧昏鏃堕棿" prop="registerDate" show-overflow-tooltip></el-table-column>
+      <el-table-column label="鐘舵��" prop="status">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.status === '0' ? 'warning' : 'success'">
+            {{ scope.row.status === '0' ? '寰呭鏍�' : '宸插鏍�' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" width="180">
+        <template slot-scope="scope">
+          <el-button type="text" @click="viewDetail(scope.row)">鏌ョ湅</el-button>
+          <el-button type="text" @click="openEditDia(scope.row)">缂栬緫</el-button>
+          <el-button type="text" @click="handleSingleDelete(scope.row)">鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 鍒嗛〉 -->
+    <el-pagination
+      :current-page="page.current"
+      :page-size="page.size"
+      :total="page.total"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      layout="total, sizes, prev, pager, next, jumper">
+    </el-pagination>
+
+    <!-- 鏂板/缂栬緫寮圭獥 -->
+    <el-dialog :title="isEdit ? '缂栬緫涓嶈壇鍝佺櫥璁�' : '鏂板涓嶈壇鍝佺櫥璁�'" :visible.sync="formVisible" width="500px">
+      <el-form :model="formData" label-width="100px" size="small">
+        <el-form-item label="鎶ュ憡缂栧彿" prop="reportNo">
+          <el-input v-model="formData.reportNo" placeholder="璇疯緭鍏ユ姤鍛婄紪鍙�"></el-input>
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О" prop="productName">
+          <el-input v-model="formData.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"></el-input>
+        </el-form-item>
+        <el-form-item label="瑙勬牸鍨嬪彿" prop="specModel">
+          <el-input v-model="formData.specModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"></el-input>
+        </el-form-item>
+        <el-form-item label="鐢熶骇鍘傚" prop="manufacturer">
+          <el-input v-model="formData.manufacturer" placeholder="璇疯緭鍏ョ敓浜у巶瀹�"></el-input>
+        </el-form-item>
+        <el-form-item label="鍘熸潗鏂欎俊鎭�" prop="materialInfo">
+          <el-input v-model="formData.materialInfo" placeholder="璇疯緭鍏ュ師鏉愭枡淇℃伅"></el-input>
+        </el-form-item>
+        <el-form-item label="涓嶅悎鏍兼弿杩�" prop="unqualifiedDesc">
+          <el-textarea v-model="formData.unqualifiedDesc" :rows="3" placeholder="璇疯緭鍏ヤ笉鍚堟牸鎻忚堪"></el-textarea>
+        </el-form-item>
+        <el-form-item label="妫�楠屼汉鍛�" prop="inspector">
+          <el-input v-model="formData.inspector" placeholder="璇疯緭鍏ユ楠屼汉鍛�"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="formVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="submitForm" :loading="submitLoading">纭畾</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 璇︽儏寮圭獥 -->
+    <el-dialog title="涓嶈壇鍝佺櫥璁拌鎯�" :visible.sync="detailVisible" width="600px">
+      <el-form :model="detailData" label-width="120px" size="small" disabled>
+        <el-form-item label="鎶ュ憡缂栧彿">
+          <span>{{ detailData.reportNo }}</span>
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О">
+          <span>{{ detailData.productName }}</span>
+        </el-form-item>
+        <el-form-item label="瑙勬牸鍨嬪彿">
+          <span>{{ detailData.specModel }}</span>
+        </el-form-item>
+        <el-form-item label="鐢熶骇鍘傚">
+          <span>{{ detailData.manufacturer }}</span>
+        </el-form-item>
+        <el-form-item label="鍘熸潗鏂欎俊鎭�">
+          <span>{{ detailData.materialInfo }}</span>
+        </el-form-item>
+        <el-form-item label="涓嶅悎鏍兼弿杩�">
+          <span>{{ detailData.unqualifiedDesc }}</span>
+        </el-form-item>
+        <el-form-item label="妫�楠屼汉鍛�">
+          <span>{{ detailData.inspector }}</span>
+        </el-form-item>
+        <el-form-item label="鐧昏鏃堕棿">
+          <span>{{ detailData.registerDate }}</span>
+        </el-form-item>
+        <el-form-item label="瀹℃牳鐘舵��">
+          <el-tag :type="detailData.status === '0' ? 'warning' : 'success'">
+            {{ detailData.status === '0' ? '寰呭鏍�' : '宸插鏍�' }}
+          </el-tag>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="detailVisible = false">鍏抽棴</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  pageDefectiveProduct,
+  addDefectiveProduct,
+  updateDefectiveProduct,
+  deleteDefectiveProduct,
+  getDefectiveProduct,
+} from "@/api/quality/defectiveProduct";
+
+export default {
+  name: "DefectiveProduct",
+  data() {
+    return {
+      searchForm: {
+        reportNo: "",
+        productName: "",
+        registerDate: "",
+      },
+      tableData: [],
+      tableLoading: false,
+      page: {
+        current: 1,
+        size: 20,
+        total: 0,
+      },
+      selectedIds: [],
+      formVisible: false,
+      isEdit: false,
+      formData: {
+        id: null,
+        reportNo: "",
+        productName: "",
+        specModel: "",
+        manufacturer: "",
+        materialInfo: "",
+        unqualifiedDesc: "",
+        inspector: "",
+      },
+      submitLoading: false,
+      detailVisible: false,
+      detailData: {},
+    };
+  },
+  mounted() {
+    this.searchList();
+  },
+  methods: {
+    searchList() {
+      this.tableLoading = true;
+      pageDefectiveProduct({
+        ...this.searchForm,
+        page: this.page.current,
+        size: this.page.size,
+      }).then((res) => {
+        this.tableData = res.data.records;
+        this.page.total = res.data.total;
+        this.tableLoading = false;
+      }).catch((err) => {
+        this.tableLoading = false;
+        console.error(err);
+      });
+    },
+    resetSearch() {
+      this.searchForm = {
+        reportNo: "",
+        productName: "",
+        registerDate: "",
+      };
+      this.searchList();
+    },
+    handleSizeChange(val) {
+      this.page.size = val;
+      this.searchList();
+    },
+    handleCurrentChange(val) {
+      this.page.current = val;
+      this.searchList();
+    },
+    handleSelectionChange(val) {
+      this.selectedIds = val.map((item) => item.id);
+    },
+    openAddDia() {
+      this.isEdit = false;
+      this.formData = {
+        id: null,
+        reportNo: "",
+        productName: "",
+        specModel: "",
+        manufacturer: "",
+        materialInfo: "",
+        unqualifiedDesc: "",
+        inspector: "",
+      };
+      this.formVisible = true;
+    },
+    openEditDia(row) {
+      this.isEdit = true;
+      this.formData = { ...row };
+      this.formVisible = true;
+    },
+    submitForm() {
+      if (!this.formData.reportNo) {
+        this.$message.error("璇疯緭鍏ユ姤鍛婄紪鍙�");
+        return;
+      }
+      if (!this.formData.productName) {
+        this.$message.error("璇疯緭鍏ヤ骇鍝佸悕绉�");
+        return;
+      }
+      this.submitLoading = true;
+      const api = this.isEdit ? updateDefectiveProduct : addDefectiveProduct;
+      api(this.formData).then((res) => {
+        if (res.code === 200) {
+          this.$message.success(this.isEdit ? "淇敼鎴愬姛" : "鏂板鎴愬姛");
+          this.formVisible = false;
+          this.searchList();
+        } else {
+          this.$message.error(res.msg || "鎿嶄綔澶辫触");
+        }
+        this.submitLoading = false;
+      }).catch((err) => {
+        this.submitLoading = false;
+        console.error(err);
+      });
+    },
+    viewDetail(row) {
+      getDefectiveProduct({ id: row.id }).then((res) => {
+        this.detailData = res.data;
+        this.detailVisible = true;
+      }).catch((err) => {
+        console.error(err);
+      });
+    },
+    handleDelete() {
+      this.$confirm("纭畾鍒犻櫎閫変腑鐨勮褰曞悧锛�", "鎻愮ず", {
+        type: "warning",
+      }).then(() => {
+        deleteDefectiveProduct({ ids: this.selectedIds.join(",") }).then((res) => {
+          if (res.code === 200) {
+            this.$message.success("鍒犻櫎鎴愬姛");
+            this.searchList();
+          } else {
+            this.$message.error(res.msg || "鍒犻櫎澶辫触");
+          }
+        }).catch((err) => {
+          console.error(err);
+        });
+      }).catch(() => {});
+    },
+    handleSingleDelete(row) {
+      this.$confirm("纭畾鍒犻櫎璇ヨ褰曞悧锛�", "鎻愮ず", {
+        type: "warning",
+      }).then(() => {
+        deleteDefectiveProduct({ ids: row.id }).then((res) => {
+          if (res.code === 200) {
+            this.$message.success("鍒犻櫎鎴愬姛");
+            this.searchList();
+          } else {
+            this.$message.error(res.msg || "鍒犻櫎澶辫触");
+          }
+        }).catch((err) => {
+          console.error(err);
+        });
+      }).catch(() => {});
+    },
+  },
+};
+</script>
+
+<style scoped>
+.search-form {
+  margin-bottom: 15px;
+}
+
+.btn-container {
+  margin-bottom: 15px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+</style>
diff --git a/src/views/quality/eipCable/index.vue b/src/views/quality/eipCable/index.vue
new file mode 100644
index 0000000..7451f7b
--- /dev/null
+++ b/src/views/quality/eipCable/index.vue
@@ -0,0 +1,232 @@
+<template>
+  <div class="app-container">
+    <!-- 鏍囩椤� -->
+    <el-tabs v-model="activeTab" type="card" @tab-click="handleTabClick">
+      <el-tab-pane label="楂樺帇鐢靛姏鐢电紗" name="highVoltage"></el-tab-pane>
+      <el-tab-pane label="涓帇鐢靛姏鐢电紗" name="mediumVoltage"></el-tab-pane>
+      <el-tab-pane label="浣庡帇绾跨紗" name="lowVoltage"></el-tab-pane>
+      <el-tab-pane label="涓荤綉鍙峰湴绾�" name="mainNetwork"></el-tab-pane>
+      <el-tab-pane label="閰嶇綉鍙峰湴绾�" name="distribution"></el-tab-pane>
+      <el-tab-pane label="鍏夌紗" name="opticalFiber"></el-tab-pane>
+      <el-tab-pane label="OPGW鍏夌紗" name="opgw"></el-tab-pane>
+      <el-tab-pane label="ADSS鍏夌紗" name="adss"></el-tab-pane>
+    </el-tabs>
+
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="search-form">
+      <el-form :model="searchForm" inline size="small">
+        <el-form-item label="鏍峰搧缂栧彿">
+          <el-input v-model="searchForm.sampleCode" placeholder="璇疯緭鍏ユ牱鍝佺紪鍙�" clearable></el-input>
+        </el-form-item>
+        <el-form-item label="璇曢獙绫诲瀷">
+          <el-input v-model="searchForm.testType" placeholder="璇疯緭鍏ヨ瘯楠岀被鍨�" clearable></el-input>
+        </el-form-item>
+        <el-form-item label="璇曢獙鏃堕棿">
+          <el-date-picker v-model="searchForm.testDate" type="date" placeholder="閫夋嫨鏃ユ湡" clearable></el-date-picker>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="searchList">鏌ヨ</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+          <el-button type="success" @click="syncData">鍚屾EIP鏁版嵁</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 鏁版嵁琛ㄦ牸 -->
+    <el-table v-loading="tableLoading" :data="tableData" border>
+      <el-table-column label="鏍峰搧缂栧彿" prop="sampleCode" show-overflow-tooltip></el-table-column>
+      <el-table-column label="浜у搧鍚嶇О" prop="productName" show-overflow-tooltip></el-table-column>
+      <el-table-column label="瑙勬牸鍨嬪彿" prop="specModel" show-overflow-tooltip></el-table-column>
+      <el-table-column label="璇曢獙绫诲瀷" prop="testType" show-overflow-tooltip></el-table-column>
+      <el-table-column label="璇曢獙缁撴灉" prop="testResult" show-overflow-tooltip></el-table-column>
+      <el-table-column label="鍘熸潗鏂�" prop="rawMaterial" show-overflow-tooltip></el-table-column>
+      <el-table-column label="杩囩▼妫�" prop="processInspection" show-overflow-tooltip></el-table-column>
+      <el-table-column label="鎴愬搧妫�" prop="finalInspection" show-overflow-tooltip></el-table-column>
+      <el-table-column label="璇曢獙鏃堕棿" prop="testDate" show-overflow-tooltip></el-table-column>
+      <el-table-column label="鎿嶄綔" width="100">
+        <template slot-scope="scope">
+          <el-button type="text" @click="viewDetail(scope.row)">鏌ョ湅</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 鍒嗛〉 -->
+    <el-pagination
+      :current-page="page.current"
+      :page-size="page.size"
+      :total="page.total"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      layout="total, sizes, prev, pager, next, jumper">
+    </el-pagination>
+
+    <!-- 璇︽儏寮圭獥 -->
+    <el-dialog title="璇曢獙鏁版嵁璇︽儏" :visible.sync="detailVisible" width="600px">
+      <el-form :model="detailData" label-width="120px" size="small" disabled>
+        <el-form-item label="鏍峰搧缂栧彿">
+          <span>{{ detailData.sampleCode }}</span>
+        </el-form-item>
+        <el-form-item label="浜у搧鍚嶇О">
+          <span>{{ detailData.productName }}</span>
+        </el-form-item>
+        <el-form-item label="瑙勬牸鍨嬪彿">
+          <span>{{ detailData.specModel }}</span>
+        </el-form-item>
+        <el-form-item label="璇曢獙绫诲瀷">
+          <span>{{ detailData.testType }}</span>
+        </el-form-item>
+        <el-form-item label="璇曢獙缁撴灉">
+          <span>{{ detailData.testResult }}</span>
+        </el-form-item>
+        <el-form-item label="鍘熸潗鏂�">
+          <span>{{ detailData.rawMaterial }}</span>
+        </el-form-item>
+        <el-form-item label="杩囩▼妫�">
+          <span>{{ detailData.processInspection }}</span>
+        </el-form-item>
+        <el-form-item label="鎴愬搧妫�">
+          <span>{{ detailData.finalInspection }}</span>
+        </el-form-item>
+        <el-form-item label="璇曢獙鏃堕棿">
+          <span>{{ detailData.testDate }}</span>
+        </el-form-item>
+        <el-form-item label="澶囨敞">
+          <span>{{ detailData.remark || "-" }}</span>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="detailVisible = false">鍏抽棴</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  pageHighVoltageCable,
+  pageMediumVoltageCable,
+  pageLowVoltageCable,
+  pageMainNetworkGroundWire,
+  pageDistributionGroundWire,
+  pageOpticalFiber,
+  pageOPGWOpticalFiber,
+  pageADSSOpticalFiber,
+  syncEIPData,
+} from "@/api/quality/eipCable";
+
+export default {
+  name: "EipCable",
+  data() {
+    return {
+      activeTab: "highVoltage",
+      searchForm: {
+        sampleCode: "",
+        testType: "",
+        testDate: "",
+      },
+      tableData: [],
+      tableLoading: false,
+      page: {
+        current: 1,
+        size: 20,
+        total: 0,
+      },
+      detailVisible: false,
+      detailData: {},
+      syncLoading: false,
+    };
+  },
+  mounted() {
+    this.searchList();
+  },
+  methods: {
+    getApi() {
+      switch (this.activeTab) {
+        case "highVoltage":
+          return pageHighVoltageCable;
+        case "mediumVoltage":
+          return pageMediumVoltageCable;
+        case "lowVoltage":
+          return pageLowVoltageCable;
+        case "mainNetwork":
+          return pageMainNetworkGroundWire;
+        case "distribution":
+          return pageDistributionGroundWire;
+        case "opticalFiber":
+          return pageOpticalFiber;
+        case "opgw":
+          return pageOPGWOpticalFiber;
+        case "adss":
+          return pageADSSOpticalFiber;
+        default:
+          return pageHighVoltageCable;
+      }
+    },
+    searchList() {
+      this.tableLoading = true;
+      const api = this.getApi();
+      api({
+        ...this.searchForm,
+        page: this.page.current,
+        size: this.page.size,
+      }).then((res) => {
+        this.tableData = res.data.records;
+        this.page.total = res.data.total;
+        this.tableLoading = false;
+      }).catch((err) => {
+        this.tableLoading = false;
+        console.error(err);
+      });
+    },
+    resetSearch() {
+      this.searchForm = {
+        sampleCode: "",
+        testType: "",
+        testDate: "",
+      };
+      this.searchList();
+    },
+    handleTabClick() {
+      this.page.current = 1;
+      this.searchList();
+    },
+    handleSizeChange(val) {
+      this.page.size = val;
+      this.searchList();
+    },
+    handleCurrentChange(val) {
+      this.page.current = val;
+      this.searchList();
+    },
+    viewDetail(row) {
+      this.detailData = row;
+      this.detailVisible = true;
+    },
+    syncData() {
+      this.syncLoading = true;
+      syncEIPData({ cableType: this.activeTab }).then((res) => {
+        if (res.code === 200) {
+          this.$message.success("鍚屾鎴愬姛");
+          this.searchList();
+        } else {
+          this.$message.error(res.msg || "鍚屾澶辫触");
+        }
+        this.syncLoading = false;
+      }).catch((err) => {
+        this.syncLoading = false;
+        console.error(err);
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.search-form {
+  margin-bottom: 15px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+</style>

--
Gitblit v1.9.3