index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. <template>
  2. <zj-tab-page ref="tabPage" :defaultActives="[{ key: 'list', label: $route.meta.title + '-列表', essential: true }]">
  3. <template slot-scope="{ activeKey, data }">
  4. <div :style="{
  5. width: '100%',
  6. height: activeKey == 'list' ? '100%' : '0px',
  7. overflow: 'hidden'
  8. }">
  9. <template-page ref="pageRef" :get-list="getList" :table-attributes="tableAttributes" :table-events="tableEvents"
  10. :options-evens-group="optionsEvensGroup" :moreParameters="moreParameters" :column-parsing="columnParsing"
  11. :exportList="exportList" :operation="operation()">
  12. </template-page>
  13. </div>
  14. <div v-if="~['add', 'edit'].indexOf(activeKey)" style="box-sizing: border-box; padding: 16px">
  15. <zj-form-container ref="formRef" :form-data="formData" :form-attributes="{ size: 'mini' }">
  16. <zj-form-module title="" label-width="100px" :form-data="formData" :form-items="formItems">
  17. <div slot="internal-bottom"
  18. style="text-align: right; margin-bottom: 20px; box-sizing: border-box; padding-right: 10px">
  19. <el-button size="mini" @click="data.removeTab()">取消</el-button>
  20. <el-button size="mini" type="primary" @click="queding(data.removeTab)">确定</el-button>
  21. </div>
  22. </zj-form-module>
  23. </zj-form-container>
  24. </div>
  25. </template>
  26. </zj-tab-page>
  27. </template>
  28. <script>
  29. import TemplatePage from '@/components/template/template-page-1.vue'
  30. import import_mixin from '@/components/template/import_mixin.js'
  31. import operation_mixin from '@/components/template/operation_mixin.js'
  32. import { required, mobileRequired, mobile, httpUrl, email } from '@/components/template/rules_verify.js'
  33. import { getBrandList } from '@/api/miniapp'
  34. import { getClassifyList } from '@/api/goods'
  35. import {
  36. goodsMaterialList,
  37. goodsMaterialListExport,
  38. goodsMaterialAdd,
  39. goodsMaterialUpdate,
  40. goodsMaterialBatchUpdateStatus,
  41. goodsMaterialItemCount,
  42. goodsMaterialDetail
  43. } from '@/api/commercialMaterial.js'
  44. export default {
  45. components: { TemplatePage },
  46. mixins: [import_mixin, operation_mixin],
  47. data() {
  48. return {
  49. // 表格属性
  50. tableAttributes: {
  51. // 启用勾选列
  52. selectColumn: false
  53. },
  54. // 表格事件
  55. tableEvents: {
  56. 'selection-change': this.selectionChange
  57. },
  58. // 勾选选中行
  59. recordSelected: [],
  60. formData: {
  61. companyWechatId: '',
  62. brandId: '',
  63. mainId: '',
  64. smallId: '',
  65. seriesName: '',
  66. goodsName: '',
  67. specsName: '',
  68. state: '',
  69. unit: '',
  70. isVirtyual: '',
  71. remark: '',
  72. factoryNo: "",
  73. items: []
  74. },
  75. isEditIndex: -1,
  76. brandList: [],
  77. ClassifyList: []
  78. }
  79. },
  80. computed: {
  81. // 事件组合
  82. optionsEvensGroup() {
  83. return [
  84. [
  85. [
  86. this.optionsEvensAuth('add', {
  87. click: () => {
  88. this.$refs.tabPage.addTab({
  89. activeKey: 'add',
  90. key: 'add',
  91. label: '新增',
  92. triggerEvent: () => {
  93. this.openForm()
  94. }
  95. })
  96. }
  97. })
  98. ]
  99. // [
  100. // this.optionsEvensAuth("pilqy", {
  101. // click: () => {
  102. // }
  103. // })
  104. // ],
  105. // [
  106. // this.optionsEvensAuth("piljy", {
  107. // click: () => {
  108. // }
  109. // })
  110. // ]
  111. ]
  112. ]
  113. },
  114. // 更多参数
  115. moreParameters() {
  116. return []
  117. },
  118. formItems() {
  119. return [
  120. {
  121. name: 'slot-component',
  122. md: 12,
  123. formItemAttributes: {
  124. label: '所属商户'
  125. },
  126. render: (h, { props }) => {
  127. return <el-input disabled={true} value={JSON.parse(localStorage.getItem('greemall_user')).companyName} />
  128. }
  129. },
  130. {
  131. name: 'el-select',
  132. md: 6,
  133. options: this.brandList,
  134. attributes: {
  135. disabled: false,
  136. placeholder: '请选择',
  137. clearable: true,
  138. filterable: true
  139. },
  140. formItemAttributes: {
  141. label: '选择品牌',
  142. prop: 'brandId',
  143. rules: [...required]
  144. },
  145. events: {
  146. change: val => {
  147. this.formData.brandName = this.brandList.find(item => item.value === val)?.label || ''
  148. }
  149. }
  150. },
  151. {
  152. name: 'el-select',
  153. md: 6,
  154. options: this.ClassifyList.map(item => ({ label: item.name, value: item.categoryId })),
  155. attributes: {
  156. disabled: false,
  157. placeholder: '请选择',
  158. clearable: true,
  159. filterable: true
  160. },
  161. formItemAttributes: {
  162. label: '选择大类',
  163. prop: 'mainId',
  164. rules: [...required]
  165. },
  166. events: {
  167. change: val => {
  168. this.formData.mainName =
  169. this.ClassifyList.map(item => ({ label: item.name, value: item.categoryId })).find(
  170. item => item.value === val
  171. )?.label || ''
  172. this.formData.smallId = ''
  173. }
  174. }
  175. },
  176. {
  177. name: 'el-select',
  178. md: 6,
  179. options: (this.ClassifyList.find(item => item.categoryId === this.formData.mainId)?.children || [])?.map(
  180. item => ({ label: item.name, value: item.categoryId })
  181. ),
  182. attributes: {
  183. disabled: false,
  184. placeholder: '请选择',
  185. clearable: true,
  186. filterable: true
  187. },
  188. formItemAttributes: {
  189. label: '选择小类',
  190. prop: 'smallId',
  191. rules: [...required]
  192. },
  193. events: {
  194. change: val => {
  195. this.formData.smallName =
  196. (this.ClassifyList.find(item => item.categoryId === this.formData.mainId)?.children || [])
  197. ?.map(item => ({ label: item.name, value: item.categoryId }))
  198. .find(item => item.value === val)?.label || ''
  199. }
  200. }
  201. },
  202. {
  203. name: 'el-input',
  204. md: 6,
  205. attributes: {
  206. disabled: false,
  207. placeholder: '请输入'
  208. },
  209. formItemAttributes: {
  210. label: '系列名称',
  211. prop: 'seriesName'
  212. }
  213. },
  214. {
  215. name: 'el-input',
  216. md: 6,
  217. attributes: {
  218. disabled: false,
  219. placeholder: '请输入'
  220. },
  221. formItemAttributes: {
  222. label: '商品名称',
  223. prop: 'goodsName',
  224. rules: [...required]
  225. }
  226. },
  227. {
  228. name: 'el-input',
  229. md: 6,
  230. attributes: {
  231. disabled: false,
  232. placeholder: '请输入'
  233. },
  234. formItemAttributes: {
  235. label: '规格型号',
  236. prop: 'specsName',
  237. rules: [...required]
  238. }
  239. },
  240. {
  241. name: 'el-input',
  242. md: 6,
  243. attributes: {
  244. disabled: false,
  245. placeholder: '请输入'
  246. },
  247. formItemAttributes: {
  248. label: '厂物料编码',
  249. prop: 'factoryNo',
  250. rules: []
  251. }
  252. },
  253. {
  254. md: 6,
  255. name: 'el-radio',
  256. options: [
  257. { label: '有效', value: 'ON' },
  258. { label: '无效', value: 'OFF' }
  259. ],
  260. attributes: {},
  261. formItemAttributes: {
  262. label: '状态',
  263. prop: 'state',
  264. rules: [...required]
  265. }
  266. },
  267. {
  268. md: 6,
  269. name: 'el-radio',
  270. options: [
  271. { label: '整套', value: 'C' },
  272. { label: '单个', value: 'I' }
  273. ],
  274. attributes: {},
  275. formItemAttributes: {
  276. label: '单位',
  277. prop: 'unit',
  278. rules: [...required]
  279. }
  280. },
  281. {
  282. md: 6,
  283. name: 'el-radio',
  284. options: [
  285. { label: '是', value: 'YES' },
  286. { label: '否', value: 'NO' }
  287. ],
  288. attributes: {},
  289. formItemAttributes: {
  290. label: '虚拟商品',
  291. prop: 'isVirtyual',
  292. rules: [...required]
  293. }
  294. },
  295. ...(() => {
  296. if (this.formData.isVirtyual === 'NO') {
  297. this.isEditIndex = -1
  298. return [
  299. {
  300. name: 'slot-component',
  301. md: 24,
  302. formItemAttributes: {
  303. label: '子物料',
  304. prop: 'items',
  305. rules: [...required]
  306. },
  307. render: (h, { props }) => {
  308. return (
  309. <div>
  310. <el-button
  311. size="mini"
  312. type="primary"
  313. onClick={() => {
  314. if (this.isEditIndex > -1) {
  315. this.$refs.formRef.validateField(
  316. this.getVfyKey(this.isEditIndex),
  317. (valid, invalidFields, errLabels) => {
  318. if (valid && this.eidtItems()) {
  319. this.formData.items.unshift({
  320. name: '',
  321. qty: '',
  322. type: '',
  323. uniqueCode: '',
  324. unit: ''
  325. })
  326. this.isEditIndex = 0
  327. }
  328. }
  329. )
  330. } else if (this.eidtItems()) {
  331. this.formData.items.unshift({
  332. name: '',
  333. qty: '',
  334. type: '',
  335. uniqueCode: '',
  336. unit: ''
  337. })
  338. this.isEditIndex = 0
  339. }
  340. }}
  341. >
  342. 新增
  343. </el-button>
  344. <zj-table columns={this.productColumns} table-data={this.formData.items} />
  345. </div>
  346. )
  347. }
  348. }
  349. ]
  350. }
  351. return []
  352. })(),
  353. {
  354. name: 'el-input',
  355. md: 24,
  356. attributes: {
  357. disabled: false,
  358. type: 'textarea',
  359. rows: 3,
  360. placeholder: '请输入'
  361. },
  362. formItemAttributes: {
  363. label: '备注',
  364. prop: 'remark',
  365. rules: []
  366. }
  367. }
  368. ]
  369. },
  370. productColumns() {
  371. return [
  372. {
  373. columnAttributes: {
  374. label: '物料类型',
  375. prop: 'type'
  376. },
  377. render: (h, { row, column, index }) => {
  378. return (
  379. <div class="redbordererr">
  380. <el-form-item
  381. label=""
  382. label-width="0px"
  383. prop={`items.${index}.${column.columnAttributes.prop}`}
  384. rules={required}
  385. >
  386. <el-select
  387. disabled={this.isEditIndex !== index}
  388. value={row[column.columnAttributes.prop]}
  389. onInput={val => {
  390. row[column.columnAttributes.prop] = val
  391. }}
  392. placeholder="请选择"
  393. >
  394. {[
  395. { value: 'INSIDE', label: '内机' },
  396. { value: 'OUT', label: '外机' },
  397. { value: 'PARTS', label: '配件' }
  398. ].map((item, index_) => (
  399. <el-option key={index_} label={item.label} value={item.value}></el-option>
  400. ))}
  401. </el-select>
  402. </el-form-item>
  403. </div>
  404. )
  405. }
  406. },
  407. {
  408. columnAttributes: {
  409. label: '名称',
  410. prop: 'name'
  411. },
  412. render: (h, { row, column, index }) => {
  413. return (
  414. <div class="redbordererr">
  415. <el-form-item
  416. label=""
  417. label-width="0px"
  418. prop={`items.${index}.${column.columnAttributes.prop}`}
  419. rules={required}
  420. >
  421. <el-input
  422. disabled={this.isEditIndex !== index}
  423. value={row[column.columnAttributes.prop]}
  424. onInput={val => {
  425. row[column.columnAttributes.prop] = val
  426. }}
  427. placeholder="请输入内容"
  428. ></el-input>
  429. </el-form-item>
  430. </div>
  431. )
  432. }
  433. },
  434. {
  435. columnAttributes: {
  436. label: '是否一物一码',
  437. prop: 'uniqueCode'
  438. },
  439. render: (h, { row, column, index }) => {
  440. return (
  441. <div class="redbordererr">
  442. <el-form-item
  443. label=""
  444. label-width="0px"
  445. prop={`items.${index}.${column.columnAttributes.prop}`}
  446. rules={required}
  447. >
  448. <el-select
  449. disabled={this.isEditIndex !== index}
  450. value={row[column.columnAttributes.prop]}
  451. onInput={val => {
  452. row[column.columnAttributes.prop] = val
  453. }}
  454. placeholder="请选择"
  455. >
  456. {[
  457. { label: '是', value: 'YES' },
  458. { label: '否', value: 'NO' }
  459. ].map((item, index_) => (
  460. <el-option key={index_} label={item.label} value={item.value}></el-option>
  461. ))}
  462. </el-select>
  463. </el-form-item>
  464. </div>
  465. )
  466. }
  467. },
  468. {
  469. columnAttributes: {
  470. label: '数量',
  471. prop: 'qty'
  472. },
  473. render: (h, { row, column, index }) => {
  474. return (
  475. <div class="redbordererr">
  476. <el-form-item
  477. label=""
  478. label-width="0px"
  479. prop={`items.${index}.${column.columnAttributes.prop}`}
  480. rules={required}
  481. >
  482. <el-input
  483. disabled={this.isEditIndex !== index}
  484. value={row[column.columnAttributes.prop]}
  485. onInput={val => {
  486. row[column.columnAttributes.prop] = val
  487. }}
  488. placeholder="请输入内容"
  489. ></el-input>
  490. </el-form-item>
  491. </div>
  492. )
  493. }
  494. },
  495. {
  496. columnAttributes: {
  497. label: '单位',
  498. prop: 'unit'
  499. },
  500. render: (h, { row, column, index }) => {
  501. return (
  502. <div class="redbordererr">
  503. <el-form-item
  504. label=""
  505. label-width="0px"
  506. prop={`items.${index}.${column.columnAttributes.prop}`}
  507. rules={required}
  508. >
  509. <el-input
  510. disabled={this.isEditIndex !== index}
  511. value={row[column.columnAttributes.prop]}
  512. onInput={val => {
  513. row[column.columnAttributes.prop] = val
  514. }}
  515. placeholder="请输入内容"
  516. ></el-input>
  517. </el-form-item>
  518. </div>
  519. )
  520. }
  521. },
  522. {
  523. columnAttributes: {
  524. label: '操作'
  525. },
  526. render: (h, { row, column, index }) => {
  527. return (
  528. <div style="padding-left:10px">
  529. <el-button
  530. type="text"
  531. onClick={() => {
  532. this.delProduct(row, index)
  533. }}
  534. >
  535. 删除
  536. </el-button>
  537. {this.isEditIndex == index && (
  538. <el-button
  539. type="text"
  540. onClick={() => {
  541. this.$refs.formRef.validateField(
  542. this.getVfyKey(this.isEditIndex),
  543. (valid, invalidFields, errLabels) => {
  544. if (valid && this.eidtItems()) {
  545. this.isEditIndex = -1
  546. }
  547. }
  548. )
  549. }}
  550. >
  551. 确定
  552. </el-button>
  553. )}
  554. {this.isEditIndex == -1 && (
  555. <el-button
  556. type="text"
  557. onClick={() => {
  558. this.isEditIndex = index
  559. }}
  560. >
  561. 编辑
  562. </el-button>
  563. )}
  564. </div>
  565. )
  566. }
  567. }
  568. ]
  569. }
  570. },
  571. methods: {
  572. // 列表请求函数
  573. getList: goodsMaterialList,
  574. // 列表导出函数
  575. exportList: goodsMaterialListExport,
  576. // 表格列解析渲染数据更改
  577. columnParsing(item, defaultData) {
  578. return defaultData
  579. },
  580. // 监听勾选变化
  581. selectionChange(data) {
  582. this.recordSelected = data
  583. },
  584. getVfyKey(index, bool = true) {
  585. return [
  586. ...(() => {
  587. if (bool) {
  588. return [`items`]
  589. }
  590. return []
  591. })(),
  592. ...(() => {
  593. if (index > -1) {
  594. return [
  595. `items.${index}.name`,
  596. `items.${index}.type`,
  597. `items.${index}.uniqueCode`,
  598. `items.${index}.qty`,
  599. `items.${index}.unit`
  600. ]
  601. }
  602. return []
  603. })()
  604. ]
  605. },
  606. eidtItems() {
  607. try {
  608. this.formData.items.map((item, index) => {
  609. this.formData.items.map((item2, index2) => {
  610. if (index !== index2 && `${item.type}_${item.name}` == `${item2.type}_${item2.name}`) {
  611. throw new Error('')
  612. }
  613. })
  614. })
  615. } catch (error) {
  616. this.$message.warning('子物料重复')
  617. return false
  618. }
  619. return true
  620. },
  621. operation() {
  622. return this.operationBtn({
  623. edit: {
  624. click: ({ row, index, column }) => {
  625. this.$refs.tabPage.addTab({
  626. activeKey: 'edit',
  627. key: 'edit',
  628. label: '编辑',
  629. triggerEvent: () => {
  630. this.openForm()
  631. goodsMaterialDetail({ id: row.id }).then(res => {
  632. this.formData = res.data
  633. console.log(this.formData)
  634. })
  635. }
  636. })
  637. }
  638. }
  639. })
  640. },
  641. openForm() {
  642. this.formCancel()
  643. getBrandList({
  644. status: true
  645. }).then(res => {
  646. this.brandList = res.data.map(item => ({
  647. label: item.brandName,
  648. value: item.id
  649. }))
  650. })
  651. getClassifyList({
  652. type: 2,
  653. status: true
  654. }).then(res => {
  655. this.ClassifyList = res.data
  656. })
  657. },
  658. formCancel() {
  659. this.$refs?.formRef?.resetFields()
  660. this.$data.formData = this.$options.data().formData
  661. },
  662. queding(removeTab) {
  663. this.$refs.formRef.validate((valid, invalidFields, errLabels) => {
  664. if (valid && this.eidtItems()) {
  665. ;[goodsMaterialAdd, goodsMaterialUpdate][this.formData.id ? 1 : 0](this.formData).then(res => {
  666. this.$message({
  667. type: 'success',
  668. message: '保存成功'
  669. })
  670. this.$refs.pageRef.refreshList()
  671. removeTab()
  672. })
  673. }
  674. })
  675. },
  676. delProduct(row, index) {
  677. if (index > this.isEditIndex) {
  678. this.formData?.items?.splice(index, 1)
  679. } else if (index == this.isEditIndex) {
  680. this.formData?.items?.splice(index, 1)
  681. this.isEditIndex = -1
  682. }
  683. }
  684. }
  685. }
  686. </script>
  687. <style lang="scss" scoped>
  688. .tab {
  689. padding: 20px 20px 0 20px;
  690. }
  691. </style>