certificateQualificationsDialog.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. <template>
  2. <ele-modal custom-class="ele-dialog-form long-dialog-form"
  3. :centered="true" :visible.sync="certificateQualificationsDialogFlag" :title="title"
  4. append-to-body
  5. :close-on-click-modal="false" width="70%" :before-close="cancel">
  6. <el-tabs v-model="activeName" type="card">
  7. <el-tab-pane label="证书资质" name="QC">
  8. <el-form ref="form" :model="form" class="el-form-box">
  9. <headerTitle title="基本信息"/>
  10. <el-row :gutter="20">
  11. <el-col :span="12">
  12. <el-form-item label-width="50px" label="名称" prop="name"
  13. :rules=" {required: true, message: '请输入',trigger: 'blur' }">
  14. <el-input v-model="form.name" :disabled="type=='view'" clearable></el-input>
  15. </el-form-item>
  16. </el-col>
  17. <el-col :span="12">
  18. <el-form-item label="有效时间:" prop="date" label-width="90px">
  19. <el-date-picker
  20. :disabled="type=='view'"
  21. v-model="form.date"
  22. style="width: 100%;"
  23. type="daterange"
  24. value-format="yyyy-MM-dd"
  25. range-separator="至"
  26. start-placeholder="开始日期"
  27. end-placeholder="结束日期"
  28. >
  29. </el-date-picker>
  30. </el-form-item>
  31. </el-col>
  32. </el-row>
  33. <el-row :gutter="20">
  34. <el-col :span="12">
  35. <el-form-item label-width="50px" label="备注">
  36. <el-input type="textarea" v-model="form.remark" :disabled="type=='view'" clearable></el-input>
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="12">
  40. <el-form-item label="附件:" prop="accessory" label-width="90px">
  41. <fileUpload
  42. v-if="type!=='view'"
  43. v-model="form.accessory"
  44. module="main"
  45. :showLib="false"
  46. :limit="10"/>
  47. <div v-else>
  48. <el-link
  49. v-for="link in form.accessory"
  50. :key="link.id"
  51. type="primary"
  52. :underline="false"
  53. @click="downloadFile(link)">
  54. {{ link.name }}
  55. </el-link>
  56. </div>
  57. </el-form-item>
  58. </el-col>
  59. </el-row>
  60. <headerTitle title="资质信息"/>
  61. <ele-pro-table ref="linkTable" :columns="columns" :datasource="form.detailsList" height="300px"
  62. :need-page="false">
  63. <!-- 表头工具栏 -->
  64. <template v-slot:toolbar>
  65. <el-button v-if="type!=='view'" type="primary" @click="handleAdd">添加</el-button>
  66. </template>
  67. <template v-slot:name="scope">
  68. <el-form-item :prop="'detailsList.' + scope.$index + '.name'" :rules="{
  69. required: true,
  70. message: '',
  71. trigger: 'change'
  72. }">
  73. <el-select v-if="type!=='view'" v-model="scope.row.name" clearable
  74. @change="(val)=>handleChangeType(val,scope.row)">
  75. <el-option :disabled="disabledToType(scope.row).includes(item.dictCode)"
  76. v-for="item in dictList" :value="item.dictCode"
  77. :label="item.dictValue"></el-option>
  78. </el-select>
  79. <!-- <DictSelection v-if="type!=='view'" clearable dictName="客户/生产厂家资质类型" v-model="scope.row.type"-->
  80. <!-- @itemChange="(val)=>handleChangeType(val,scope.row)"></DictSelection>-->
  81. <span v-else>{{ getLabelName(dictList,scope.row.name) }}</span>
  82. </el-form-item>
  83. </template>
  84. <template v-slot:code="scope">
  85. <el-form-item :prop="'detailsList.' + scope.$index + '.code'" :rules="{
  86. required: true,
  87. message: '',
  88. trigger: 'blur'
  89. }">
  90. <el-input v-model="scope.row.code" :disabled="type=='view'" clearable></el-input>
  91. </el-form-item>
  92. </template>
  93. <template v-slot:businessRange="scope">
  94. <el-form-item :prop="'detailsList.' + scope.$index + '.businessRange'">
  95. <el-input type="textarea" v-model="scope.row.businessRange" :disabled="type=='view'" clearable></el-input>
  96. </el-form-item>
  97. </template>
  98. <template v-slot:startTime="scope">
  99. <el-form-item inline-message :prop="'detailsList.' + scope.$index + '.startTime'" :rules="{
  100. required: false,
  101. message: '',
  102. trigger: 'change'
  103. }">
  104. <el-date-picker
  105. :disabled="type=='view'"
  106. v-model="scope.row.startTime"
  107. type="date"
  108. style="width: 100%"
  109. value-format="yyyy-MM-dd"
  110. placeholder="选择日期">
  111. </el-date-picker>
  112. </el-form-item>
  113. </template>
  114. <template v-slot:endTime="scope">
  115. <el-form-item :prop="'detailsList.' + scope.$index + '.endTime'"
  116. :rules="{
  117. required: false,
  118. validator: validateEndDate(scope.row,scope.$index),
  119. trigger: ['blur','change']
  120. }">
  121. <el-date-picker
  122. :disabled="type=='view'"
  123. v-model="scope.row.endTime"
  124. type="date"
  125. style="width: 100%"
  126. value-format="yyyy-MM-dd"
  127. placeholder="选择日期">
  128. </el-date-picker>
  129. </el-form-item>
  130. </template>
  131. <template v-slot:noticePersonName="scope">
  132. <el-form-item :prop="'detailsList.' + scope.$index + '.noticePersonName'" :rules="{
  133. required: true,
  134. message: '',
  135. trigger: ['blur','change']
  136. }">
  137. <el-input
  138. :disabled="type=='view'"
  139. @click.native="openStaffSelection(scope.$index)"
  140. v-model="scope.row.noticePersonName"
  141. placeholder="请选择"
  142. ></el-input>
  143. </el-form-item>
  144. </template>
  145. <template v-slot:accessory="scope">
  146. <el-form-item :prop="'detailsList.' + scope.$index + '.accessory'" :rules="{
  147. required: true,
  148. message: '',
  149. trigger: ['change','blur']
  150. }">
  151. <fileUpload
  152. v-if="type!=='view'"
  153. v-model="scope.row.accessory"
  154. module="main"
  155. :showLib="false"
  156. :limit="10"/>
  157. <div v-else>
  158. <el-link
  159. v-for="link in scope.row.accessory"
  160. :key="link.id"
  161. type="primary"
  162. :underline="false"
  163. @click="downloadFile(link)">
  164. {{ link.name }}
  165. </el-link>
  166. </div>
  167. </el-form-item>
  168. </template>
  169. <template v-slot:type="scope">
  170. <el-form-item :prop="'detailsList.' + scope.$index + '.type'">
  171. <el-select v-if="type!=='view'" v-model="scope.row.type" clearable>
  172. <el-option v-for="item in typeList" :value="item.dictCode"
  173. :label="item.dictValue"></el-option>
  174. </el-select>
  175. <!-- <DictSelection v-if="type!=='view'" clearable dictName="客户/生产厂家资质类型" v-model="scope.row.type"-->
  176. <!-- @itemChange="(val)=>handleChangeType(val,scope.row)"></DictSelection>-->
  177. <span v-else>{{ getLabelName(typeList,scope.row.type) }}</span>
  178. </el-form-item>
  179. </template>
  180. <template v-slot:level="scope">
  181. <el-form-item :prop="'detailsList.' + scope.$index + '.level'">
  182. <el-select v-if="type!=='view'" v-model="scope.row.level" clearable>
  183. <el-option v-for="item in levelOptions" :value="item.dictCode"
  184. :label="item.dictValue"></el-option>
  185. </el-select>
  186. <!-- <DictSelection v-if="type!=='view'" clearable dictName="客户/生产厂家资质类型" v-model="scope.row.type"-->
  187. <!-- @itemChange="(val)=>handleChangeType(val,scope.row)"></DictSelection>-->
  188. <span v-else>{{ getLabelName(levelOptions,scope.row.type) }}</span>
  189. </el-form-item>
  190. </template>
  191. <template v-slot:remark="scope">
  192. <el-form-item :prop="'detailsList.' + scope.$index + '.remark'">
  193. <el-input type="textarea" :disabled="type=='view'" v-model="scope.row.remark"></el-input>
  194. </el-form-item>
  195. </template>
  196. <template v-slot:status="scope">
  197. <el-form-item :prop="'detailsList.' + scope.$index + '.status'">
  198. <el-tag v-if="scope.row.status" :type="statusTagTypeList[scope.row.status]">
  199. {{ statusList[scope.row.status] }}
  200. </el-tag>
  201. </el-form-item>
  202. </template>
  203. <template v-slot:isRequired="{ column }">
  204. <span class="is-required">{{ column.label }}</span>
  205. </template>
  206. <template v-slot:action="{ row, $index }">
  207. <el-popconfirm
  208. class="ele-action"
  209. title="确定要删除该信息吗?"
  210. @confirm="handleRemove($index)"
  211. >
  212. <template v-slot:reference>
  213. <el-link
  214. v-if="type!=='view'"
  215. type="danger"
  216. :underline="false"
  217. icon="el-icon-delete"
  218. >
  219. 删除
  220. </el-link>
  221. </template>
  222. </el-popconfirm>
  223. </template>
  224. </ele-pro-table>
  225. </el-form>
  226. </el-tab-pane>
  227. <el-tab-pane v-if="form.processInstanceId" label="流程详情" name="processInstance">
  228. <bpmDetail :id="form.processInstanceId"></bpmDetail>
  229. </el-tab-pane>
  230. </el-tabs>
  231. <div slot="footer" v-if="activeName=='QC'">
  232. <el-button v-if="type!=='view'" type="primary" @click="handleSave(false)">保存</el-button>
  233. <el-button v-if="type!=='view'" type="primary" plan @click="handleSave(true)">提交</el-button>
  234. <el-button @click="cancel">返回</el-button>
  235. </div>
  236. <staffSelection
  237. ref="staffSelection"
  238. @confirm="confirmStaffSelection"
  239. ></staffSelection>
  240. </ele-modal>
  241. </template>
  242. <script>
  243. import FileUpload from "@/components/upload/fileUpload.vue";
  244. import staffSelection from "@/components/staffSelection/staffSelection.vue";
  245. import {
  246. contactQcPackDetailAPI,
  247. contactQcPackSaveAPI,
  248. contactQcPackUpdateAPI,
  249. contactQcSubmit
  250. } from "@/api/saleManage/contact";
  251. import {getFile} from "@/api/system/file";
  252. import bpmDetail from "@/views/bpm/processInstance/detail.vue";
  253. import {mapActions, mapGetters} from "vuex";
  254. import dictEnum from "@/enum/dict";
  255. export default {
  256. name: "certificateQualificationsDialog",
  257. components: {bpmDetail, FileUpload, staffSelection},
  258. props: {
  259. certificateQualificationsDialogFlag: Boolean,
  260. contactInfo: Object,
  261. typeInfo: String
  262. },
  263. data() {
  264. return {
  265. title: '',
  266. type: '',
  267. activeName: 'QC',
  268. defaultData: {
  269. accessory: [],
  270. name: "",
  271. noticePersonId: "",
  272. noticePersonName: "",
  273. num: "",
  274. remark: "",
  275. businessRange: "",
  276. type: "",
  277. endTime: "",
  278. startTime: ""
  279. },
  280. form: {
  281. accessory:[],
  282. detailsList: [],
  283. relationName: '',
  284. name: '',
  285. date: [],
  286. remark: '',
  287. },
  288. curIndex: null,
  289. levelOptions: [
  290. {
  291. dictValue: '初级',
  292. dictCode: '1'
  293. },
  294. {
  295. dictValue: '中级',
  296. dictCode: '2'
  297. },
  298. {
  299. dictValue: '高级',
  300. dictCode: '3'
  301. }
  302. ],
  303. statusList: {
  304. 10: '有效',
  305. 20: '无效',
  306. 30: '已过期',
  307. },
  308. statusTagTypeList: {
  309. 10: 'success',
  310. 20: 'info',
  311. 30: 'danger',
  312. },
  313. }
  314. },
  315. computed: {
  316. ...mapGetters(['dict']),
  317. dictList() {
  318. return this.dict[dictEnum['客户/生产厂家资质类型']] || [];
  319. },
  320. typeList() {
  321. return this.dict[dictEnum['工种类型']] || [];
  322. },
  323. columns() {
  324. return [
  325. {
  326. type: 'index',
  327. width: 55,
  328. align: 'center'
  329. },
  330. {
  331. label: '名称',
  332. prop: 'name',
  333. slot: 'name',
  334. headerSlot: 'isRequired',
  335. minWidth: 180,
  336. align: 'center'
  337. },
  338. {
  339. label: '编号',
  340. prop: 'code',
  341. slot: 'code',
  342. headerSlot: 'isRequired',
  343. minWidth: 120,
  344. align: 'center'
  345. },
  346. {
  347. label: '许可/经营范围',
  348. prop: 'businessRange',
  349. slot: 'businessRange',
  350. minWidth: 140,
  351. align: 'center'
  352. },
  353. {
  354. label: '有效期起始日期',
  355. prop: 'startTime',
  356. slot: 'startTime',
  357. // headerSlot: 'isRequired',
  358. minWidth: 160,
  359. align: 'center'
  360. },
  361. {
  362. label: '有效期截止日期',
  363. prop: 'endTime',
  364. slot: 'endTime',
  365. // headerSlot: 'isRequired',
  366. minWidth: 160,
  367. align: 'center'
  368. },
  369. {
  370. label: '通知人',
  371. prop: 'noticePersonName',
  372. slot: 'noticePersonName',
  373. headerSlot: 'isRequired',
  374. minWidth: 140,
  375. align: 'center'
  376. },
  377. {
  378. label: '附件',
  379. prop: 'accessory',
  380. slot: 'accessory',
  381. headerSlot: 'isRequired',
  382. minWidth: 140,
  383. },
  384. {
  385. label: '等级',
  386. prop: 'level',
  387. slot: 'level',
  388. minWidth: 140,
  389. align: 'center'
  390. },
  391. {
  392. label: '分类',
  393. prop: 'type',
  394. slot: 'type',
  395. minWidth: 140,
  396. align: 'center'
  397. },
  398. {
  399. label: '备注',
  400. prop: 'remark',
  401. slot: 'remark',
  402. minWidth: 140,
  403. align: 'center'
  404. },
  405. {
  406. label: '状态',
  407. prop: 'status',
  408. slot: 'status',
  409. align: 'center',
  410. },
  411. {
  412. action: 'action',
  413. slot: 'action',
  414. label: '操作',
  415. align: 'center',
  416. fixed:'right'
  417. }
  418. ]
  419. },
  420. disabledToType() {
  421. return (row) => {
  422. let list = this.form.detailsList.map(item => item.name)
  423. let dictCodeList = this.dictList.map(item => item.dictCode)
  424. let intersectionList = list.filter((v) => dictCodeList.indexOf(v) > -1)
  425. intersectionList = intersectionList.filter(v => row.name !== v)
  426. return intersectionList
  427. }
  428. },
  429. },
  430. created() {
  431. this.requestDict('客户/生产厂家资质类型');
  432. this.requestDict('工种类型');
  433. },
  434. methods: {
  435. ...mapActions('dict', ['requestDict']),
  436. getLabelName(arr,id){
  437. if(!id) return ''
  438. return arr.find(item=>item.dictCode == id)?.dictValue
  439. },
  440. //删除资质
  441. handleRemove(index) {
  442. this.form.detailsList.splice(index, 1)
  443. },
  444. //结束日期验证
  445. validateEndDate(row, index) {
  446. return (rule, value, callback) => {
  447. //new Error('')
  448. if (!value) return callback()
  449. if (
  450. row.endTime &&
  451. row.startTime &&
  452. value < row.startTime
  453. ) {
  454. callback(new Error('截止日期不能小于起始日期'))
  455. } else {
  456. callback()
  457. }
  458. }
  459. },
  460. //页面初始化
  461. init(type, row = {}) {
  462. this.title = type == 'add' ? '新增' : type == 'update' ? '修改' : '详情'
  463. this.type = type
  464. if (type !== 'add') {
  465. this.getCertificateInfo(row)
  466. }
  467. },
  468. async getCertificateInfo(row) {
  469. this.form = await contactQcPackDetailAPI(row.id)
  470. this.form.date = [this.form.startTime, this.form.endTime]
  471. },
  472. //打开选择负责人弹窗
  473. openStaffSelection(index) {
  474. this.curIndex = index
  475. this.$refs.staffSelection.open([]);
  476. },
  477. //选择负责人回调
  478. confirmStaffSelection(data) {
  479. this.form.detailsList[this.curIndex].noticePersonName = data.map((item) => item.name).toString();
  480. this.form.detailsList[this.curIndex].noticePersonId = data.map((item) => item.id).toString();
  481. },
  482. //新增
  483. handleAdd() {
  484. this.form.detailsList.push({...this.defaultData})
  485. },
  486. //修改资质证书
  487. handleChangeType(val, row) {
  488. if (!val) return row.name = ''
  489. row.name = this.dictList.find(i => i.dictCode == val)?.dictValue || ''
  490. },
  491. downloadFile(file) {
  492. getFile({objectName: file.storePath}, file.name);
  493. },
  494. //保存/提交
  495. handleSave(isSub) {
  496. let msg = this.typeInfo == '1' ? '请保存客户信息后新增资质':'请保存生产厂家信息后新增资质'
  497. if (!this.contactInfo.id) return this.$message.success(msg)
  498. this.$refs.form.validate(async (valid) => {
  499. console.log(1111,valid);
  500. if (!valid) return this.$message.warning('有必填项未填写,请检查')
  501. if (!this.form.detailsList.length) return this.$message.warning('至少保存一条资质信息')
  502. this.form.certificationType = this.typeInfo
  503. this.form.relationId = this.contactInfo.id
  504. this.form.relationName = this.contactInfo.name
  505. this.form.startTime = this.form.date[0]
  506. this.form.endTime = this.form.date[1]
  507. let api = this.type == 'add' ? contactQcPackSaveAPI : contactQcPackUpdateAPI
  508. let id = await api(this.form)
  509. if (isSub) {
  510. await contactQcSubmit({businessId: id, certificationType: this.typeInfo})
  511. }
  512. this.$message.success('保存成功')
  513. this.$emit('reload')
  514. this.cancel()
  515. })
  516. },
  517. //关闭弹窗
  518. cancel() {
  519. this.$emit('update:certificateQualificationsDialogFlag', false)
  520. },
  521. }
  522. }
  523. </script>
  524. <style scoped lang="scss">
  525. :deep.el-form-item {
  526. margin-bottom: 0
  527. }
  528. </style>