index.vue 20 KB

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