communicate-add-or-update.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. <template>
  2. <div>
  3. <div class="my-title">{{ !id ? "新增" : display ? "详情" : "修改" }}</div>
  4. <el-form
  5. :model="dataForm"
  6. :rules="dataRule"
  7. ref="dataForm"
  8. label-width="auto"
  9. >
  10. <el-row class="my-row">
  11. <el-col :span="6">
  12. <el-form-item label="客户名称" prop="cusId">
  13. <el-select
  14. v-model="dataForm.cusId"
  15. :disabled="display"
  16. remote
  17. placeholder="请选择"
  18. style="width: 100%"
  19. >
  20. <el-option
  21. v-for="item in optionsCus"
  22. :key="item.value"
  23. :label="item.customerName"
  24. :value="item.customerId"
  25. >
  26. </el-option>
  27. </el-select>
  28. </el-form-item>
  29. </el-col>
  30. <el-col :span="6">
  31. <el-form-item label="客户联系人" prop="contact">
  32. <el-input
  33. v-model="dataForm.contact"
  34. disabled
  35. placeholder="联系人"
  36. ></el-input>
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="6">
  40. <el-form-item label="联系电话" prop="contactTel">
  41. <el-input v-model="dataForm.contactTel" placeholder=""></el-input>
  42. </el-form-item>
  43. </el-col>
  44. <el-col :span="6">
  45. <el-form-item label="沟通方式" prop="way">
  46. <el-input v-model="dataForm.way" placeholder=""></el-input>
  47. </el-form-item>
  48. </el-col>
  49. </el-row>
  50. <el-row class="my-row">
  51. <el-col :span="6">
  52. <el-form-item label="沟通类别" prop="coType">
  53. <el-select
  54. v-model="dataForm.coType"
  55. :disabled="display"
  56. remote
  57. @change="typeChanged"
  58. placeholder="请选择"
  59. style="width: 100%"
  60. >
  61. <el-option
  62. v-for="item in options"
  63. :key="item.code"
  64. :label="item.value"
  65. :value="item.code"
  66. >
  67. </el-option>
  68. </el-select>
  69. </el-form-item>
  70. </el-col>
  71. </el-row>
  72. <el-row class="my-row">
  73. <el-col :span="12">
  74. <el-form-item label="沟通主要内容" prop="content">
  75. <el-input
  76. v-model="dataForm.content"
  77. :disabled="display"
  78. type="textarea"
  79. ></el-input>
  80. </el-form-item>
  81. </el-col>
  82. <el-col :span="12">
  83. <el-form-item label="备注">
  84. <el-input
  85. v-model="dataForm.notes"
  86. :disabled="display"
  87. type="textarea"
  88. ></el-input>
  89. </el-form-item>
  90. </el-col>
  91. </el-row>
  92. <el-row class="my-row">
  93. <el-col :span="8">
  94. <el-form-item label="技术资料" prop="attachListTechnical">
  95. <upload-component
  96. :display="display"
  97. :displayStar="false"
  98. :accept="'*'"
  99. v-model="dataForm.attachListTechnical"
  100. @uploadSuccess="uploadSuccessTechnical"
  101. />
  102. </el-form-item>
  103. </el-col>
  104. <el-col :span="8" :offset="4">
  105. <el-form-item label="数模/图纸" prop="attachListDrawing">
  106. <upload-component
  107. :display="display"
  108. :displayStar="false"
  109. :accept="'*'"
  110. v-model="dataForm.attachListDrawing"
  111. @uploadSuccess="uploadSuccessDrawing"
  112. />
  113. </el-form-item>
  114. </el-col>
  115. </el-row>
  116. <el-row class="my-row">
  117. <el-col :span="8">
  118. <el-form-item label="沟通表原件" prop="attachList">
  119. <upload-component
  120. :display="display"
  121. :displayStar="false"
  122. :accept="'*'"
  123. v-model="dataForm.attachList"
  124. @uploadSuccess="uploadSuccess"
  125. />
  126. </el-form-item>
  127. </el-col>
  128. <el-col :span="8" :offset="4">
  129. <el-form-item label="其他附件" prop="attachListOther">
  130. <upload-component
  131. :display="display"
  132. :displayStar="false"
  133. :accept="'*'"
  134. v-model="dataForm.attachListOther"
  135. @uploadSuccess="uploadSuccessOther"
  136. />
  137. </el-form-item>
  138. </el-col>
  139. </el-row>
  140. <div>
  141. <div class="title">沟通物料明细</div>
  142. <el-row>
  143. <el-table :data="cusRCommProductVOS" border style="width: 100%">
  144. <el-table-column
  145. label="序号"
  146. type="index"
  147. width="50"
  148. align="center"
  149. >
  150. </el-table-column>
  151. <el-table-column
  152. prop="productName"
  153. header-align="center"
  154. align="center"
  155. min-width="120"
  156. :show-tooltip-when-overflow="true"
  157. label="物料名称"
  158. >
  159. </el-table-column>
  160. <el-table-column
  161. prop="productSpecifications"
  162. header-align="center"
  163. align="center"
  164. :show-tooltip-when-overflow="true"
  165. label="规格"
  166. >
  167. </el-table-column>
  168. <el-table-column
  169. prop="cnt"
  170. header-align="center"
  171. align="center"
  172. label="数量"
  173. >
  174. </el-table-column>
  175. <el-table-column
  176. prop="deliveryDate"
  177. header-align="center"
  178. align="center"
  179. min-width="100"
  180. width="150"
  181. label="交付日期"
  182. >
  183. </el-table-column>
  184. <!-- <el-table-column
  185. prop="price"
  186. header-align="center"
  187. align="center"
  188. min-width="100"
  189. label="含税单价"
  190. >
  191. </el-table-column>
  192. <el-table-column
  193. prop="amount"
  194. header-align="center"
  195. align="center"
  196. min-width="100"
  197. label="含税总价"
  198. >
  199. <template slot-scope="scope">
  200. <span>{{ (scope.row.cnt * scope.row.price).toFixed(1) }}</span>
  201. </template>
  202. </el-table-column>
  203. <el-table-column
  204. prop="rate"
  205. header-align="center"
  206. align="center"
  207. min-width="100"
  208. label="税率"
  209. >
  210. <template slot-scope="scope"> {{ scope.row.rate }}% </template>
  211. </el-table-column> -->
  212. <el-table-column
  213. prop="notes"
  214. header-align="center"
  215. align="center"
  216. min-width="180"
  217. :show-tooltip-when-overflow="true"
  218. label="备注"
  219. >
  220. </el-table-column>
  221. <el-table-column
  222. fixed="right"
  223. header-align="center"
  224. align="center"
  225. width="100"
  226. label="操作"
  227. >
  228. <template slot-scope="scope">
  229. <el-button
  230. type="text"
  231. size="small"
  232. @click="updateProductHandle(scope.row)"
  233. >编辑</el-button
  234. >
  235. <el-button
  236. style="color: red"
  237. type="text"
  238. size="small"
  239. @click="deleteProductHandle(scope.row.recordId)"
  240. >删除</el-button
  241. >
  242. </template>
  243. </el-table-column>
  244. </el-table>
  245. </el-row>
  246. <el-row v-if="!display" style="text-align: center; margin-top: 10px">
  247. <el-button
  248. type="primary"
  249. icon="el-icon-plus"
  250. @click="inBound"
  251. ></el-button>
  252. </el-row>
  253. </div>
  254. <div>
  255. <div class="title">任务工单派发</div>
  256. <el-row>
  257. <el-table :data="workInfoList" border style="width: 100%">
  258. <el-table-column
  259. label="序号"
  260. type="index"
  261. width="50"
  262. align="center"
  263. >
  264. </el-table-column>
  265. <el-table-column
  266. prop="taskType"
  267. header-align="center"
  268. align="center"
  269. min-width="100"
  270. width="120"
  271. label="工单类型"
  272. >
  273. <template slot-scope="scope">
  274. <span>{{
  275. taskTypeOption.findIndex((t) => t.value == scope.row.taskType) > -1
  276. ? taskTypeOption.find((t) => t.value == scope.row.taskType).label
  277. : ''
  278. }}</span>
  279. </template>
  280. </el-table-column>
  281. <el-table-column
  282. prop="taskName"
  283. header-align="center"
  284. align="center"
  285. :show-tooltip-when-overflow="true"
  286. label="工单名称"
  287. >
  288. </el-table-column>
  289. <el-table-column
  290. prop="ranks"
  291. header-align="center"
  292. align="center"
  293. width="120"
  294. label="级别"
  295. >
  296. <template slot-scope="scope">
  297. <span>{{
  298. rankTypeOption.findIndex((t) => t.value == scope.row.ranks) > -1
  299. ? rankTypeOption.find((t) => t.value == scope.row.ranks).label
  300. : ''
  301. }}</span>
  302. </template>
  303. </el-table-column>
  304. <el-table-column
  305. prop="content"
  306. header-align="center"
  307. align="center"
  308. min-width="100"
  309. label="工单内容"
  310. :show-tooltip-when-overflow="true"
  311. >
  312. </el-table-column>
  313. <el-table-column
  314. prop="receiver"
  315. header-align="center"
  316. align="center"
  317. width="150"
  318. label="任务接收人"
  319. >
  320. <template slot-scope="scope">
  321. <span>{{ scope.row.receiverName }}</span>
  322. </template>
  323. </el-table-column>
  324. <el-table-column
  325. prop="attachListVo"
  326. header-align="center"
  327. align="center"
  328. width="150"
  329. label="任务附件"
  330. >
  331. <template slot-scope="scope">
  332. <el-button
  333. :disabled="
  334. !scope.row.attachListVo || scope.row.attachListVo.length === 0
  335. "
  336. type="text"
  337. size="small"
  338. @click="attachDetails(scope.row.attachListVo)"
  339. >查看</el-button
  340. >
  341. </template>
  342. </el-table-column>
  343. <el-table-column
  344. prop="notes"
  345. header-align="center"
  346. align="center"
  347. :show-tooltip-when-overflow="true"
  348. label="备注"
  349. >
  350. </el-table-column>
  351. <el-table-column
  352. fixed="right"
  353. header-align="center"
  354. align="center"
  355. width="100"
  356. label="操作"
  357. >
  358. <template slot-scope="scope">
  359. <el-button
  360. type="text"
  361. size="small"
  362. @click="updateWorderHandle(scope.row)"
  363. >编辑</el-button
  364. >
  365. <el-button
  366. style="color: red"
  367. type="text"
  368. size="small"
  369. @click="deleteProductHandle(scope.row.recordId)"
  370. >删除</el-button
  371. >
  372. </template>
  373. </el-table-column>
  374. </el-table>
  375. </el-row>
  376. <el-row v-if="!display" style="text-align: center; margin-top: 10px">
  377. <el-button
  378. type="primary"
  379. icon="el-icon-plus"
  380. @click="worderAdd"
  381. ></el-button>
  382. </el-row>
  383. </div>
  384. </el-form>
  385. <span slot="footer" class="dialog-footer">
  386. <el-button @click="onChose">取消</el-button>
  387. <el-button v-if="!display" type="primary" @click="dataFormSubmit()"
  388. >确定</el-button
  389. >
  390. </span>
  391. <add-or-update v-if="inboundVisible" ref="inbound" @addItem="addItem" />
  392. <worder-add-or-update-dialog
  393. v-if="worderVisible"
  394. ref="worder"
  395. @submit="addWorderItem"
  396. />
  397. <attach-detail-dialog ref="attachDetail" @onChose="onChose" />
  398. </div>
  399. </template>
  400. <script>
  401. // import templateChose from '../product/template-chose'
  402. import { getCustomer, getCoDetail } from '@/api/cus'
  403. import { getDictList } from '@/api/dict'
  404. import uploadComponent from '../common/upload-component-v2'
  405. import AddOrUpdate from '../product/template-add-or-update-v2'
  406. import WorderAddOrUpdateDialog from '../worder/add-or-update-dialog'
  407. import AttachDetailDialog from '../common/attach-detail-dialog'
  408. import { taskTypeOption, rankTypeOption } from '@/utils/enums'
  409. export default {
  410. name: 'communicate-add-or-update',
  411. components: {
  412. AddOrUpdate,
  413. uploadComponent,
  414. WorderAddOrUpdateDialog,
  415. AttachDetailDialog
  416. },
  417. computed: {
  418. orgId: {
  419. get () {
  420. return this.$store.state.user.orgId
  421. }
  422. }
  423. },
  424. data () {
  425. return {
  426. inboundVisible: false,
  427. detailVisible: false,
  428. worderVisible: false,
  429. attachVisible: false,
  430. visible: false,
  431. display: false,
  432. dictType: 'material_type',
  433. options: [],
  434. optionsCus: [],
  435. dataList: [],
  436. attachListTechnical: [], // 技术资料
  437. attachListDrawing: [], // 数模/图纸
  438. attachList: [], // 沟通表原件
  439. attachListOther: [], // 其他附件
  440. id: 0,
  441. cusRCommProductVOS: [],
  442. workInfoList: [],
  443. dataForm: {},
  444. taskTypeOption: taskTypeOption,
  445. rankTypeOption: rankTypeOption,
  446. dataRule: {
  447. cusId: [
  448. { required: true, message: '客户名称不能为空', trigger: 'blur' }
  449. ],
  450. coType: [
  451. { required: true, message: '沟通类别不能为空', trigger: 'change' }
  452. ],
  453. contact: [
  454. { required: true, message: '联系人不能为空', trigger: 'blur' }
  455. ],
  456. contactTel: [
  457. { required: true, message: '联系电话不能为空', trigger: 'blur' }
  458. ],
  459. way: [{ required: true, message: '沟通方式不能为空', trigger: 'blur' }],
  460. content: [
  461. { required: true, message: '沟通内容不能为空', trigger: 'blur' }
  462. ]
  463. }
  464. }
  465. },
  466. watch: {
  467. 'dataForm.cusId' (value) {
  468. this.optionsCus.forEach((v) => {
  469. if (v.customerId === value) {
  470. this.dataForm.contact = v.contact
  471. this.dataForm.contactTel = v.contactTel
  472. }
  473. })
  474. }
  475. },
  476. methods: {
  477. onChose () {
  478. this.$emit('onChose')
  479. this.inboundVisible = false
  480. this.detailVisible = false
  481. this.worderVisible = false
  482. this.attachVisible = false
  483. },
  484. async init (id, display) {
  485. this.dataForm = {}
  486. this.cusRCommProductVOS = []
  487. this.workInfoList = []
  488. this.visible = true
  489. this.id = id || 0
  490. this.display = display
  491. // 获取沟通类别
  492. await getDictList({ type: 'communication_type' }).then(({ data }) => {
  493. if (data) {
  494. this.options = data
  495. }
  496. })
  497. await getCustomer().then(({ data }) => {
  498. if (data && data.code === '200') {
  499. this.optionsCus = data.data
  500. }
  501. })
  502. if (!id) return
  503. this.detailVisible = true
  504. await getCoDetail(this.id).then(({ data }) => {
  505. if (data && data.code === '200') {
  506. this.dataForm = data.data
  507. if (this.dataForm.coType !== '1') {
  508. this.detailVisible = false
  509. }
  510. // 附件显示
  511. if (this.dataForm.attachListTechnical) {
  512. this.dataForm.attachListTechnical.forEach((item) => {
  513. item.name = item.fileName
  514. item.id = item.url
  515. })
  516. }
  517. if (this.dataForm.attachListDrawing) {
  518. this.dataForm.attachListDrawing.forEach((item) => {
  519. item.name = item.fileName
  520. item.id = item.url
  521. })
  522. }
  523. if (this.dataForm.attachList) {
  524. this.dataForm.attachList.forEach((item) => {
  525. item.name = item.fileName
  526. item.id = item.url
  527. })
  528. }
  529. if (this.dataForm.attachListOther) {
  530. this.dataForm.attachListOther.forEach((item) => {
  531. item.name = item.fileName
  532. item.id = item.url
  533. })
  534. }
  535. if (data.data.cusRCommProductVOS) {
  536. data.data.cusRCommProductVOS.forEach((item) => {
  537. this.addItem(item)
  538. })
  539. }
  540. if (data.data.workInfoList) {
  541. data.data.workInfoList.forEach((item) => {
  542. this.addWorderItem(item)
  543. })
  544. }
  545. }
  546. })
  547. },
  548. // 表单提交
  549. dataFormSubmit () {
  550. this.$refs['dataForm'].validate((valid) => {
  551. if (valid) {
  552. // 添加附件
  553. // let fList = this.fileList
  554. // console.log('fileList = ' + fList)
  555. // if (fList.length > 0) {
  556. // this.dataForm.attachList = [];
  557. // for (let i = 0; i < fList.length; i++) {
  558. // this.dataForm.attachList.push({
  559. // fileName: fList[i].name,
  560. // url: fList[i].url,
  561. // });
  562. // }
  563. // } else {
  564. // this.$message.error("请上传文件");
  565. // return;
  566. // }
  567. // if (this.dataForm.coType === "1") {
  568. // if (this.cusRCommProductVOS.length === 0) {
  569. // this.$message.error("请选择任务单物料明细");
  570. // return;
  571. // }
  572. // }
  573. this.dataForm.cusRCommProductVOS = this.cusRCommProductVOS
  574. this.dataForm.workInfoList = this.workInfoList
  575. this.$http({
  576. url: !this.id
  577. ? this.$http.adornUrl(`/biz-service/cusCommunication/save`)
  578. : this.$http.adornUrl(`/biz-service/cusCommunication/update`),
  579. method: 'post',
  580. data: this.$http.adornData({ ...this.dataForm, orgId: this.orgId })
  581. }).then(({ data }) => {
  582. if (data && data.code === '200') {
  583. this.$message({
  584. message: '操作成功',
  585. type: 'success',
  586. duration: 1500,
  587. onClose: () => {
  588. this.onChose()
  589. this.$emit('refreshDataList')
  590. }
  591. })
  592. } else {
  593. this.$message.error(data.msg)
  594. }
  595. })
  596. }
  597. })
  598. },
  599. validateField (type) {
  600. this.$refs.dataForm.validateField(type)
  601. },
  602. inBound () {
  603. this.inboundVisible = true
  604. this.$nextTick(() => {
  605. this.$refs.inbound.init(1)
  606. })
  607. },
  608. // 编辑物料项
  609. updateProductHandle (row) {
  610. this.inboundVisible = true
  611. this.$nextTick(() => {
  612. this.$refs.inbound.init(1, row)
  613. })
  614. },
  615. addItem (item) {
  616. if (!item.recordId) {
  617. item.recordId = Math.round(Math.random() * 1000000)
  618. }
  619. if (
  620. this.cusRCommProductVOS.findIndex(
  621. (item1) => item1.recordId === item.recordId
  622. ) === -1
  623. ) {
  624. this.cusRCommProductVOS.push({
  625. ...item
  626. })
  627. }
  628. },
  629. // 添加工单
  630. addWorderItem (item) {
  631. if (!item.recordId) {
  632. item.recordId = Math.round(Math.random() * 1000000)
  633. }
  634. if (
  635. this.workInfoList.findIndex(
  636. (item1) => item1.recordId === item.recordId
  637. ) === -1
  638. ) {
  639. this.workInfoList.push({ ...item })
  640. }
  641. },
  642. uploadSuccessTechnical (fileList) {
  643. this.attachListTechnical = fileList
  644. },
  645. uploadSuccessDrawing (fileList) {
  646. this.attachListDrawing = fileList
  647. },
  648. uploadSuccess (fileList) {
  649. this.attachList = fileList
  650. },
  651. uploadSuccessOther (fileList) {
  652. this.attachListOther = fileList
  653. },
  654. typeChanged (item) {
  655. this.detailVisible = item === '1'
  656. },
  657. // 删除物料项
  658. deleteProductHandle (recordId) {
  659. this.cusRCommProductVOS.splice(
  660. this.cusRCommProductVOS.findIndex((item) => item.recordId === recordId),
  661. 1
  662. )
  663. },
  664. worderAdd () {
  665. this.worderVisible = true
  666. this.$nextTick(() => {
  667. this.$refs.worder.init(0, null, 'addItem')
  668. })
  669. },
  670. updateWorderHandle (row) {
  671. this.worderVisible = true
  672. row.attachList = row.attachListVo
  673. this.$nextTick(() => {
  674. this.$refs.worder.init(1, row)
  675. })
  676. },
  677. attachDetails (attachList) {
  678. // attachList.forEach((item) => {
  679. // item.fileName = item.name
  680. // })
  681. this.$refs.attachDetail.init(attachList)
  682. }
  683. }
  684. }
  685. </script>
  686. <style scoped>
  687. .my-line {
  688. border-bottom: 1px solid #c0c4cc;
  689. margin-bottom: 10px;
  690. }
  691. .title {
  692. padding: 10px 0;
  693. }
  694. </style>