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.

1049 lines
39 KiB

  1. <template>
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  4. <el-form-item label="真实姓名" prop="realName">
  5. <el-input
  6. v-model="queryParams.realName"
  7. placeholder="请输入真实姓名"
  8. clearable
  9. @keyup.enter.native="handleQuery"
  10. />
  11. </el-form-item>
  12. <el-form-item label="身份证号" prop="idCard">
  13. <el-input
  14. v-model="queryParams.idCard"
  15. placeholder="请输入身份证号"
  16. clearable
  17. @keyup.enter.native="handleQuery"
  18. />
  19. </el-form-item>
  20. <el-form-item label="资质类型" prop="qualificationType">
  21. <el-select
  22. v-model="queryParams.qualificationType"
  23. placeholder="请选择资质类型"
  24. style="width: 100%;"
  25. @keyup.enter.native="handleQuery"
  26. >
  27. <el-option
  28. v-for="dict in dict.type.qualification_type"
  29. :key="dict.value"
  30. :label="dict.label"
  31. :value="dict.value"
  32. />
  33. </el-select>
  34. </el-form-item>
  35. <!-- <el-form-item label="资质类型" prop="qualificationType">-->
  36. <!-- <el-input-->
  37. <!-- v-model="queryParams.qualificationType"-->
  38. <!-- placeholder="请输入资质类型"-->
  39. <!-- clearable-->
  40. <!-- @keyup.enter.native="handleQuery"-->
  41. <!-- />-->
  42. <!-- </el-form-item>-->
  43. <!-- <el-form-item label="证书编号" prop="certificateNo">-->
  44. <!-- <el-input-->
  45. <!-- v-model="queryParams.certificateNo"-->
  46. <!-- placeholder="请输入证书编号"-->
  47. <!-- clearable-->
  48. <!-- @keyup.enter.native="handleQuery"-->
  49. <!-- />-->
  50. <!-- </el-form-item>-->
  51. <el-form-item label="审核状态" prop="auditStatus">
  52. <el-select v-model="queryParams.auditStatus" placeholder="审核状态" clearable style="width: 100px">
  53. <el-option
  54. v-for="dict in dict.type.qualification_shenhe"
  55. :key="dict.value"
  56. :label="dict.label"
  57. :value="dict.value"
  58. />
  59. </el-select>
  60. </el-form-item>
  61. <el-form-item>
  62. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  63. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  64. </el-form-item>
  65. </el-form>
  66. <el-row :gutter="10" class="mb8">
  67. <el-col :span="1.5">
  68. <el-button
  69. type="primary"
  70. plain
  71. icon="el-icon-plus"
  72. size="mini"
  73. @click="handleAdd"
  74. v-hasPermi="['vet:qualification:add']"
  75. >新增</el-button>
  76. </el-col>
  77. <el-col :span="1.5">
  78. <el-button
  79. type="success"
  80. plain
  81. icon="el-icon-edit"
  82. size="mini"
  83. :disabled="single"
  84. @click="handleUpdate"
  85. v-hasPermi="['vet:qualification:edit']"
  86. >修改</el-button>
  87. </el-col>
  88. <el-col :span="1.5">
  89. <el-button
  90. type="danger"
  91. plain
  92. icon="el-icon-delete"
  93. size="mini"
  94. :disabled="multiple"
  95. @click="handleDelete"
  96. v-hasPermi="['vet:qualification:remove']"
  97. >删除</el-button>
  98. </el-col>
  99. <!-- <el-col :span="1.5">-->
  100. <!-- <el-button-->
  101. <!-- type="warning"-->
  102. <!-- plain-->
  103. <!-- icon="el-icon-download"-->
  104. <!-- size="mini"-->
  105. <!-- @click="handleExport"-->
  106. <!-- v-hasPermi="['vet:qualification:export']"-->
  107. <!-- >导出</el-button>-->
  108. <!-- </el-col>-->
  109. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  110. </el-row>
  111. <el-table v-loading="loading" :data="qualificationList" @selection-change="handleSelectionChange">
  112. <el-table-column type="selection" width="55" align="center" />
  113. <!-- <el-table-column label="资质ID" align="center" prop="qualificationId" v-if="false" />-->
  114. <!-- <el-table-column label="真实姓名" align="center" prop="realName" />-->
  115. <!-- <el-table-column label="身份证号" align="center" prop="idCard" />-->
  116. <el-table-column label="真实姓名" align="center" prop="realName" width="150">
  117. <template slot-scope="scope">
  118. <span v-if="scope.row.realName">{{ scope.row.realName }}</span>
  119. <span v-else style="color: #909399">-</span>
  120. </template>
  121. </el-table-column>
  122. <el-table-column label="身份证号" align="center" prop="idCard" width="150">
  123. <template slot-scope="scope">
  124. <span v-if="scope.row.idCard">{{ scope.row.idCard }}</span>
  125. <span v-else style="color: #909399">-</span>
  126. </template>
  127. </el-table-column>
  128. <el-table-column label="资质类型" align="center" prop="qualificationType" width="120">
  129. <template slot-scope="scope">
  130. <span>{{ formatQualificationType(scope.row.qualificationType) }}</span>
  131. </template>
  132. </el-table-column>
  133. <!-- <el-table-column label="证书编号" align="center" prop="certificateNo" />-->
  134. <!-- <el-table-column label="证书编号" align="center" prop="certificateNo" width="150">-->
  135. <!-- <template slot-scope="scope">-->
  136. <!-- <span v-if="scope.row.certificateNo">{{ scope.row.certificateNo }}</span>-->
  137. <!-- <span v-else style="color: #909399">-</span>-->
  138. <!-- </template>-->
  139. <!-- </el-table-column>-->
  140. <!-- &lt;!&ndash; 新增的证书字段 &ndash;&gt;-->
  141. <!-- <el-table-column label="证书名称" align="center" prop="certName" width="150">-->
  142. <!-- <template slot-scope="scope">-->
  143. <!-- <span v-if="scope.row.certName">{{ scope.row.certName }}</span>-->
  144. <!-- <span v-else style="color: #909399">-</span>-->
  145. <!-- </template>-->
  146. <!-- </el-table-column>-->
  147. <!-- <el-table-column label="发证机构" align="center" prop="issueOrg" width="150">-->
  148. <!-- <template slot-scope="scope">-->
  149. <!-- <span v-if="scope.row.issueOrg">{{ scope.row.issueOrg }}</span>-->
  150. <!-- <span v-else style="color: #909399">-</span>-->
  151. <!-- </template>-->
  152. <!-- </el-table-column>-->
  153. <!-- <el-table-column label="证书文件" prop="certificateFiles">-->
  154. <!-- <template slot-scope="scope">-->
  155. <!--&lt;!&ndash; <span v-if="scope.row.certificateFiles">{{ scope.row.certificateFiles }}</span>&ndash;&gt;-->
  156. <!-- <span v-if="scope.row.certificateFiles">{{ getImageUrl(scope.row.certificateFiles) }}</span>-->
  157. <!-- <span v-else style="color: #909399">-</span>-->
  158. <!-- </template>-->
  159. <!-- </el-table-column>-->
  160. <!-- <el-table-column label="到期日期" align="center" prop="expireDate" width="180">-->
  161. <!-- <template slot-scope="scope">-->
  162. <!-- <span v-if="scope.row.expireDate">{{ parseTime(scope.row.expireDate, '{y}-{m}-{d}') }}</span>-->
  163. <!-- <span v-else style="color: #909399">-</span>-->
  164. <!-- </template>-->
  165. <!-- </el-table-column>-->
  166. <!-- <el-table-column label="证书状态" align="center" prop="certStatus" width="100">-->
  167. <!-- <template slot-scope="scope">-->
  168. <!-- <el-tag :type="getCertStatusType(scope.row.certStatus)" size="small">-->
  169. <!-- {{ getCertStatusLabel(scope.row.certStatus) }}-->
  170. <!-- </el-tag>-->
  171. <!-- </template>-->
  172. <!-- </el-table-column>-->
  173. <el-table-column label="申请时间" align="center" prop="applyTime" width="180">
  174. <template slot-scope="scope">
  175. <span v-if="scope.row.applyTime">{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
  176. <span v-else style="color: #909399">-</span>
  177. </template>
  178. </el-table-column>
  179. <el-table-column label="审核时间" align="center" prop="auditTime" width="180">
  180. <template slot-scope="scope">
  181. <span v-if="scope.row.auditTime">{{ parseTime(scope.row.auditTime, '{y}-{m}-{d}') }}</span>
  182. <span v-else style="color: #909399">-</span>
  183. </template>
  184. </el-table-column>
  185. <el-table-column label="审核状态" align="center" prop="auditStatus" width="100">
  186. <template slot-scope="scope">
  187. <el-tag :type="getAuditStatusType(scope.row.auditStatus)" size="small">
  188. {{ getDictLabel('qualification_shenhe', scope.row.auditStatus) }}
  189. </el-tag>
  190. </template>
  191. </el-table-column>
  192. <el-table-column label="备注" align="center" prop="remark" />
  193. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="300">
  194. <template slot-scope="scope">
  195. <!-- 查看按钮 -->
  196. <el-button
  197. size="mini"
  198. type="text"
  199. icon="el-icon-view"
  200. @click="handleView(scope.row)"
  201. v-hasPermi="['vet:qualification:query']"
  202. >查看证书详情</el-button>
  203. <!-- 修改按钮 -->
  204. <!-- <el-button-->
  205. <!-- v-if="!scope.row.auditStatus || scope.row.auditStatus === '0' || scope.row.auditStatus === '2'"-->
  206. <!-- size="mini"-->
  207. <!-- type="text"-->
  208. <!-- icon="el-icon-edit"-->
  209. <!-- style="color: #42B983"-->
  210. <!-- @click="handleUpdate(scope.row)"-->
  211. <!-- v-hasPermi="['vet:qualification:edit']"-->
  212. <!-- >修改</el-button>-->
  213. <!-- 提交/重新提交按钮 -->
  214. <!-- <el-button-->
  215. <!-- v-if="!scope.row.auditStatus || scope.row.auditStatus === '2'"-->
  216. <!-- size="mini"-->
  217. <!-- type="text"-->
  218. <!-- icon="el-icon-s-check"-->
  219. <!-- style="color: #409EFF"-->
  220. <!-- @click="handleSubmitAudit(scope.row)"-->
  221. <!-- v-hasPermi="['vet:qualification:edit']"-->
  222. <!-- >{{ !scope.row.auditStatus ? '提交审核' : '重新提交' }}</el-button>-->
  223. <!-- 下架按钮已上架状态显示 -->
  224. <!-- <el-button-->
  225. <!-- v-if="scope.row.auditStatus === '1'"-->
  226. <!-- size="mini"-->
  227. <!-- type="text"-->
  228. <!-- icon="el-icon-bottom"-->
  229. <!-- style="color: #E6A23C"-->
  230. <!-- @click="handleUnshelf(scope.row)"-->
  231. <!-- v-hasPermi="['vet:qualification:unshelf']"-->
  232. <!-- >下架</el-button>-->
  233. <!-- 上架按钮已下架状态显示 -->
  234. <!-- <el-button-->
  235. <!-- v-if="scope.row.auditStatus === '3'"-->
  236. <!-- size="mini"-->
  237. <!-- type="text"-->
  238. <!-- icon="el-icon-top"-->
  239. <!-- style="color: #67C23A"-->
  240. <!-- @click="handleShelf(scope.row)"-->
  241. <!-- v-hasPermi="['vet:qualification:shelf']"-->
  242. <!-- >上架</el-button>-->
  243. <!-- 删除按钮 -->
  244. <!-- <el-button-->
  245. <!-- v-if="!scope.row.auditStatus || scope.row.auditStatus === '2'"-->
  246. <!-- size="mini"-->
  247. <!-- type="text"-->
  248. <!-- icon="el-icon-delete"-->
  249. <!-- style="color: #f56c6c"-->
  250. <!-- @click="handleDelete(scope.row)"-->
  251. <!-- v-hasPermi="['vet:qualification:remove']"-->
  252. <!-- >删除</el-button>-->
  253. </template>
  254. </el-table-column>
  255. </el-table>
  256. <pagination
  257. v-show="total>0"
  258. :total="total"
  259. :page.sync="queryParams.pageNum"
  260. :limit.sync="queryParams.pageSize"
  261. @pagination="getList"
  262. />
  263. <!-- 显示资质证书信息 -->
  264. <el-dialog :title="title" :visible.sync="openDetail" width="800px" append-to-body>
  265. <div v-if="detailData" style="padding: 20px;">
  266. <div style="margin-top: 30px;">
  267. <el-alert
  268. v-if="!certificateList || certificateList.length === 0"
  269. title="暂无资质证书"
  270. type="info"
  271. :closable="false"
  272. style="margin-bottom: 20px;"
  273. />
  274. <el-table v-else :data="certificateList" border style="width: 100%">
  275. <el-table-column type="selection" width="55" align="center" />
  276. <el-table-column prop="certificateNo" label="证书编号" align="center" width="200">
  277. <template slot-scope="scope">
  278. <span>{{ scope.row.certificateNo }}</span>
  279. </template>
  280. </el-table-column>
  281. <el-table-column prop="certName" label="证书名称" align="center" width="180">
  282. <template slot-scope="scope">
  283. <span>{{ scope.row.certName }}</span>
  284. </template>
  285. </el-table-column>
  286. <el-table-column label="发证机构" align="center" prop="issueOrg" width="150">
  287. <template slot-scope="scope">
  288. <span v-if="scope.row.issueOrg">{{ scope.row.issueOrg }}</span>
  289. <span v-else style="color: #909399">-</span>
  290. </template>
  291. </el-table-column>
  292. <el-table-column label="证书文件" prop="certificateFiles">
  293. <template slot-scope="scope">
  294. <span v-if="scope.row.certificateFiles">
  295. <template v-if="isImageFile(scope.row.certificateFiles)">
  296. <el-button
  297. type="text"
  298. icon="el-icon-view"
  299. @click="previewCertificate(scope.row.certificateFiles)"
  300. style="color: #409EFF;"
  301. >
  302. </el-button>
  303. </template>
  304. <template v-else-if="isPdfFile(scope.row.certificateFiles)">
  305. <el-button
  306. type="text"
  307. icon="el-icon-download"
  308. @click="downloadFile(scope.row.certificateFiles)"
  309. style="color: #287c07;"
  310. >
  311. </el-button>
  312. </template>
  313. <template v-else>
  314. {{ getImageUrl(scope.row.certificateFiles) }}
  315. </template>
  316. </span>
  317. <span v-else style="color: #909399">-</span>
  318. </template>
  319. </el-table-column>
  320. <el-table-column prop="issueDate" label="发证日期" align="center" width="120">
  321. <template slot-scope="scope">
  322. <span>{{ parseTime(scope.row.issueDate, '{y}-{m}-{d}') }}</span>
  323. </template>
  324. </el-table-column>
  325. <el-table-column prop="expireDate" label="到期日期" align="center" width="120">
  326. <template slot-scope="scope">
  327. <span>{{ parseTime(scope.row.expireDate, '{y}-{m}-{d}') }}</span>
  328. </template>
  329. </el-table-column>
  330. <el-table-column label="证书状态" align="center" prop="certStatus" width="100">
  331. <template slot-scope="scope">
  332. <el-tag :type="getCertStatusType(scope.row.certStatus)" size="small">
  333. {{ getCertStatusLabel(scope.row.certStatus) }}
  334. </el-tag>
  335. </template>
  336. </el-table-column>
  337. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="300">
  338. <template slot-scope="scope">
  339. <!-- 修改按钮 -->
  340. <el-button
  341. v-if="!scope.row.auditStatus || scope.row.auditStatus === '0' || scope.row.auditStatus === '2'"
  342. size="mini"
  343. type="text"
  344. icon="el-icon-edit"
  345. style="color: #42B983"
  346. @click="handleUpdate(scope.row)"
  347. v-hasPermi="['vet:qualification:edit']"
  348. >修改</el-button>
  349. </template>
  350. </el-table-column>
  351. </el-table>
  352. </div>
  353. </div>
  354. <div slot="footer" class="dialog-footer">
  355. <el-button @click="closeDetail"> </el-button>
  356. </div>
  357. </el-dialog>
  358. <el-dialog :visible.sync="previewDialogVisible" width="60%" append-to-body>
  359. <div style="text-align: center; padding: 20px;">
  360. <img
  361. :src="getImageUrl(previewFileUrl)"
  362. style="max-width: 100%; max-height: 70vh; height: auto;"
  363. preview-teleported
  364. :preview-src-list="[getImageUrl(previewFileUrl)]"
  365. />
  366. </div>
  367. </el-dialog>
  368. <!-- 添加或修改兽医资质对话框 -->
  369. <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
  370. <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  371. <!-- <el-form-item label="真实姓名" prop="realName">-->
  372. <!-- <el-input v-model="form.realName" placeholder="请输入真实姓名" />-->
  373. <!-- </el-form-item>-->
  374. <!-- <el-form-item label="身份证号" prop="idCard">-->
  375. <!-- <el-input v-model="form.idCard" placeholder="请输入身份证号" />-->
  376. <!-- </el-form-item>-->
  377. <!-- <el-form-item label="资质类型" prop="qualificationType">-->
  378. <!-- <el-select-->
  379. <!-- v-model="form.qualificationType"-->
  380. <!-- placeholder="请选择资质类型"-->
  381. <!-- style="width: 100%;"-->
  382. <!-- >-->
  383. <!-- <el-option-->
  384. <!-- v-for="dict in dict.type.qualification_type"-->
  385. <!-- :key="dict.value"-->
  386. <!-- :label="dict.label"-->
  387. <!-- :value="dict.value"-->
  388. <!-- />-->
  389. <!-- </el-select>-->
  390. <!-- </el-form-item>-->
  391. <el-form-item label="证书编号" prop="certificateNo">
  392. <el-input v-model="form.certificateNo" placeholder="请输入证书编号" />
  393. </el-form-item>
  394. <el-form-item label="证书名称" prop="certName">
  395. <el-input v-model="form.certName" placeholder="请输入证书名称" />
  396. </el-form-item>
  397. <el-form-item label="发证机构" prop="issueOrg">
  398. <el-input v-model="form.issueOrg" placeholder="请输入发证机构" />
  399. </el-form-item>
  400. <el-form-item label="发证日期" prop="issueDate">
  401. <el-date-picker clearable
  402. v-model="form.issueDate"
  403. type="date"
  404. value-format="yyyy-MM-dd"
  405. placeholder="请选择发证日期"
  406. style="width: 100%">
  407. </el-date-picker>
  408. </el-form-item>
  409. <el-form-item label="到期日期" prop="expireDate">
  410. <el-date-picker clearable
  411. v-model="form.expireDate"
  412. type="date"
  413. value-format="yyyy-MM-dd"
  414. placeholder="请选择到期日期"
  415. style="width: 100%">
  416. </el-date-picker>
  417. </el-form-item>
  418. <!-- <el-form-item label="证书图片" prop="certImage">-->
  419. <!-- <image-upload v-model="form.certImage"/>-->
  420. <!-- </el-form-item>-->
  421. <el-form-item label="证书文件" prop="certificateFiles">
  422. <!--&lt;!&ndash; <el-input v-model="form.certificateFiles" type="textarea" placeholder="请输入内容" />&ndash;&gt;-->
  423. <file-upload
  424. v-model="form.certificateFiles"
  425. :limit="1"
  426. :file-type="['pdf','png','jpg','jpeg']"
  427. />
  428. </el-form-item>
  429. <el-form-item label="提前提醒天数" prop="remindDays">
  430. <el-input v-model="form.remindDays" placeholder="请输入提前提醒天数" />
  431. </el-form-item>
  432. <el-form-item label="备注" prop="remark">
  433. <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
  434. </el-form-item>
  435. </el-form>
  436. <div slot="footer" class="dialog-footer">
  437. <el-button type="primary" @click="resubmitForm">重新提交审核</el-button>
  438. <el-button @click="cancel"> </el-button>
  439. </div>
  440. </el-dialog>
  441. </div>
  442. </template>
  443. <script>
  444. import { listQualification, getQualificationCertificate, delQualification, getQualificationCertificates, updateAndSubmitQualification} from "@/api/vet/qualification"
  445. export default {
  446. name: "Qualification",
  447. dicts: ['qualification_shenhe', 'expert_type', 'qualification_type'],
  448. data() {
  449. return {
  450. baseUrl: process.env.VUE_APP_BASE_API,
  451. // 待预览的证书文件路径
  452. previewFileUrl: '',
  453. // 遮罩层
  454. loading: true,
  455. detailLoading: true,
  456. // 选中数组
  457. ids: [],
  458. // 非单个禁用
  459. single: true,
  460. // 非多个禁用
  461. multiple: true,
  462. // 显示搜索条件
  463. showSearch: true,
  464. // 总条数
  465. total: 0,
  466. // 兽医资质表格数据
  467. qualificationList: [],
  468. // 资质证书列表
  469. certificateList: [],
  470. // 详情数据
  471. detailData: null,
  472. // 弹出层标题
  473. title: "",
  474. // 是否显示弹出层
  475. open: false,
  476. openDetail: false,
  477. previewDialogVisible: false,
  478. // 查询参数
  479. queryParams: {
  480. pageNum: 1,
  481. pageSize: 10,
  482. realName: null,
  483. idCard: null,
  484. qualificationType: null,
  485. certificateNo: null,
  486. auditStatus: null,
  487. certName: null,
  488. issueOrg: null,
  489. expireDate: null,
  490. certStatus: null,
  491. },
  492. // 表单参数
  493. form: {},
  494. // 表单校验
  495. rules: {
  496. // realName: [
  497. // { required: true, message: "真实姓名不能为空", trigger: "blur" }
  498. // ],
  499. // idCard: [
  500. // { required: true, message: "身份证号不能为空", trigger: "blur" }
  501. // ],
  502. // qualificationType: [
  503. // { required: true, message: "资质类型不能为空", trigger: "change" }
  504. // ],
  505. certificateNo: [
  506. { required: true, message: "证书编号不能为空", trigger: "blur" }
  507. ],
  508. certName: [
  509. { required: true, message: "证书名称不能为空", trigger: "blur" }
  510. ],
  511. issueOrg: [
  512. { required: true, message: "发证机构不能为空", trigger: "blur" }
  513. ],
  514. issueDate: [
  515. { required: true, message: "发证日期不能为空", trigger: "change" }
  516. ],
  517. expireDate: [
  518. { required: true, message: "到期日期不能为空", trigger: "change" }
  519. ],
  520. certificateFiles: [
  521. { required: true, message: "证书文件不能为空", trigger: "blur" }
  522. ],
  523. }
  524. }
  525. },
  526. created() {
  527. this.getList()
  528. },
  529. methods: {
  530. /** 查询兽医资质列表 */
  531. getList() {
  532. this.loading = true
  533. listQualification(this.queryParams).then(response => {
  534. this.qualificationList = response.rows
  535. this.total = response.total
  536. this.loading = false
  537. })
  538. },
  539. /** 获取证书状态标签 */
  540. getCertStatusLabel(status) {
  541. const map = {
  542. '0': '正常',
  543. '1': '即将过期',
  544. '2': '已过期'
  545. }
  546. return map[status] || status || '-'
  547. },
  548. /** 获取证书状态标签类型 */
  549. getCertStatusType(status) {
  550. const map = {
  551. '0': 'success',
  552. '1': 'warning',
  553. '2': 'danger'
  554. }
  555. return map[status] || 'info'
  556. },
  557. /** 获取审核状态标签类型 */
  558. getAuditStatusType(status) {
  559. const map = {
  560. '0': 'info', // 待审核 - 蓝色
  561. '1': 'success', // 已上架 - 绿色
  562. '2': 'danger', // 已拒绝 - 红色
  563. '3': 'warning' // 已下架 - 黄色
  564. }
  565. return map[status] || 'info'
  566. },
  567. /** 格式化资质类型显示 */
  568. formatQualificationType(status) {
  569. const map = {
  570. '1': '执业兽医师',
  571. '2': '执业助理兽医',
  572. '3': '官方兽医',
  573. '4': '乡村兽医'
  574. }
  575. return map[status] || 'info'
  576. },
  577. /** 获取完整的图片URL */
  578. getImageUrl(filePath) {
  579. return `${this.baseUrl}${filePath}`
  580. },
  581. isImageFile(filePath) {
  582. if (!filePath) return false;
  583. const imageExts = ['.png','.jpg','.jpeg'];
  584. const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
  585. return imageExts.includes(ext);
  586. },
  587. /** 判断是否为PDF文件 */
  588. isPdfFile(filePath) {
  589. if (!filePath) return false;
  590. const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
  591. return ext === '.pdf';
  592. },
  593. /** 预览图片 */
  594. previewCertificate(filePath) {
  595. this.previewFileUrl = filePath;
  596. this.previewDialogVisible = true;
  597. },
  598. /** 下载文件 */
  599. downloadFile(filePath) {
  600. const fullUrl = this.getImageUrl(filePath);
  601. const link = document.createElement('a');
  602. link.href = fullUrl;
  603. const fileName = filePath.substring(filePath.lastIndexOf('/') + 1);
  604. link.download = fileName;
  605. document.body.appendChild(link);
  606. link.click();
  607. document.body.removeChild(link);
  608. this.$modal.msgSuccess('开始下载文件');
  609. },
  610. /** 下架操作 */
  611. // handleUnshelf(row) {
  612. // this.$prompt('请输入下架原因', '下架确认', {
  613. // confirmButtonText: '确定',
  614. // cancelButtonText: '取消',
  615. // inputPlaceholder: '请输入下架原因(如:证书过期、违规操作等)',
  616. // inputValidator: (value) => {
  617. // if (!value || value.trim().length < 2) {
  618. // return '下架原因不能少于2个字'
  619. // }
  620. // if (value.trim().length > 200) {
  621. // return '下架原因不能超过200字'
  622. // }
  623. // return true
  624. // }
  625. // }).then(({ value }) => {
  626. // this.loading = true
  627. // unshelfQualification(row.qualificationId, value).then(response => {
  628. // this.loading = false
  629. // if (response.code === 200) {
  630. // this.$modal.msgSuccess('下架成功')
  631. // this.getList() // 刷新列表
  632. // } else {
  633. // this.$modal.msgError(response.msg || '下架失败')
  634. // }
  635. // }).catch(error => {
  636. // this.loading = false
  637. // this.$modal.msgError(error.msg || '下架失败')
  638. // })
  639. // }).catch(() => {
  640. // // 用户取消操作
  641. // })
  642. // },
  643. /** 上架操作 */
  644. // handleShelf(row) {
  645. // this.$confirm('确认要上架此资质吗?', '上架确认', {
  646. // confirmButtonText: '确定',
  647. // cancelButtonText: '取消',
  648. // type: 'warning'
  649. // }).then(() => {
  650. // this.loading = true
  651. // shelfQualification(row.qualificationId).then(response => {
  652. // this.loading = false
  653. // if (response.code === 200) {
  654. // this.$modal.msgSuccess('上架成功')
  655. // this.getList() // 刷新列表
  656. // } else {
  657. // this.$modal.msgError(response.msg || '上架失败')
  658. // }
  659. // }).catch(error => {
  660. // this.loading = false
  661. // this.$modal.msgError(error.msg || '上架失败')
  662. // })
  663. // }).catch(() => {
  664. // // 用户取消操作
  665. // })
  666. // },
  667. /** 提交审核操作 */
  668. // handleSubmitAudit(row) {
  669. // this.$modal.confirm('确认提交 "' + row.realName + '" 的资质进行审核?').then(() => {
  670. // // 准备提交数据
  671. // const submitData = {
  672. // qualificationId: row.qualificationId,
  673. // realName: row.realName,
  674. // idCard: row.idCard,
  675. // qualificationType: row.qualificationType,
  676. // certificateNo: row.certificateNo,
  677. // certName: row.certName,
  678. // issueOrg: row.issueOrg,
  679. // issueDate: row.issueDate,
  680. // expireDate: row.expireDate,
  681. // certImage: row.certImage,
  682. // certificateFiles: row.certificateFiles,
  683. // remark: row.remark,
  684. // // 提交审核时设置审核状态为待审核(0)
  685. // auditStatus: '0'
  686. // }
  687. //
  688. // return submitQualification(submitData)
  689. // }).then(response => {
  690. // if (response.code === 200) {
  691. // this.$modal.msgSuccess("提交审核成功")
  692. // this.getList()
  693. // } else {
  694. // this.$modal.msgError(response.msg || "提交审核失败")
  695. // }
  696. // }).catch(() => {
  697. // })
  698. // },
  699. /** 重新提交审核 */
  700. resubmitForm() {
  701. this.$refs["form"].validate(valid => {
  702. if (valid) {
  703. let certId = this.form.certId || this.form.certificateId || this.form.id
  704. if (certId && typeof certId === 'object') {
  705. certId = certId.value || certId.id || certId.certificateId
  706. }
  707. certId = String(certId || '')
  708. if (!certId || certId === 'null' || certId === 'undefined' || certId === 'NaN') {
  709. this.$modal.msgError("证书ID无效:" + certId)
  710. return
  711. }
  712. const submitData = {
  713. certId: certId,
  714. qualificationId: this.form.qualificationId,
  715. realName: this.form.realName,
  716. idCard: this.form.idCard,
  717. qualificationType: this.form.qualificationType,
  718. certificateNo: this.form.certificateNo,
  719. certName: this.form.certName,
  720. issueOrg: this.form.issueOrg,
  721. issueDate: this.form.issueDate,
  722. expireDate: this.form.expireDate,
  723. certificateFiles: this.form.certificateFiles,
  724. remark: this.form.remark,
  725. auditStatus: '0',
  726. auditOpinion: null,
  727. applyTime: new Date().toISOString(),
  728. }
  729. updateAndSubmitQualification(submitData).then(response => {
  730. if (response.code === 200) {
  731. this.$modal.msgSuccess("重新提交审核成功")
  732. this.open = false
  733. this.getList()
  734. if (this.openDetail && this.detailData && this.detailData.qualificationId) {
  735. getQualificationCertificates(this.detailData.qualificationId).then(response => {
  736. if (response.code === 200) {
  737. this.certificateList = response.rows || [];
  738. const updatedCertificate = this.certificateList.find(cert =>
  739. cert.certificateId === certId || cert.certId === certId
  740. );
  741. if (updatedCertificate) {
  742. this.certificateList = this.certificateList.map(cert => {
  743. if (cert.certificateId === certId || cert.certId === certId) {
  744. return {
  745. ...cert,
  746. auditStatus: '0',
  747. applyTime: new Date().toISOString(),
  748. auditTime: null,
  749. auditOpinion: null
  750. }
  751. }
  752. return cert;
  753. });
  754. }
  755. }
  756. })
  757. }
  758. this.reset()
  759. } else {
  760. this.$modal.msgError(response.msg || "重新提交审核失败")
  761. }
  762. })
  763. }
  764. })
  765. },
  766. /** 查看详情 */
  767. // handleView(row) {
  768. // // 构建详情内容
  769. // let detailContent = `
  770. // <table style="width:100%; border-collapse: collapse;">
  771. // <tr>
  772. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">姓名:</td>
  773. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${row.realName || '-'}</td>
  774. // </tr>
  775. // <tr>
  776. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">身份证:</td>
  777. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${row.idCard || '-'}</td>
  778. // </tr>
  779. // <tr>
  780. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">证书编号:</td>
  781. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${row.certificateNo || '-'}</td>
  782. // </tr>
  783. // <tr>
  784. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">证书名称:</td>
  785. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${row.certName || '-'}</td>
  786. // </tr>
  787. // <tr>
  788. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">发证机构:</td>
  789. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${row.issueOrg || '-'}</td>
  790. // </tr>
  791. // <tr>
  792. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">到期日期:</td>
  793. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${row.expireDate ? this.parseTime(row.expireDate, '{y}-{m}-{d}') : '-'}</td>
  794. // </tr>
  795. // <tr>
  796. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">证书状态:</td>
  797. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${this.getCertStatusLabel(row.certStatus)}</td>
  798. // </tr>
  799. // <tr>
  800. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">审核状态:</td>
  801. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${this.getDictLabel('qualification_shenhe', row.auditStatus) || '-'}</td>
  802. // </tr>`
  803. //
  804. // // 如果有审核意见,添加审核意见
  805. // if (row.auditOpinion) {
  806. // detailContent += `
  807. // <tr>
  808. // <td style="padding:8px 5px; border-bottom: 1px solid #eee; color: #666;">审核意见:</td>
  809. // <td style="padding:8px 5px; border-bottom: 1px solid #eee;">${row.auditOpinion}</td>
  810. // </tr>`
  811. // }
  812. //
  813. // detailContent += `</table>`
  814. //
  815. // this.$alert(detailContent, '资质详情', {
  816. // dangerouslyUseHTMLString: true,
  817. // confirmButtonText: '关闭',
  818. // width: '550px',
  819. // customClass: 'qualification-detail-dialog'
  820. // })
  821. // },
  822. /** 资质证书详情 */
  823. handleView(row) {
  824. this.openDetail = true
  825. this.detailData = row
  826. this.title = "资质证书详情"
  827. this.certificateList = []
  828. this.detailLoading = true
  829. getQualificationCertificates(row.qualificationId).then(response => {
  830. this.detailLoading = false
  831. if (response.code === 200) {
  832. this.certificateList = response.rows || [];
  833. }
  834. })
  835. },
  836. // 取消按钮
  837. cancel() {
  838. this.open = false
  839. this.reset()
  840. },
  841. // 关闭按钮
  842. closeDetail(){
  843. this.openDetail = false
  844. this.reset()
  845. },
  846. // 表单重置
  847. reset() {
  848. this.form = {
  849. qualificationId: null,
  850. userId: null,
  851. realName: null,
  852. idCard: null,
  853. qualificationType: null,
  854. certificateNo: null,
  855. certificateFiles: null,
  856. applyTime: null,
  857. auditTime: null,
  858. auditStatus: null,
  859. auditOpinion: null,
  860. auditorId: null,
  861. remark: null,
  862. certName: null,
  863. certType: null,
  864. issueOrg: null,
  865. issueDate: null,
  866. expireDate: null,
  867. certImage: null,
  868. certStatus: null,
  869. remindDays: 30,
  870. lastRemindTime: null,
  871. scopeIds: null,
  872. scopeNames: null
  873. }
  874. this.resetForm("form")
  875. },
  876. /** 搜索按钮操作 */
  877. handleQuery() {
  878. this.queryParams.pageNum = 1
  879. this.getList()
  880. },
  881. /** 重置按钮操作 */
  882. resetQuery() {
  883. this.resetForm("queryForm")
  884. this.handleQuery()
  885. },
  886. // 多选框选中数据
  887. handleSelectionChange(selection) {
  888. this.ids = selection.map(item => item.qualificationId)
  889. this.single = selection.length !== 1
  890. this.multiple = !selection.length
  891. },
  892. /** 新增按钮操作 */
  893. handleAdd() {
  894. this.reset()
  895. this.open = true
  896. this.title = "添加兽医资质"
  897. this.form.auditStatus = null
  898. },
  899. /** 修改按钮操作 */
  900. handleUpdate(row) {
  901. this.reset()
  902. let certId = row.certId || row.certificateId || row.id
  903. if (certId && typeof certId === 'object') {
  904. certId = certId.value || certId.id || certId.certificateId
  905. }
  906. certId = String(certId || '')
  907. if (!certId || certId === 'null' || certId === 'undefined' || certId === 'NaN') {
  908. this.$modal.msgError("证书ID无效:" + certId)
  909. return
  910. }
  911. getQualificationCertificate(certId).then(response => {
  912. if (response.code === 200 && response.data) {
  913. this.form = response.data
  914. this.open = true
  915. this.title = "修改兽医资质证书信息"
  916. } else {
  917. this.$modal.msgError(response.msg || "获取证书信息失败")
  918. }
  919. }).catch(error => {
  920. console.error('获取证书信息失败:', error)
  921. this.$modal.msgError("获取证书信息失败")
  922. })
  923. },
  924. /** 提交按钮 */
  925. // submitForm() {
  926. // this.$refs["form"].validate(valid => {
  927. // if (valid) {
  928. // if (this.form.qualificationId != null) {
  929. // updateQualification(this.form).then(response => {
  930. // this.$modal.msgSuccess("修改成功")
  931. // this.open = false
  932. // this.getList()
  933. // })
  934. // } else {
  935. // this.form.auditStatus = null
  936. // addQualification(this.form).then(response => {
  937. // this.$modal.msgSuccess("新增成功")
  938. // this.open = false
  939. // this.getList()
  940. // })
  941. // }
  942. // }
  943. // })
  944. // },
  945. /** 删除按钮操作 */
  946. handleDelete(row) {
  947. const qualificationIds = row.qualificationId || this.ids
  948. this.$modal.confirm('是否确认删除兽医资质编号为"' + qualificationIds + '"的数据项?').then(function() {
  949. return delQualification(qualificationIds)
  950. }).then(() => {
  951. this.getList()
  952. this.$modal.msgSuccess("删除成功")
  953. }).catch(() => {})
  954. },
  955. /** 导出按钮操作 */
  956. handleExport() {
  957. this.download('vet/qualification/export', {
  958. ...this.queryParams
  959. }, `qualification_${new Date().getTime()}.xlsx`)
  960. },
  961. /** 根据字典值获取标签 */
  962. getDictLabel(dictType, value) {
  963. const dict = this.dict.type[dictType]
  964. if (dict && value) {
  965. const item = dict.find(item => item.value === value)
  966. return item ? item.label : value
  967. }
  968. return value || '-'
  969. }
  970. }
  971. }
  972. </script>
  973. <style scoped>
  974. /* 操作按钮样式优化 */
  975. .el-button--text {
  976. padding: 6px 10px;
  977. margin: 0 2px;
  978. min-width: 50px;
  979. }
  980. /* 状态标签样式 */
  981. .el-tag {
  982. margin: 2px;
  983. }
  984. /* 详情对话框样式 */
  985. ::v-deep .qualification-detail-dialog .el-message-box__content {
  986. max-height: 400px;
  987. overflow-y: auto;
  988. }
  989. ::v-deep .qualification-detail-dialog table {
  990. width: 100%;
  991. }
  992. ::v-deep .qualification-detail-dialog table tr:last-child td {
  993. border-bottom: none;
  994. }
  995. </style>