addCommodity.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. <template>
  2. <div>
  3. <el-card class="box-card">
  4. <div slot="header">
  5. <span v-if="!productId" class="addTitle">新增商品</span>
  6. <span v-else class="addTitle">编辑商品</span>
  7. <el-button v-if="active" class="btnList" @click="back">取消</el-button>
  8. <el-button v-if="active" type="primary" class="btnList" @click="next">下一步</el-button>
  9. <el-button v-if="!active" class="btnList" @click="last">上一步</el-button>
  10. </div>
  11. <!-- 步骤条 -->
  12. <div class="stepsColor common">
  13. <div class="stepsOne common">
  14. <div :class="active ? 'one_class common' : 't_class common'">1</div>
  15. <div :class="active ? 'two_class' : 'w_class'">基本属性&商品描述</div>
  16. </div>
  17. <div class="line" />
  18. <div class="stepsTwo common">
  19. <div :class="active ? 't_class common' : 'one_class common'">2</div>
  20. <div :class="active ? 'w_class' : 'two_class'">基本属性&商品描述</div>
  21. </div>
  22. </div>
  23. </el-card>
  24. <!-- 商品 -->
  25. <div class="addCom common">
  26. <div v-if="active">
  27. <el-form ref="form" :model="form" :disabled="true" :rules="rules" label-width="100px" style="padding: 40px 40px;">
  28. <div class="leftCom">
  29. <el-form-item label="商品名称" prop="productName">
  30. <el-input v-model="form.productName" maxlength="40" show-word-limit />
  31. </el-form-item>
  32. <el-form-item label="卖点简介">
  33. <el-input v-model="form.productBrief" maxlength="50" show-word-limit />
  34. </el-form-item>
  35. <el-form-item
  36. label="商品排序值" prop="sortId"
  37. >
  38. <el-input v-model.number="form.sortId" show-word-limit />
  39. </el-form-item>
  40. <el-form-item>
  41. <Tinymce v-if="showTinymce" ref="content" v-model="form.productText" class="tinymce-wrap" :height="200" />
  42. </el-form-item>
  43. </div>
  44. <div class="rightCom">
  45. <el-form-item label="官方分类" prop="classifyId">
  46. <el-cascader
  47. v-model="form.classifyId" :options="classifyList" clearable :props="{
  48. checkStrictly: false,
  49. label: 'categoryName',
  50. value: 'id',
  51. children: 'childs'
  52. }"
  53. @change="handleChangeCascader"
  54. />
  55. </el-form-item>
  56. <el-form-item label="商品分组" prop="shopGroupId">
  57. <el-cascader
  58. v-model="form.shopGroupId" :options="groupList" clearable :props="{
  59. checkStrictly: false,
  60. label: 'groupName',
  61. value: 'shopGroupId',
  62. children: 'childs',
  63. checkStrictly: true,
  64. emitPath: false
  65. }"
  66. />
  67. </el-form-item>
  68. <el-form-item label="品牌">
  69. <el-select v-model="form.brandId" clearable placeholder="请选择品牌">
  70. <el-option v-for="item in brandList" :key="item.id" :label="item.brandName" :value="item.id" />
  71. </el-select>
  72. </el-form-item>
  73. <el-form-item class="form-item-long" label="供应商">
  74. <el-input v-model="form.supplierName" maxlength="20" show-word-limit placeholder="请输入供应商名称" />
  75. </el-form-item>
  76. <el-form-item class="form-item-long" label="商品型号">
  77. <el-input v-model.trim="form.productMarque" placeholder="请输入商品型号" />
  78. </el-form-item>
  79. <el-form-item label="需要物流" prop="ifLogistics">
  80. <el-radio-group v-model="form.ifLogistics">
  81. <el-radio :label="1">是</el-radio>
  82. <el-radio :label="0">否</el-radio>
  83. </el-radio-group>
  84. </el-form-item>
  85. <el-form-item label="上架状态" prop="shelveState">
  86. <el-radio-group v-model="form.shelveState">
  87. <el-radio :label="1">上架</el-radio>
  88. <el-radio :label="0">下架</el-radio>
  89. </el-radio-group>
  90. </el-form-item>
  91. <el-form-item label="允许超卖" prop="ifOversold">
  92. <el-radio-group v-model="form.ifOversold">
  93. <el-radio :label="1">允许</el-radio>
  94. <el-radio :label="0">不允许</el-radio>
  95. </el-radio-group>
  96. </el-form-item>
  97. <el-form-item label="积分兑换" prop="ifCredit">
  98. <el-radio-group v-model="form.ifCredit">
  99. <el-radio :label="1">允许</el-radio>
  100. <el-radio :label="0">不允许</el-radio>
  101. </el-radio-group>
  102. <p style="color: #cf0f0f">开启积分兑换后,积分所抵扣的金额由商户承担</p>
  103. </el-form-item>
  104. <el-form-item v-if="form.ifCredit" class="form-item-long" label="单笔最大抵扣" prop="creditLimit">
  105. <!-- <el-input v-model="form.creditLimit" type="number" placeholder="请输入单笔最大抵扣" /> -->
  106. <el-input-number
  107. v-model="form.creditLimit" :controls="false" :max="999999999" :min="0"
  108. :precision="0"
  109. placeholder="请输入单笔最大抵扣"
  110. />
  111. <p style="color: #cf0f0f; height: 25px; line-height: 25px;margin-top: 10px">限制一笔订单中该商品最多抵扣多少积分</p>
  112. <p style="color: #cf0f0f; height: 25px; line-height: 25px">( 注:1积分 = {{ integralProportion }}元 请输入整数 )</p>
  113. </el-form-item>
  114. </div>
  115. </el-form>
  116. </div>
  117. <div v-if="!active" class="centerCom">
  118. <el-form ref="form" :model="params" label-width="80px">
  119. <StyleInformation @cancel="cancel" v-bind="$props" :form="params" @syncVoucherPrice="handleSyncVoucherPrice" @syncVoucherId="handleSyncVoucherId" />
  120. </el-form>
  121. </div>
  122. </div>
  123. <!-- 弹窗 -->
  124. <el-dialog :visible.sync="dialogVisible" class="check-image-dialog" title="查看图片" center="center">
  125. <img width="100%" :src="dialogImageUrl" alt>
  126. </el-dialog>
  127. </div>
  128. </template>
  129. <script>
  130. import Tinymce from '@/components/Tinymce'
  131. import {
  132. getGroupSelect,
  133. getClassify,
  134. getClassifyAdd,
  135. getClassifyGetById,
  136. getClassifyUpdate,
  137. getBrandList
  138. } from '@/api/commodity'
  139. import {
  140. getSelect
  141. } from '@/api/account'
  142. import { uploadUrl } from '@/utils/request'
  143. import StyleInformation from './addComponent'
  144. export default {
  145. name: 'Bugyellow',
  146. components: {
  147. Tinymce,
  148. StyleInformation
  149. },
  150. props: {
  151. productId: {
  152. type: Number,
  153. default: 0
  154. },
  155. showTinymce: {
  156. type: Boolean
  157. },
  158. voucherList: {
  159. type: Array,
  160. default: []
  161. }
  162. },
  163. data() {
  164. return {
  165. brandList: [],
  166. active: 1,
  167. action: uploadUrl,
  168. form: {
  169. brandId: null, // 品牌ID
  170. productName: '', // 商品名称
  171. productBrief: '', // 商品简介
  172. shopGroupId: '', // 商品分组id
  173. classifyId: '', // 分类id
  174. sortId: 0, // 排序值
  175. productMarque: '', // 商品型号
  176. supplierName: '', // 供应商名称
  177. ifLogistics: '', // 是否需要物流 1-是 0-否
  178. shelveState: '', // 是否上架 1-上架 0-不上架
  179. ifOversold: '', // 是否允许超卖 1-是 0-否
  180. ifCredit: '', // 是否支持积分兑换 1-是 0-否
  181. ifSelection: -1,
  182. creditLimit: '', // 单笔订单限制使用多少积分
  183. ifHuabei: 1, // 是否支持花呗分期 1-是 0-否
  184. productText: '', // 商品描述(富文本)
  185. images: [], // "图片地址"
  186. deletes: [], // 删除的规格id数组
  187. names: [
  188. {
  189. code: '', // 级别
  190. skuName: '', // 规格名
  191. values: [
  192. {
  193. valueCode: '', // 级别
  194. skuValue: '', // 规格值
  195. image: '' // 图片
  196. }
  197. ]
  198. }
  199. ],
  200. skus: [
  201. {
  202. skuName: '', // 规格名称
  203. skuValue: '', // 规格值
  204. price: '', // 售价
  205. originalPrice: '', // 原价
  206. stockNumber: '', // 库存数量
  207. weight: '', // 重量
  208. skuImage: '', // 配图地址
  209. style: '', // 款式 1-单款式 2-多款式
  210. voucherId: '', // 允许使用的代金券ID
  211. voucherPrice: '' // 代金券最大的使用限额
  212. }
  213. ]
  214. },
  215. params: {
  216. applyPrice: 0,
  217. attrStyle: 0,
  218. categoryId: '',
  219. oversold: 1,
  220. collects: 0,
  221. groupId: '',
  222. imgs: [],
  223. deletes: [], // 删除规格数据
  224. isDelete: 0,
  225. limitCount: 0,
  226. minusStock: '',
  227. needLogistics: 1,
  228. platform: '',
  229. price: 0,
  230. productCode: '',
  231. productName: '',
  232. sellCount: 0,
  233. sellDesc: '',
  234. sellType: '',
  235. shortName: '',
  236. skuAttrList: [
  237. {
  238. code: '',
  239. skuName: '',
  240. needImg: false,
  241. values: [
  242. {
  243. skuValue: '',
  244. valueCode: '',
  245. image: ''
  246. }
  247. ]
  248. }
  249. ],
  250. skuList: [
  251. {
  252. originalPrice: 0,
  253. price: 0,
  254. productId: '',
  255. skuAttrCodeDTOList: [
  256. {
  257. code: '',
  258. valueCode: ''
  259. }
  260. ],
  261. skuId: '',
  262. skuImage: '',
  263. stockNumber: 0,
  264. voucherId: 0,
  265. voucherPrice: 0,
  266. weight: 0
  267. }
  268. ],
  269. sortOrder: '',
  270. status: '',
  271. stock: '',
  272. supplierName: '',
  273. views: '',
  274. weight: ''
  275. },
  276. imgList: [],
  277. groupList: [],
  278. classifyList: [],
  279. dialogImageUrl: '',
  280. dialogVisible: false,
  281. rules: {
  282. productName: [ { required: true, message: '请输入商品名称', trigger: 'blur' } ],
  283. sortId: [{ required: false, message: '请输入排序值', trigger: 'blur' }, { type: 'number', message: '排序值必须为数字' }],
  284. shopGroupId: [ { required: true, message: '请选择商品分组', trigger: 'change' } ],
  285. classifyId: [ { required: true, message: '请选择商品分类', trigger: 'change' } ],
  286. ifLogistics: [ { required: true, message: '请选择是否需要物流', trigger: 'change' } ],
  287. shelveState: [ { required: true, message: '请选择是否上架', trigger: 'change' } ],
  288. ifOversold: [ { required: true, message: '请选择是否允许超卖', trigger: 'change' } ],
  289. ifCredit: [ { required: true, message: '请选择是否支持积分兑换', trigger: 'change' } ],
  290. creditLimit: [ { required: true, message: '请输入单笔最大抵扣', trigger: 'blur' } ]
  291. },
  292. integralList: [],
  293. integralProportion: '' // 积分兑换金额比例
  294. }
  295. },
  296. watch: {
  297. productId: {
  298. handler(nVal, oVal) {
  299. if (nVal) {
  300. // this.details()
  301. }
  302. }
  303. }
  304. },
  305. mounted() {
  306. // console.log(this.voucherList)
  307. this.groups()
  308. this.selectList()
  309. this.getBrandList()
  310. // if (this.productId) {
  311. // this.details()
  312. // }
  313. this.getCredit()
  314. },
  315. methods: {
  316. // 向上一级传递事件
  317. cancel(){
  318. this.$emit("cancel")
  319. },
  320. handleChangeCascader() {
  321. console.log(this.form.classifyId)
  322. },
  323. async getBrandList() {
  324. const { data } = await getBrandList()
  325. this.brandList = data
  326. },
  327. async getCredit() {
  328. const res = await getSelect({ dictName: 'CREDIT_CONFIG' })
  329. this.integralList = res.data
  330. this.integralList.forEach((item) => {
  331. if (item.dictName === 'credit_exchange_rate') {
  332. this.integralProportion = item.dictDescribe
  333. }
  334. })
  335. },
  336. handleImageSuccess(response) {
  337. const { url } = response.data
  338. this.imgList.push(url)
  339. },
  340. handlePictureCardPreview(file) {
  341. this.dialogImageUrl = file.imgPath
  342. this.dialogVisible = true
  343. },
  344. // 移除图片
  345. handleRemove(file) {
  346. const { imgPath } = file
  347. this.form.imgs = this.form.imgs.filter((item) => item.imgPath !== imgPath)
  348. },
  349. // 下一步
  350. next() {
  351. this.$refs.form.validate((valid) => {
  352. console.log('val', valid)
  353. if (valid) {
  354. if (this.active === 1) {
  355. this.active = 0
  356. // console.log(this.form);
  357. sessionStorage.setItem('form', JSON.stringify(this.form.skus))
  358. }
  359. } else {
  360. this.$message({
  361. message: '请填写正确的信息',
  362. type: 'warning'
  363. })
  364. return false
  365. }
  366. })
  367. },
  368. // 同步代金券抵扣额度
  369. handleSyncVoucherPrice() {
  370. this.params.skuList.forEach((element) => {
  371. element.voucherPrice = element.price
  372. })
  373. },
  374. // 统一选择代金券
  375. handleSyncVoucherId(e) {
  376. this.params.skuList.forEach((element) => {
  377. element.voucherId = e
  378. })
  379. },
  380. // 点击新增商品时表单数据重置
  381. reset() {
  382. // this.form.productText = ''
  383. this.form = {
  384. productName: '',
  385. productBrief: '',
  386. shopGroupId: '',
  387. classifyId: '',
  388. supplierName: '',
  389. ifLogistics: '',
  390. shelveState: ' ',
  391. ifOversold: '',
  392. ifCredit: '',
  393. ifSelection: -1,
  394. creditLimit: '',
  395. ifHuabei: 1,
  396. productText: '',
  397. images: [],
  398. deletes: [],
  399. names: [
  400. {
  401. code: '',
  402. skuName: '',
  403. values: [
  404. {
  405. valueCode: '',
  406. skuValue: '',
  407. image: ''
  408. }
  409. ]
  410. }
  411. ],
  412. skus: [
  413. {
  414. skuName: '',
  415. skuValue: '',
  416. price: '',
  417. originalPrice: '',
  418. stockNumber: '',
  419. weight: '',
  420. skuImage: '',
  421. style: ''
  422. }
  423. ]
  424. }
  425. this.params = {
  426. applyPrice: 0,
  427. attrStyle: 0,
  428. categoryId: '',
  429. oversold: 1,
  430. collects: 0,
  431. groupId: '',
  432. imgs: [],
  433. deletes: [],
  434. isDelete: 0,
  435. limitCount: 0,
  436. minusStock: '',
  437. needLogistics: 1,
  438. platform: '',
  439. price: 0,
  440. productCode: '',
  441. productName: '',
  442. sellCount: 0,
  443. sellDesc: '',
  444. sellType: '',
  445. shortName: '',
  446. skuAttrList: [
  447. {
  448. code: '',
  449. skuName: '',
  450. needImg: false,
  451. values: [
  452. {
  453. skuValue: '',
  454. valueCode: '',
  455. image: ''
  456. }
  457. ]
  458. }
  459. ],
  460. skuList: [
  461. {
  462. originalPrice: 0,
  463. price: 0,
  464. productId: '',
  465. skuAttrCodeDTOList: [
  466. {
  467. code: '',
  468. valueCode: ''
  469. }
  470. ],
  471. skuId: '',
  472. skuImage: '',
  473. stockNumber: 0,
  474. voucherId: 0,
  475. voucherPrice: 0,
  476. weight: 0
  477. }
  478. ],
  479. sortOrder: '',
  480. status: '',
  481. stock: '',
  482. supplierName: '',
  483. views: '',
  484. weight: ''
  485. }
  486. this.imgList = []
  487. this.dialogImageUrl = ''
  488. this.dialogVisible = false
  489. this.active = 1
  490. },
  491. // 返回
  492. back() {
  493. this.active = 1
  494. this.$emit('cancel')
  495. },
  496. // 上一步
  497. last() {
  498. if (this.active !== 1) {
  499. this.active = 1
  500. }
  501. },
  502. // 获取商品分组
  503. async groups() {
  504. const res = await getGroupSelect({
  505. })
  506. this.groupList = res.data
  507. },
  508. // 获取详情
  509. async details() {
  510. const res = await getClassifyGetById({ productId: this.productId })
  511. this.form = res.data
  512. this.$set(this.form, 'productText', res.data.productText)
  513. // this.form.productText = res.data.productText
  514. // console.log(this.form.productText, 'productText')
  515. if (res.data.names.length !== 0) {
  516. this.params.skuAttrList = res.data.names
  517. }
  518. // this.params.skuAttrList.forEach((item) => {
  519. // var data = {}
  520. // var arr = Object.keys(res.data)
  521. // if (arr.length === 0) {
  522. // item.needImg = false
  523. // }
  524. // })
  525. this.params.skuList = this.form.skus
  526. this.params.attrStyle = res.data.skus[0]?.style
  527. this.params.imgs = res.data.images
  528. },
  529. async selectList() {
  530. const res = await getClassify()
  531. this.classifyList = this.filterList(res.data)
  532. },
  533. filterList(data) {
  534. data.forEach((i) => {
  535. if (i.childs.length) {
  536. this.filterList(i.childs)
  537. } else {
  538. i.childs = null
  539. }
  540. })
  541. return data
  542. }
  543. }
  544. }
  545. </script>
  546. <style scoped lang='scss'>
  547. @import url("../../../styles/elDialog.scss");
  548. .btnList {
  549. float: right;
  550. padding: 3px 0;
  551. width: 100px;
  552. height: 40px;
  553. border-radius: 4px;
  554. margin-right: 30px;
  555. }
  556. .addTitle {
  557. font-size: 20px;
  558. color: #333333;
  559. line-height: 50px;
  560. }
  561. .stepsColor {
  562. font-size: 20px;
  563. line-height: 40px;
  564. .one_class {
  565. width: 40px;
  566. background: #3a68f2;
  567. border-radius: 50%;
  568. color: #ffffff;
  569. margin: 0 10px;
  570. }
  571. .two_class {
  572. color: #3a68f2;
  573. }
  574. .line {
  575. width: 230px;
  576. height: 2px;
  577. background: #e0e5eb;
  578. margin: 0 20px;
  579. }
  580. .t_class {
  581. width: 40px;
  582. background: #dddddd;
  583. border-radius: 50%;
  584. color: #333333;
  585. margin: 0 10px;
  586. }
  587. .w_class {
  588. color: #666666;
  589. }
  590. }
  591. .common {
  592. display: flex;
  593. justify-content: center;
  594. align-items: center;
  595. }
  596. .addCom {
  597. margin: 10px 0;
  598. justify-content: space-around;
  599. align-items: unset;
  600. .el-form {
  601. display: flex;
  602. padding: 40px 0;
  603. }
  604. .leftCom {
  605. width: 65%;
  606. background: #ffffff;
  607. }
  608. .rightCom {
  609. width: 35%;
  610. background: #ffffff;
  611. margin-left: 80px;
  612. }
  613. }
  614. .centerCom {
  615. width: 1660px;
  616. background: #ffffff;
  617. box-shadow: 0px 5px 20px 0px rgba(51, 51, 51, 0.15);
  618. border-radius: 4px;
  619. }
  620. </style>
  621. <style scoped>
  622. .form-item-long>>>.el-input {
  623. width: 100%;
  624. }
  625. </style>