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.

1179 lines
42 KiB

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