You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1228 lines
38 KiB

  1. <template>
  2. <div class="customer-css">
  3. <!-- 查询条件 -->
  4. <el-form :inline="true" label-position="top" class="search-form-inline">
  5. <div class="search-row">
  6. <el-form-item label="供应商编码" class="search-item">
  7. <el-input v-model="searchData.supplierNo" style="width: 120px" @keyup.enter.native="getMainData"/>
  8. </el-form-item>
  9. <el-form-item label="供应商名称" class="search-item">
  10. <el-input v-model="searchData.supplierName" style="width: 200px" @keyup.enter.native="getMainData"/>
  11. </el-form-item>
  12. <el-form-item label="反馈单号" class="search-item">
  13. <el-input v-model="searchData.issueNo" style="width: 120px" @keyup.enter.native="getMainData"/>
  14. </el-form-item>
  15. <el-form-item label="问题日期" class="search-item">
  16. <el-date-picker
  17. v-model="searchData.issueDate"
  18. type="date"
  19. value-format="yyyy-MM-dd"
  20. placeholder="选择日期"
  21. style="width: 150px"
  22. clearable>
  23. </el-date-picker>
  24. </el-form-item>
  25. <el-form-item label="状态" class="search-item">
  26. <el-select v-model="searchData.statusDb" clearable placeholder="全部" style="width: 100%">
  27. <el-option label="全部" value="" />
  28. <el-option label="已确认" value="Confirmed" />
  29. <el-option label="已分析" value="Analyzed" />
  30. <el-option label="已关闭" value="Closed" />
  31. <el-option label="已取消" value="Cancelled" />
  32. </el-select>
  33. </el-form-item>
  34. </div>
  35. <div class="search-row">
  36. <el-form-item label=" " class="search-item search-btn-item">
  37. <el-button type="primary" @click="getMainData" class="customer-bun-min">查询</el-button>
  38. <el-button type="primary" @click="addQualityIssue" class="customer-bun-min">新增</el-button>
  39. <el-button type="primary" @click="exportExcel" class="customer-bun-min">导出</el-button>
  40. </el-form-item>
  41. </div>
  42. </el-form>
  43. <el-table
  44. :height="height"
  45. :data="mainDataList"
  46. border
  47. ref="mainTable"
  48. highlight-current-row
  49. @row-click="changeData"
  50. v-loading="dataListLoading"
  51. style="margin-top: 0px; width: 100%;">
  52. <el-table-column
  53. v-for="(item,index) in columnArray1" :key="index"
  54. :sortable="item.columnSortable"
  55. :prop="item.columnProp"
  56. :header-align="item.headerAlign"
  57. :show-overflow-tooltip="item.showOverflowTooltip"
  58. :align="item.align"
  59. :fixed="item.fixed==''?false:item.fixed"
  60. :min-width="item.columnWidth"
  61. :label="item.columnLabel">
  62. <template slot-scope="scope">
  63. <span v-if="!item.columnHidden">{{ scope.row[item.columnProp] }}</span>
  64. <span v-if="item.columnImage"><img :src="scope.row[item.columnProp]"
  65. style="width: 100px; height: 100px"/></span>
  66. </template>
  67. </el-table-column>
  68. <el-table-column fixed="right" header-align="center" align="center" width="180" label="操作">
  69. <template slot-scope="scope">
  70. <template v-if="scope.row.status !== '已回复'">
  71. <a class="customer-a" @click="editQualityIssue(scope.row)">编辑 |</a>
  72. <a class="customer-a" @click="deleteQualityIssue(scope.row)">删除 </a>
  73. <a class="customer-a" @click="replyQualityIssue(scope.row)">| 回复</a>
  74. </template>
  75. </template>
  76. </el-table-column>
  77. </el-table>
  78. <!-- 分页插件 -->
  79. <el-pagination style="margin-top: 0px"
  80. @size-change="sizeChangeHandle"
  81. @current-change="currentChangeHandle"
  82. :current-page="pageIndex"
  83. :page-sizes="[20, 50, 100, 200, 500]"
  84. :page-size="pageSize"
  85. :total="totalPage"
  86. layout="total, sizes, prev, pager, next, jumper">
  87. </el-pagination>
  88. <!-- 详情页签 -->
  89. <el-tabs v-model="activeTab" style="margin-top: 0px; width: 99%;" @tab-click="handleTabClick" class="customer-tab" type="border-card">
  90. <!-- 详情 -->
  91. <el-tab-pane label="详情" name="detail">
  92. <quality-issue-detail :detail-data="currentRow" />
  93. </el-tab-pane>
  94. <!-- 附件 -->
  95. <el-tab-pane label="附件" name="attachment">
  96. <quality-issue-attachment :detail-data="currentRow" :table-height="detailHeight" />
  97. </el-tab-pane>
  98. </el-tabs>
  99. <!-- 新增弹窗 -->
  100. <el-dialog
  101. title="质量问题 - 新增"
  102. :visible.sync="addDialogVisible"
  103. width="45%"
  104. top="10vh"
  105. :close-on-click-modal="false"
  106. @close="handleCloseAddDialog">
  107. <el-form :model="addFormData" :rules="addRules" ref="addFormData" label-width="110px" size="mini" class="add-dialog-form">
  108. <!-- 第一行 -->
  109. <el-row :gutter="10">
  110. <el-col :span="8">
  111. <el-form-item label="反馈单号">
  112. <el-input v-model="addFormData.issueNo" placeholder="自动生成" disabled size="mini"></el-input>
  113. </el-form-item>
  114. </el-col>
  115. <el-col :span="8">
  116. <el-form-item label="问题日期" prop="issueDate">
  117. <el-date-picker
  118. v-model="addFormData.issueDate"
  119. type="date"
  120. value-format="yyyy-MM-dd"
  121. placeholder="选择日期"
  122. size="mini"
  123. style="width: 100%">
  124. </el-date-picker>
  125. </el-form-item>
  126. </el-col>
  127. <el-col :span="8">
  128. <el-form-item label="要求回复日期" prop="requireReplyDate">
  129. <el-date-picker
  130. v-model="addFormData.requireReplyDate"
  131. type="date"
  132. value-format="yyyy-MM-dd"
  133. placeholder="选择日期"
  134. size="mini"
  135. style="width: 100%">
  136. </el-date-picker>
  137. </el-form-item>
  138. </el-col>
  139. </el-row>
  140. <!-- 第二行 -->
  141. <el-row :gutter="10">
  142. <el-col :span="8">
  143. <el-form-item label="供应商编码" prop="supplierNo">
  144. <el-input v-model="addFormData.supplierNo" placeholder="请选择" readonly @click.native="selectSupplier" size="mini">
  145. <i slot="suffix" class="el-icon-search" style="cursor: pointer;"></i>
  146. </el-input>
  147. </el-form-item>
  148. </el-col>
  149. <el-col :span="12">
  150. <el-form-item label="供应商名称">
  151. <el-input v-model="addFormData.supplierName" disabled size="mini"></el-input>
  152. </el-form-item>
  153. </el-col>
  154. </el-row>
  155. <!-- 第三行 -->
  156. <el-row :gutter="10">
  157. <el-col :span="8">
  158. <el-form-item label="问题分类" prop="issueCategory">
  159. <el-select v-model="addFormData.issueCategory" placeholder="请选择" size="mini" style="width: 100%">
  160. <el-option label="产品外观" value="产品外观"></el-option>
  161. <el-option label="产品性能" value="产品性能"></el-option>
  162. <el-option label="尺寸不符" value="尺寸不符"></el-option>
  163. <el-option label="材质问题" value="材质问题"></el-option>
  164. <el-option label="包装破损" value="包装破损"></el-option>
  165. </el-select>
  166. </el-form-item>
  167. </el-col>
  168. </el-row>
  169. <!-- 第四行 -->
  170. <el-row :gutter="10">
  171. <el-col :span="24">
  172. <el-form-item label="问题简述" prop="issueSummary">
  173. <el-input v-model="addFormData.issueSummary" placeholder="请输入问题简述" size="mini"></el-input>
  174. </el-form-item>
  175. </el-col>
  176. </el-row>
  177. <!-- 第五行 -->
  178. <el-row :gutter="10">
  179. <el-col :span="24">
  180. <el-form-item label="问题详细描述">
  181. <el-input
  182. v-model="addFormData.issueDescription"
  183. type="textarea"
  184. :rows="4"
  185. placeholder="请输入问题详细描述"
  186. size="mini">
  187. </el-input>
  188. </el-form-item>
  189. </el-col>
  190. </el-row>
  191. </el-form>
  192. <div slot="footer" class="dialog-footer">
  193. <el-button type="primary" @click="handleSaveAdd" class="customer-bun-min">保存</el-button>
  194. <el-button @click="handleCloseAddDialog" class="customer-bun-min">关闭</el-button>
  195. </div>
  196. </el-dialog>
  197. <!-- 编辑弹窗 -->
  198. <el-dialog
  199. title="质量问题 - 编辑"
  200. :visible.sync="editDialogVisible"
  201. width="45%"
  202. top="10vh"
  203. :close-on-click-modal="false"
  204. @close="handleCloseEditDialog">
  205. <el-form :model="editFormData" :rules="editRules" ref="editFormData" label-width="110px" size="mini" class="add-dialog-form">
  206. <!-- 第一行 -->
  207. <el-row :gutter="10">
  208. <el-col :span="8">
  209. <el-form-item label="反馈单号">
  210. <el-input v-model="editFormData.issueNo" placeholder="自动生成" disabled size="mini"></el-input>
  211. </el-form-item>
  212. </el-col>
  213. <el-col :span="8">
  214. <el-form-item label="问题日期" prop="issueDate">
  215. <el-date-picker
  216. v-model="editFormData.issueDate"
  217. type="date"
  218. value-format="yyyy-MM-dd"
  219. placeholder="选择日期"
  220. size="mini"
  221. style="width: 100%">
  222. </el-date-picker>
  223. </el-form-item>
  224. </el-col>
  225. <el-col :span="8">
  226. <el-form-item label="要求回复日期" prop="requireReplyDate">
  227. <el-date-picker
  228. v-model="editFormData.requireReplyDate"
  229. type="date"
  230. value-format="yyyy-MM-dd"
  231. placeholder="选择日期"
  232. size="mini"
  233. style="width: 100%">
  234. </el-date-picker>
  235. </el-form-item>
  236. </el-col>
  237. </el-row>
  238. <!-- 第二行 -->
  239. <el-row :gutter="10">
  240. <el-col :span="8">
  241. <el-form-item label="供应商编码">
  242. <el-input v-model="editFormData.supplierNo" disabled size="mini"></el-input>
  243. </el-form-item>
  244. </el-col>
  245. <el-col :span="12">
  246. <el-form-item label="供应商名称">
  247. <el-input v-model="editFormData.supplierName" disabled size="mini"></el-input>
  248. </el-form-item>
  249. </el-col>
  250. </el-row>
  251. <!-- 第三行 -->
  252. <el-row :gutter="10">
  253. <el-col :span="8">
  254. <el-form-item label="问题分类" prop="issueCategory">
  255. <el-select v-model="editFormData.issueCategory" placeholder="请选择" size="mini" style="width: 100%">
  256. <el-option label="产品外观" value="产品外观"></el-option>
  257. <el-option label="产品性能" value="产品性能"></el-option>
  258. <el-option label="尺寸不符" value="尺寸不符"></el-option>
  259. <el-option label="材质问题" value="材质问题"></el-option>
  260. <el-option label="包装破损" value="包装破损"></el-option>
  261. </el-select>
  262. </el-form-item>
  263. </el-col>
  264. </el-row>
  265. <!-- 第四行 -->
  266. <el-row :gutter="10">
  267. <el-col :span="24">
  268. <el-form-item label="问题简述" prop="issueSummary">
  269. <el-input v-model="editFormData.issueSummary" placeholder="请输入问题简述" size="mini"></el-input>
  270. </el-form-item>
  271. </el-col>
  272. </el-row>
  273. <!-- 第五行 -->
  274. <el-row :gutter="10">
  275. <el-col :span="24">
  276. <el-form-item label="问题详细描述">
  277. <el-input
  278. v-model="editFormData.issueDescription"
  279. type="textarea"
  280. :rows="4"
  281. placeholder="请输入问题详细描述"
  282. size="mini">
  283. </el-input>
  284. </el-form-item>
  285. </el-col>
  286. </el-row>
  287. </el-form>
  288. <div slot="footer" class="dialog-footer">
  289. <el-button type="primary" @click="handleSaveEdit" class="customer-bun-min">保存</el-button>
  290. <el-button @click="handleCloseEditDialog" class="customer-bun-min">关闭</el-button>
  291. </div>
  292. </el-dialog>
  293. <!-- 回复弹窗 -->
  294. <el-dialog
  295. title="质量问题 - 回复"
  296. :visible.sync="replyDialogVisible"
  297. width="50%"
  298. top="10vh"
  299. :close-on-click-modal="false"
  300. @close="handleCloseReplyDialog">
  301. <div class="reply-dialog-info">
  302. <el-row :gutter="20">
  303. <el-col :span="8">
  304. <div class="info-item">
  305. <span class="info-label">反馈单号</span>
  306. <span class="info-value">{{ replyFormData.issueNo }}</span>
  307. </div>
  308. </el-col>
  309. <el-col :span="8">
  310. <div class="info-item">
  311. <span class="info-label">回复日期</span>
  312. <span class="info-value">{{ replyFormData.replyTime }}</span>
  313. </div>
  314. </el-col>
  315. <el-col :span="8">
  316. <div class="info-item">
  317. <span class="info-label">回复人</span>
  318. <span class="info-value">{{ replyFormData.replyBy }}</span>
  319. </div>
  320. </el-col>
  321. </el-row>
  322. </div>
  323. <el-form :model="replyFormData" :rules="replyRules" ref="replyFormData" label-position="top" size="mini" class="reply-dialog-form">
  324. <!-- 原因分析 -->
  325. <el-form-item label="原因分析" prop="analysis">
  326. <el-input
  327. v-model="replyFormData.analysis"
  328. type="textarea"
  329. :rows="4"
  330. placeholder="请输入原因分析"
  331. size="mini">
  332. </el-input>
  333. </el-form-item>
  334. <!-- 后续措施 -->
  335. <el-form-item label="后续措施" prop="correctiveAction">
  336. <el-input
  337. v-model="replyFormData.correctiveAction"
  338. type="textarea"
  339. :rows="4"
  340. placeholder="请输入后续措施"
  341. size="mini">
  342. </el-input>
  343. </el-form-item>
  344. </el-form>
  345. <div slot="footer" class="dialog-footer">
  346. <el-button type="primary" @click="handleSaveReply" class="customer-bun-min">保存</el-button>
  347. <el-button @click="handleCloseReplyDialog" class="customer-bun-min">关闭</el-button>
  348. </div>
  349. </el-dialog>
  350. <Chooselist ref="baseList" @getBaseData="getBaseData"></Chooselist>
  351. </div>
  352. </template>
  353. <script>
  354. import { queryQualityIssuePage, saveQualityIssue,deleteQualityIssue,updateQualityIssue, saveReply } from '@/api/quality/qualityIssue.js'
  355. import Chooselist from '@/views/modules/common/Chooselist_eam'
  356. import ComQualityIssueDetail from './com_qualityIssueDetail.vue'
  357. import ComQualityIssueAttachment from './com_qualityIssueAttachment.vue'
  358. import excel from '@/utils/excel-util.js'
  359. export default {
  360. components: {
  361. Chooselist,
  362. QualityIssueDetail: ComQualityIssueDetail,
  363. QualityIssueAttachment: ComQualityIssueAttachment
  364. },
  365. data () {
  366. return {
  367. functionId: this.$route.meta.menuId,
  368. height: 400,
  369. detailHeight: 400,
  370. currentRow: {},
  371. activeTab: 'detail',
  372. // 新增弹窗相关数据
  373. addDialogVisible: false,
  374. addFormData: {
  375. issueNo: '',
  376. issueDate: '',
  377. requireReplyDate: '',
  378. supplierNo: '',
  379. supplierName: '',
  380. issueCategory: '',
  381. issueSummary: '',
  382. issueDescription: ''
  383. },
  384. addRules: {
  385. issueDate: [
  386. { required: true, message: '请选择问题日期', trigger: 'change' }
  387. ],
  388. requireReplyDate: [
  389. { required: true, message: '请选择要求回复日期', trigger: 'change' }
  390. ],
  391. supplierNo: [
  392. { required: true, message: '请选择供应商', trigger: 'change' }
  393. ],
  394. issueCategory: [
  395. { required: true, message: '请选择问题分类', trigger: 'change' }
  396. ],
  397. issueSummary: [
  398. { required: true, message: '请输入问题简述', trigger: 'blur' }
  399. ]
  400. },
  401. // 编辑弹窗相关数据
  402. editDialogVisible: false,
  403. editFormData: {
  404. issueNo: '',
  405. issueDate: '',
  406. requireReplyDate: '',
  407. supplierNo: '',
  408. supplierName: '',
  409. issueCategory: '',
  410. issueSummary: '',
  411. issueDescription: '',
  412. site: ''
  413. },
  414. editRules: {
  415. issueDate: [
  416. { required: true, message: '请选择问题日期', trigger: 'change' }
  417. ],
  418. requireReplyDate: [
  419. { required: true, message: '请选择要求回复日期', trigger: 'change' }
  420. ],
  421. issueCategory: [
  422. { required: true, message: '请选择问题分类', trigger: 'change' }
  423. ],
  424. issueSummary: [
  425. { required: true, message: '请输入问题简述', trigger: 'blur' }
  426. ]
  427. },
  428. // 回复弹窗相关数据
  429. replyDialogVisible: false,
  430. replyFormData: {
  431. site: '',
  432. issueNo: '',
  433. analysis: '',
  434. correctiveAction: '',
  435. replyBy: '',
  436. replyTime: ''
  437. },
  438. replyRules: {
  439. analysis: [
  440. { required: true, message: '请输入原因分析', trigger: 'blur' }
  441. ],
  442. correctiveAction: [
  443. { required: true, message: '请输入后续措施', trigger: 'blur' }
  444. ]
  445. },
  446. tagNo: '',
  447. searchData: {
  448. issueNo: '',
  449. supplierNo: '',
  450. supplierName: '',
  451. issueCategory: '',
  452. statusDb: '',
  453. issueDate: '',
  454. page: 1,
  455. limit: 50
  456. },
  457. searchType: '',
  458. pageIndex: 1,
  459. pageSize: 50,
  460. totalPage: 0,
  461. mainDataList: [],
  462. dataListLoading: false,
  463. columnArray1: [
  464. {
  465. userId: this.$store.state.user.name,
  466. functionId: this.functionId,
  467. serialNumber: 'QualityIssueTable1IssueNo',
  468. tableId: 'QualityIssueTable1',
  469. tableName: '质量问题',
  470. columnProp: 'issueNo',
  471. headerAlign: 'center',
  472. align: 'left',
  473. columnLabel: '反馈单号',
  474. columnWidth: '120',
  475. columnHidden: false,
  476. columnImage: false,
  477. columnSortable: false,
  478. sortLv: 0,
  479. status: true,
  480. fixed: false
  481. },
  482. {
  483. userId: this.$store.state.user.name,
  484. functionId: this.functionId,
  485. serialNumber: 'QualityIssueTable1IssueDate',
  486. tableId: 'QualityIssueTable1',
  487. tableName: '质量问题',
  488. columnProp: 'issueDate',
  489. headerAlign: 'center',
  490. align: 'center',
  491. columnLabel: '问题日期',
  492. columnWidth: '120',
  493. columnHidden: false,
  494. columnImage: false,
  495. columnSortable: false,
  496. sortLv: 0,
  497. status: true,
  498. fixed: false
  499. },
  500. {
  501. userId: this.$store.state.user.name,
  502. functionId: this.functionId,
  503. serialNumber: 'QualityIssueTable1SupplierNo',
  504. tableId: 'QualityIssueTable1',
  505. tableName: '质量问题',
  506. columnProp: 'supplierNo',
  507. headerAlign: 'center',
  508. align: 'left',
  509. columnLabel: '供应商编码',
  510. columnWidth: '120',
  511. columnHidden: false,
  512. columnImage: false,
  513. columnSortable: false,
  514. sortLv: 0,
  515. status: true,
  516. fixed: false
  517. },
  518. {
  519. userId: this.$store.state.user.name,
  520. functionId: this.functionId,
  521. serialNumber: 'QualityIssueTable1SupplierName',
  522. tableId: 'QualityIssueTable1',
  523. tableName: '质量问题',
  524. columnProp: 'supplierName',
  525. headerAlign: 'center',
  526. align: 'left',
  527. columnLabel: '供应商名称',
  528. columnWidth: '150',
  529. columnHidden: false,
  530. columnImage: false,
  531. columnSortable: false,
  532. sortLv: 0,
  533. status: true,
  534. fixed: false
  535. },
  536. {
  537. userId: this.$store.state.user.name,
  538. functionId: this.functionId,
  539. serialNumber: 'QualityIssueTable1IssueCategory',
  540. tableId: 'QualityIssueTable1',
  541. tableName: '质量问题',
  542. columnProp: 'issueCategory',
  543. headerAlign: 'center',
  544. align: 'left',
  545. columnLabel: '问题分类',
  546. columnWidth: '120',
  547. columnHidden: false,
  548. columnImage: false,
  549. columnSortable: false,
  550. sortLv: 0,
  551. status: true,
  552. fixed: false
  553. },
  554. {
  555. userId: this.$store.state.user.name,
  556. functionId: this.functionId,
  557. serialNumber: 'QualityIssueTable1IssueSummary',
  558. tableId: 'QualityIssueTable1',
  559. tableName: '质量问题',
  560. columnProp: 'issueSummary',
  561. headerAlign: 'center',
  562. align: 'left',
  563. columnLabel: '问题简述',
  564. columnWidth: '200',
  565. columnHidden: false,
  566. columnImage: false,
  567. columnSortable: false,
  568. sortLv: 0,
  569. status: true,
  570. fixed: false
  571. },
  572. {
  573. userId: this.$store.state.user.name,
  574. functionId: this.functionId,
  575. serialNumber: 'QualityIssueTable1Status',
  576. tableId: 'QualityIssueTable1',
  577. tableName: '质量问题',
  578. columnProp: 'status',
  579. headerAlign: 'center',
  580. align: 'center',
  581. columnLabel: '状态',
  582. columnWidth: '100',
  583. columnHidden: false,
  584. columnImage: false,
  585. columnSortable: false,
  586. sortLv: 0,
  587. status: true,
  588. fixed: false
  589. },
  590. {
  591. userId: this.$store.state.user.name,
  592. functionId: this.functionId,
  593. serialNumber: 'QualityIssueTable1CreateBy',
  594. tableId: 'QualityIssueTable1',
  595. tableName: '质量问题',
  596. columnProp: 'createBy',
  597. headerAlign: 'center',
  598. align: 'left',
  599. columnLabel: '录入人',
  600. columnWidth: '100',
  601. columnHidden: false,
  602. columnImage: false,
  603. columnSortable: false,
  604. sortLv: 0,
  605. status: true,
  606. fixed: false
  607. },
  608. {
  609. userId: this.$store.state.user.name,
  610. functionId: this.functionId,
  611. serialNumber: 'QualityIssueTable1CreateDate',
  612. tableId: 'QualityIssueTable1',
  613. tableName: '质量问题',
  614. columnProp: 'createDate',
  615. headerAlign: 'center',
  616. align: 'center',
  617. columnLabel: '录入时间',
  618. columnWidth: '150',
  619. columnHidden: false,
  620. columnImage: false,
  621. columnSortable: false,
  622. sortLv: 0,
  623. status: true,
  624. fixed: false
  625. }
  626. ]
  627. }
  628. },
  629. mounted () {
  630. this.$nextTick(() => {
  631. this.height = (window.innerHeight - 220) / 2
  632. this.detailHeight = (window.innerHeight - 220) / 2
  633. this.getMainData()
  634. })
  635. },
  636. methods: {
  637. // 获取基础数据列表
  638. getBaseList (val, type) {
  639. this.tagNo = val
  640. this.searchType = type || ''
  641. this.$nextTick(() => {
  642. let strVal = ''
  643. let conSql = ''
  644. if (val === 1100) {
  645. strVal = this.addFormData.supplierNo || ''
  646. conSql = " and site = '" + this.$store.state.user.site + "'"
  647. }
  648. this.$refs.baseList.init(val, strVal, conSql)
  649. })
  650. },
  651. /* 列表方法的回调 */
  652. getBaseData (val) {
  653. if (this.tagNo === 1100) {
  654. // 新增弹窗:使用下划线命名的字段,使用$set确保响应式
  655. this.$set(this.addFormData, 'supplierNo', val.supplier_no || '')
  656. this.$set(this.addFormData, 'supplierName', val.supplier_name || '')
  657. }
  658. },
  659. // 查询数据
  660. getMainData () {
  661. this.searchData.limit = this.pageSize
  662. this.searchData.page = this.pageIndex
  663. this.searchData.site = this.$store.state.user.site
  664. this.dataListLoading = true
  665. queryQualityIssuePage(this.searchData).then(({ data }) => {
  666. if (data.code === 0) {
  667. this.mainDataList = data.page.list
  668. this.pageIndex = data.page.currPage
  669. this.pageSize = data.page.pageSize
  670. this.totalPage = data.page.totalCount
  671. this.$nextTick(() => {
  672. if (this.$refs.mainTable) {
  673. this.$refs.mainTable.clearSelection()
  674. }
  675. })
  676. // 判断是否有数据
  677. if (this.mainDataList.length > 0) {
  678. this.$refs.mainTable.setCurrentRow(this.mainDataList[0])
  679. this.changeData(this.mainDataList[0])
  680. } else {
  681. this.changeData(null)
  682. }
  683. }
  684. this.dataListLoading = false
  685. }).catch(() => {
  686. this.dataListLoading = false
  687. })
  688. },
  689. // 每页数
  690. sizeChangeHandle (val) {
  691. this.pageSize = val
  692. this.pageIndex = 1
  693. this.getMainData()
  694. },
  695. // 当前页
  696. currentChangeHandle (val) {
  697. this.pageIndex = val
  698. this.getMainData()
  699. },
  700. // 页签点击事件
  701. handleTabClick (tab) {
  702. // 每次点击页签都触发对应页签的查询
  703. if (tab.name === 'detail') {
  704. // 详情页签
  705. } else if (tab.name === 'attachment') {
  706. // 附件页签
  707. this.$nextTick(() => {
  708. if (this.$refs.attachmentTab) {
  709. this.$refs.attachmentTab.loadAttachmentList()
  710. }
  711. })
  712. }
  713. },
  714. // 行点击事件
  715. changeData (row) {
  716. this.currentRow = row ? JSON.parse(JSON.stringify(row)) : {}
  717. },
  718. // 新增质量问题
  719. addQualityIssue () {
  720. this.addDialogVisible = true
  721. this.resetAddForm()
  722. },
  723. // 关闭新增弹窗
  724. handleCloseAddDialog () {
  725. this.addDialogVisible = false
  726. this.resetAddForm()
  727. },
  728. // 关闭编辑弹窗
  729. handleCloseEditDialog () {
  730. this.editDialogVisible = false
  731. this.resetEditForm()
  732. },
  733. // 重置表单
  734. resetAddForm () {
  735. const today = new Date()
  736. const year = today.getFullYear()
  737. const month = String(today.getMonth() + 1).padStart(2, '0')
  738. const day = String(today.getDate()).padStart(2, '0')
  739. const todayStr = `${year}-${month}-${day}`
  740. this.addFormData = {
  741. issueNo: '',
  742. issueDate: todayStr,
  743. requireReplyDate: '',
  744. supplierNo: '',
  745. supplierName: '',
  746. issueCategory: '',
  747. issueSummary: '',
  748. issueDescription: ''
  749. }
  750. if (this.$refs.addFormData) {
  751. this.$refs.addFormData.clearValidate()
  752. }
  753. },
  754. // 重置编辑表单
  755. resetEditForm () {
  756. this.editFormData = {
  757. issueNo: '',
  758. issueDate: '',
  759. requireReplyDate: '',
  760. supplierNo: '',
  761. supplierName: '',
  762. issueCategory: '',
  763. issueSummary: '',
  764. issueDescription: '',
  765. site: ''
  766. }
  767. if (this.$refs.currentFormData) {
  768. this.$refs.currentFormData.clearValidate()
  769. }
  770. },
  771. // 选择供应商(仅新增模式)
  772. selectSupplier () {
  773. this.tagNo = 1100
  774. this.$nextTick(() => {
  775. const conSql = " and site = '" + this.$store.state.user.site + "'"
  776. this.$refs.baseList.init(1100, this.addFormData.supplierNo || '', conSql)
  777. })
  778. },
  779. // 保存新增
  780. handleSaveAdd () {
  781. this.$refs.addFormData.validate((valid) => {
  782. if (valid) {
  783. // 构建提交数据
  784. const submitData = {
  785. issueDate: this.addFormData.issueDate,
  786. requireReplyDate: this.addFormData.requireReplyDate,
  787. supplierNo: this.addFormData.supplierNo,
  788. supplierName: this.addFormData.supplierName,
  789. issueCategory: this.addFormData.issueCategory,
  790. issueSummary: this.addFormData.issueSummary,
  791. issueDescription: this.addFormData.issueDescription,
  792. site: this.$store.state.user.site
  793. }
  794. console.log('提交数据:', submitData)
  795. saveQualityIssue(submitData).then(({ data }) => {
  796. console.log('保存接口返回:', data)
  797. if (data.code === 0) {
  798. this.$message.success('保存成功')
  799. this.handleCloseAddDialog()
  800. this.getMainData()
  801. } else {
  802. this.$message.error(data.msg || '保存失败')
  803. }
  804. }).catch((error) => {
  805. console.error('保存接口错误:', error)
  806. this.$message.error('保存失败,请稍后重试')
  807. })
  808. } else {
  809. console.log('表单验证失败')
  810. this.$message.warning('请填写完整的表单信息')
  811. }
  812. })
  813. },
  814. // 保存编辑
  815. handleSaveEdit () {
  816. this.$refs.editFormData.validate((valid) => {
  817. if (valid) {
  818. // 构建提交数据
  819. const submitData = {
  820. site: this.editFormData.site,
  821. issueNo: this.editFormData.issueNo,
  822. issueDate: this.editFormData.issueDate,
  823. requireReplyDate: this.editFormData.requireReplyDate,
  824. issueCategory: this.editFormData.issueCategory,
  825. issueSummary: this.editFormData.issueSummary,
  826. issueDescription: this.editFormData.issueDescription
  827. }
  828. console.log('更新数据:', submitData)
  829. updateQualityIssue(submitData).then(({ data }) => {
  830. console.log('更新接口返回:', data)
  831. if (data.code === 0) {
  832. this.$message.success('更新成功')
  833. this.handleCloseEditDialog()
  834. this.getMainData()
  835. } else {
  836. this.$message.error(data.msg || '更新失败')
  837. }
  838. }).catch((error) => {
  839. console.error('更新接口错误:', error)
  840. this.$message.error('更新失败,请稍后重试')
  841. })
  842. } else {
  843. console.log('表单验证失败')
  844. this.$message.warning('请填写完整的表单信息')
  845. }
  846. })
  847. },
  848. // 编辑质量问题
  849. editQualityIssue (row) {
  850. this.editDialogVisible = true
  851. // 自动填充表格中的数据
  852. this.editFormData = {
  853. issueNo: row.issueNo || '',
  854. issueDate: row.issueDate || '',
  855. requireReplyDate: row.requireReplyDate || '',
  856. supplierNo: row.supplierNo || '',
  857. supplierName: row.supplierName || '',
  858. issueCategory: row.issueCategory || '',
  859. issueSummary: row.issueSummary || '',
  860. issueDescription: row.issueDescription || '',
  861. site: row.site || this.$store.state.user.site
  862. }
  863. // 清除验证状态
  864. this.$nextTick(() => {
  865. if (this.$refs.editFormData) {
  866. this.$refs.editFormData.clearValidate()
  867. }
  868. })
  869. },
  870. // 删除质量问题
  871. deleteQualityIssue(row) {
  872. this.$confirm('确定要删除该质量问题吗?删除后无法恢复!', '提示', {
  873. confirmButtonText: '确定删除',
  874. cancelButtonText: '取消',
  875. type: 'warning',
  876. dangerouslyUseHTMLString: true
  877. }).then(() => {
  878. // 显示加载中
  879. const loading = this.$loading({
  880. lock: true,
  881. text: '删除中...',
  882. spinner: 'el-icon-loading',
  883. background: 'rgba(0, 0, 0, 0.7)'
  884. });
  885. // 构建删除参数
  886. const deleteParams = {
  887. site: row.site || this.$store.state.user.site,
  888. issueNo: row.issueNo
  889. };
  890. console.log('删除参数:', deleteParams);
  891. // 调用删除接口
  892. deleteQualityIssue(deleteParams).then(({ data }) => {
  893. loading.close();
  894. if (data.code === 0) {
  895. this.$message.success('删除成功');
  896. // 判断当前页是否还有数据
  897. const isLastItem = this.mainDataList.length === 1;
  898. // 刷新列表
  899. if (isLastItem && this.pageIndex > 1) {
  900. // 如果是最后一页的最后一条数据,跳转到上一页
  901. this.pageIndex--;
  902. }
  903. this.getMainData();
  904. } else {
  905. this.$message.error(data.msg || '删除失败');
  906. }
  907. }).catch((error) => {
  908. loading.close();
  909. console.error('删除接口错误:', error);
  910. this.$message.error('删除失败,请稍后重试');
  911. });
  912. }).catch(() => {
  913. this.$message.info('已取消删除');
  914. });
  915. },
  916. // 回复质量问题
  917. replyQualityIssue (row) {
  918. this.replyDialogVisible = true
  919. // 自动填充表格中的数据
  920. const now = new Date()
  921. const year = now.getFullYear()
  922. const month = String(now.getMonth() + 1).padStart(2, '0')
  923. const day = String(now.getDate()).padStart(2, '0')
  924. const currentDate = `${year}-${month}-${day}`
  925. this.replyFormData = {
  926. site: row.site || this.$store.state.user.site,
  927. issueNo: row.issueNo || '',
  928. analysis: '',
  929. correctiveAction: '',
  930. replyBy: this.$store.state.user.name || '',
  931. replyTime: currentDate
  932. }
  933. // 清除验证状态
  934. this.$nextTick(() => {
  935. if (this.$refs.replyFormData) {
  936. this.$refs.replyFormData.clearValidate()
  937. }
  938. })
  939. },
  940. // 关闭回复弹窗
  941. handleCloseReplyDialog () {
  942. this.replyDialogVisible = false
  943. this.resetReplyForm()
  944. },
  945. // 重置回复表单
  946. resetReplyForm () {
  947. this.replyFormData = {
  948. site: '',
  949. issueNo: '',
  950. analysis: '',
  951. correctiveAction: '',
  952. replyBy: '',
  953. replyTime: ''
  954. }
  955. if (this.$refs.replyFormData) {
  956. this.$refs.replyFormData.clearValidate()
  957. }
  958. },
  959. // 保存回复
  960. handleSaveReply () {
  961. this.$refs.replyFormData.validate((valid) => {
  962. if (valid) {
  963. // 构建提交数据
  964. const submitData = {
  965. site: this.replyFormData.site,
  966. issueNo: this.replyFormData.issueNo,
  967. analysis: this.replyFormData.analysis,
  968. correctiveAction: this.replyFormData.correctiveAction
  969. }
  970. console.log('回复数据:', submitData)
  971. saveReply(submitData).then(({ data }) => {
  972. console.log('回复接口返回:', data)
  973. if (data.code === 0) {
  974. this.$message.success('回复成功')
  975. this.handleCloseReplyDialog()
  976. this.getMainData()
  977. } else {
  978. this.$message.error(data.msg || '回复失败')
  979. }
  980. }).catch((error) => {
  981. console.error('回复接口错误:', error)
  982. this.$message.error('回复失败,请稍后重试')
  983. })
  984. } else {
  985. console.log('表单验证失败')
  986. this.$message.warning('请填写完整的回复信息')
  987. }
  988. })
  989. },
  990. // 导出
  991. exportExcel () {
  992. console.log('开始导出...')
  993. // 生成文件名(使用原生 Date)
  994. const now = new Date()
  995. const year = now.getFullYear()
  996. const month = String(now.getMonth() + 1).padStart(2, '0')
  997. const day = String(now.getDate()).padStart(2, '0')
  998. const hour = String(now.getHours()).padStart(2, '0')
  999. const minute = String(now.getMinutes()).padStart(2, '0')
  1000. const second = String(now.getSeconds()).padStart(2, '0')
  1001. const exportName = `质量问题${year}${month}${day}${hour}${minute}${second}`
  1002. console.log('导出参数:', this.searchData)
  1003. // 获取当前查询条件
  1004. const exportParams = {
  1005. ...this.searchData,
  1006. limit: -1, // 导出全部数据
  1007. page: 1
  1008. }
  1009. try {
  1010. excel.exportTable({
  1011. url: '/srm/qualityIssue/queryPage',
  1012. columnMapping: this.columnArray1,
  1013. mergeSetting: [],
  1014. params: exportParams,
  1015. fileName: exportName + '.xlsx',
  1016. rowFetcher: res => {
  1017. console.log('导出数据响应:', res)
  1018. return res.data.page.list
  1019. },
  1020. columnFormatter: [],
  1021. dropColumns: []
  1022. })
  1023. console.log('导出请求已发送')
  1024. } catch (error) {
  1025. console.error('导出失败:', error)
  1026. this.$message.error('导出失败: ' + error.message)
  1027. }
  1028. }
  1029. },
  1030. created () {
  1031. this.getMainData()
  1032. }
  1033. }
  1034. </script>
  1035. <style scoped lang="scss">
  1036. .search-form-inline {
  1037. background: #fff;
  1038. }
  1039. .search-row {
  1040. display: flex;
  1041. align-items: flex-end;
  1042. flex-wrap: nowrap;
  1043. gap: 15px;
  1044. }
  1045. .search-row:last-child {
  1046. margin-top: -10px;
  1047. }
  1048. .search-item {
  1049. flex: none;
  1050. margin-bottom: 10px;
  1051. }
  1052. .search-btn-item {
  1053. flex: none;
  1054. margin-bottom: 10px;
  1055. }
  1056. .search-btn-item /deep/ .el-form-item__content {
  1057. line-height: normal;
  1058. }
  1059. .search-item /deep/ .el-form-item__label {
  1060. font-size: 13px;
  1061. color: #606266;
  1062. padding-bottom: 5px;
  1063. line-height: 1;
  1064. height: auto;
  1065. }
  1066. .search-item /deep/ .el-form-item__content {
  1067. line-height: normal;
  1068. }
  1069. .date-range {
  1070. display: flex;
  1071. align-items: center;
  1072. }
  1073. .split {
  1074. padding: 0 6px;
  1075. color: #606266;
  1076. font-size: 13px;
  1077. }
  1078. /deep/ .customer-tab .el-tabs__content {
  1079. padding: 5px !important;
  1080. }
  1081. .add-dialog-form /deep/ .el-form-item {
  1082. margin-bottom: 10px;
  1083. }
  1084. .add-dialog-form /deep/ .el-form-item__label {
  1085. text-align: left;
  1086. float: none;
  1087. display: block;
  1088. padding: 0 0 5px 0;
  1089. line-height: 1;
  1090. font-size: 13px;
  1091. }
  1092. .add-dialog-form /deep/ .el-form-item__content {
  1093. margin-left: 0 !important;
  1094. }
  1095. .dialog-footer {
  1096. text-align: center;
  1097. }
  1098. /* 回复弹窗样式 */
  1099. .reply-dialog-info {
  1100. margin-bottom: 20px;
  1101. padding: 15px;
  1102. background-color: #f5f7fa;
  1103. border-radius: 4px;
  1104. }
  1105. .reply-dialog-info .info-item {
  1106. display: flex;
  1107. align-items: center;
  1108. margin-bottom: 10px;
  1109. }
  1110. .reply-dialog-info .info-item:last-child {
  1111. margin-bottom: 0;
  1112. }
  1113. .reply-dialog-info .info-label {
  1114. font-size: 13px;
  1115. color: #606266;
  1116. font-weight: 500;
  1117. min-width: 80px;
  1118. }
  1119. .reply-dialog-info .info-value {
  1120. font-size: 13px;
  1121. color: #303133;
  1122. flex: 1;
  1123. }
  1124. .reply-dialog-form /deep/ .el-form-item {
  1125. margin-bottom: 15px;
  1126. }
  1127. .reply-dialog-form /deep/ .el-form-item__label {
  1128. font-size: 13px;
  1129. color: #606266;
  1130. font-weight: 500;
  1131. padding-bottom: 5px;
  1132. line-height: 1;
  1133. height: auto;
  1134. }
  1135. .reply-dialog-form /deep/ .el-form-item__content {
  1136. line-height: normal;
  1137. }
  1138. </style>