add.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. <template>
  2. <div class="app-container goods-add">
  3. <el-divider content-position="left">商品信息</el-divider>
  4. <el-form ref="addItem" :rules="rules" :model="addData" label-width="120px">
  5. <el-row :gutter="40" style="width: 500px">
  6. <el-col :span="23">
  7. <el-form-item label="商品类型:" prop="type">
  8. <el-radio-group v-model="addData.type">
  9. <el-radio :label="1">实物商品</el-radio>
  10. <el-radio :label="2">卡密商品</el-radio>
  11. </el-radio-group>
  12. </el-form-item>
  13. </el-col>
  14. </el-row>
  15. <el-row :gutter="40" style="width: 600px">
  16. <el-col :span="23">
  17. <el-form-item label="商品名称:" prop="title">
  18. <el-input v-model="addData.title" placeholder="请输入商品名称"/>
  19. </el-form-item>
  20. </el-col>
  21. <el-col :span="23">
  22. <el-form-item label="商品主图:" prop="picUrl">
  23. <Upload v-model="mainPicUrl" :limit="10"/>
  24. <div class="tip">第一张图片将作为商品列表图片,最多上传10张,多张图片之间可随意调整位置,支持jpg、png格式,推荐750*750px;</div>
  25. </el-form-item>
  26. </el-col>
  27. </el-row>
  28. <el-row :gutter="40" style="width: 500px">
  29. <el-col :span="23">
  30. <el-form-item label="支持盲豆兑换:" prop="exchangeShow">
  31. <!-- <el-switch-->
  32. <!-- v-model="addData.exchangeShow"-->
  33. <!-- :active-value="1"-->
  34. <!-- :inactive-value="0"-->
  35. <!-- />-->
  36. <!-- <div class="tip">关闭则不再兑换大厅显示,不支持盲豆兑换。</div>-->
  37. <el-radio-group v-model="addData.exchangeShow">
  38. <el-radio :label="0">不支持</el-radio>
  39. <el-radio :label="1">支持</el-radio>
  40. <el-radio :label="2">盲票商品</el-radio>
  41. </el-radio-group>
  42. </el-form-item>
  43. </el-col>
  44. </el-row>
  45. <el-row :gutter="40" style="width: 500px">
  46. <el-col :span="23">
  47. <el-form-item label="商品分类:" prop="categoryId">
  48. <el-cascader
  49. v-model="addData.categoryId" clearable
  50. :options="goodsCategoryItemsList"
  51. :props="{ expandTrigger: 'hover', value: 'categoryId',label: 'name', children: 'goodsCategoryList', }"></el-cascader>
  52. </el-form-item>
  53. </el-col>
  54. </el-row>
  55. <el-row :gutter="40" style="width: 500px">
  56. <el-col :span="23">
  57. <el-form-item label="供应商:" prop="supplierId">
  58. <el-select
  59. v-model="addData.supplierId"
  60. placeholder="请选择供应商"
  61. filterable
  62. clearable
  63. >
  64. <el-option :label="item.name" :value="item.id" v-for="(item, index) in SupplierList" :key="index"/>
  65. </el-select>
  66. <a style="margin-left: 20px;color: #1890FF;" @click="handleAdd">添加供应商</a>
  67. </el-form-item>
  68. </el-col>
  69. </el-row>
  70. <el-row :gutter="40" style="width: 500px">
  71. <el-col :span="23">
  72. <el-form-item label="商品采购链接:">
  73. <el-input v-model="addData.shoppingLink" placeholder="请输入商品采购链接"/>
  74. </el-form-item>
  75. </el-col>
  76. </el-row>
  77. <el-row :gutter="40" style="width: 500px">
  78. <el-col :span="23">
  79. <el-form-item label="商品标签:">
  80. <el-select
  81. v-model="addData.tagIds"
  82. placeholder="请选择商品标签"
  83. multiple
  84. clearable
  85. >
  86. <el-option :label="item.name" :value="item.tagId" v-for="(item, index) in goodsTagItemsList"
  87. :key="index"/>
  88. </el-select>
  89. </el-form-item>
  90. </el-col>
  91. <el-col :span="23">
  92. <el-form-item label="商家信息:">
  93. <Upload v-model="MerchantInformation" :limit="10"/>
  94. <div class="tip">上传商家营业执照</div>
  95. </el-form-item>
  96. </el-col>
  97. </el-row>
  98. <el-divider content-position="left">价格库存</el-divider>
  99. <el-row>
  100. <el-col :span="23">
  101. <el-form-item label="启用多SKU:" v-if="addData.type == '1'">
  102. <el-switch
  103. v-model="addData.multiSku"
  104. :active-value="1"
  105. :inactive-value="0"
  106. />
  107. </el-form-item>
  108. </el-col>
  109. </el-row>
  110. <el-row>
  111. <el-col :span="22">
  112. <el-form-item prop="skuList">
  113. <Spec ref="spec" @valid="update" :multiSku="addData.multiSku"/>
  114. </el-form-item>
  115. </el-col>
  116. </el-row>
  117. <el-row v-if="addData.multiSku === 0" :gutter="40" style="width: 600px">
  118. <el-col :span="23">
  119. <el-form-item label="价格:" prop="value">
  120. <el-input v-model="addData.value" type="number" placeholder="请输入商品价格">
  121. <template slot="append">元</template>
  122. </el-input>
  123. </el-form-item>
  124. </el-col>
  125. <el-col :span="23">
  126. <el-form-item label="盲豆兑换数量:" prop="exchangePrice">
  127. <el-input v-model="addData.exchangePrice" type="number" placeholder="请输入盲豆数量">
  128. <template slot="append">盲豆</template>
  129. </el-input>
  130. </el-form-item>
  131. </el-col>
  132. <el-col :span="23">
  133. <el-form-item label="回收折扣:" prop="discountRate">
  134. <el-input v-model="addData.discountRate" type="number" placeholder="请输入回收折扣">
  135. <template slot="append">%</template>
  136. </el-input>
  137. </el-form-item>
  138. </el-col>
  139. <el-col :span="23">
  140. <el-form-item label="盲豆划线价:">
  141. <el-input v-model="addData.originPrice" type="number" placeholder="请输入盲豆数量">
  142. <template slot="append">盲豆</template>
  143. </el-input>
  144. </el-form-item>
  145. </el-col>
  146. <el-col :span="23">
  147. <el-form-item label="商品成本:" prop="cost">
  148. <el-input v-model="addData.cost" type="number" placeholder="请输入商品成本">
  149. <template slot="append">元</template>
  150. </el-input>
  151. </el-form-item>
  152. </el-col>
  153. <el-col :span="23">
  154. <el-form-item label="商品编码:" prop="goodsCode">
  155. <el-input v-model="addData.goodsCode" type="text" placeholder="请输入商品编码">
  156. </el-input>
  157. </el-form-item>
  158. </el-col>
  159. <el-col :span="23">
  160. <el-form-item label="库存:" prop="quantity" v-if="addData.type == '1'">
  161. <el-input v-model="addData.quantity" type="number" placeholder="请输入商品库存">
  162. <template slot="append">件</template>
  163. </el-input>
  164. </el-form-item>
  165. </el-col>
  166. <el-col :span="23">
  167. <el-form-item label="使用链接:" v-if="addData.type == '2'">
  168. <el-input v-model="addData.type" placeholder="请输入商品采购链接"/>
  169. </el-form-item>
  170. </el-col>
  171. <el-col :span="23">
  172. <el-form-item label="查看卡密:" v-if="addData.goodsId && addData.type == '2'">
  173. <a style="color: #1890FF;" @click="camiloShow = true">查看已有卡密</a>
  174. </el-form-item>
  175. </el-col>
  176. <el-col :span="23">
  177. <el-form-item label="添加卡密:" v-if="addData.type == '2'">
  178. <a style="color: #1890FF;">下载Excel模版</a>
  179. <el-upload
  180. ref="upload"
  181. :limit="1"
  182. :data="reqData"
  183. accept=".xlsx, .xls"
  184. :headers="upload.headers"
  185. :action="upload.url"
  186. :disabled="upload.isUploading"
  187. :on-progress="handleFileUploadProgress"
  188. :on-success="handleFileSuccess"
  189. :auto-upload="false"
  190. :http-request="reqUploadFile"
  191. :on-exceed="exceedMax"
  192. drag
  193. >
  194. <i class="el-icon-upload"></i>
  195. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  196. </el-upload>
  197. </el-form-item>
  198. </el-col>
  199. </el-row>
  200. <!-- <el-divider content-position="left">商品详情</el-divider> -->
  201. <el-row>
  202. <el-col :span="22">
  203. <el-form-item label="商品详情" prop="description">
  204. <wang-editor ref="editor" v-model="addData.description"/>
  205. </el-form-item>
  206. </el-col>
  207. </el-row>
  208. </el-form>
  209. <br>
  210. <el-row>
  211. <el-col :span="24" style="text-align: center">
  212. <el-button type="info" @click="$router.replace('/goods/list')">取消</el-button>
  213. <el-button type="primary" @click="updateItem()">保存</el-button>
  214. </el-col>
  215. </el-row>
  216. <add-supplier
  217. v-if="createShow"
  218. :dialog-show="createShow"
  219. @close="close"
  220. />
  221. <camilo v-if="camiloShow" @cancel="cancel" :camiloShow="camiloShow"></camilo>
  222. </div>
  223. </template>
  224. <script>
  225. import Upload from '@/components/DragImageUpload'
  226. import WangEditor from '@/components/WangEditor'
  227. import Spec from './components/spec'
  228. import TinyEditor from '@/components/TinyEditor'
  229. import Camilo from '@/components/Camilo'
  230. import {getGoodsDetail, addGoods} from '@/api/business/goods'
  231. import {goodsCategoryListTree} from '@/api/business/category'
  232. import {getSupplierList} from '@/api/business/supplier'
  233. import {goodsTagItems} from '@/api/business/tag'
  234. import {publicFileGetUrl} from "@/api/common"
  235. import {accDiv, accMul} from '@/utils/util'
  236. import AddSupplier from "../supplier/components/addSupplier";
  237. import {randomStr20} from '@/utils/util'
  238. import {getToken, getSign} from "@/utils/auth";
  239. export default {
  240. name: 'GoodsAdd',
  241. components: {
  242. TinyEditor,
  243. WangEditor,
  244. Upload,
  245. Spec,
  246. AddSupplier,
  247. Camilo
  248. },
  249. data() {
  250. return {
  251. IMG_URL: publicFileGetUrl,
  252. id: this.$route.query.id,
  253. goodsCategoryItemsList: [],
  254. SupplierList: [],
  255. goodsTagItemsList: [],
  256. addData: {
  257. type: 1,
  258. multiSku: 0,
  259. description: '',
  260. originPrice: 0,
  261. exchangeShow: 0,
  262. },
  263. createShow: false,
  264. rules: {
  265. title: [{required: true, message: '请输入商品名称', trigger: 'blur'}],
  266. picUrl: [{required: true, message: '请上传商品图片', trigger: 'change'}],
  267. categoryId: [{required: true, message: '请选择商品分类', trigger: 'change'}],
  268. supplierId: [{required: true, message: '请选择供应商', trigger: 'change'}],
  269. exchangeShow: [{required: true, message: '请选择是否支持盲豆兑换', trigger: 'change'}],
  270. multiSku: [{required: true, message: '请选择SKU类型', trigger: 'change'}],
  271. value: [
  272. {required: true, message: '请输商品入价格', trigger: 'blur'},
  273. {
  274. pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
  275. message: "请输入正确的金额,最多两位小数",
  276. trigger: ["blur", "change"]
  277. }
  278. ],
  279. exchangePrice: [
  280. {required: true, message: '请输入盲豆数量', trigger: 'blur'},
  281. {pattern: /^([1-9]\d*)$/, message: "请输入正确盲豆数量", trigger: ["blur", "change"]}
  282. ],
  283. discountRate: [
  284. {required: true, message: '请输入回收折扣', trigger: 'blur'},
  285. {
  286. pattern:
  287. /^([0-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
  288. message: "请输入合法的数字,最多两位小数",
  289. trigger: ["blur", "change"],
  290. },
  291. ],
  292. cost: [
  293. {required: false, message: '请输入商品成本', trigger: 'blur'},
  294. {
  295. pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
  296. message: "请输入正确的金额,最多两位小数",
  297. trigger: ["blur", "change"]
  298. }
  299. ],
  300. quantity: [
  301. {required: true, message: '请输入库存', trigger: 'blur'},
  302. {pattern: /^([1-9]\d*)$/, message: "请输入正确的数字", trigger: ["blur", "change"]}
  303. ],
  304. description: [{required: true, message: '请输入商品详情', trigger: 'blur'}]
  305. },
  306. reqData: {},
  307. // 用户导入参数
  308. upload: {
  309. title: "",// 弹出层标题(用户导入)
  310. isUploading: false,// 是否禁用上传
  311. url: "",// 上传的地址
  312. headers: {},//请求头
  313. },
  314. camiloShow: false,
  315. }
  316. },
  317. computed: {
  318. mainPicUrl: {
  319. get() {
  320. return this.addData.picUrl ? this.addData.picUrl.split(',').map(item => {
  321. return {
  322. fileName: item
  323. }
  324. }) : []
  325. },
  326. set(val) {
  327. this.$set(this.addData, 'picUrl', val.map(item => {
  328. return item.fileName
  329. }).toString())
  330. }
  331. },
  332. MerchantInformation: {
  333. get() {
  334. return this.addData.merchantInfo ? this.addData.merchantInfo.split(',').map(item => {
  335. return {
  336. fileName: item
  337. }
  338. }) : []
  339. },
  340. set(val) {
  341. this.$set(this.addData, 'merchantInfo', val.map(item => {
  342. return item.fileName
  343. }).toString())
  344. }
  345. }
  346. },
  347. created() {
  348. this.getGoodsCategoryItems()
  349. this.getSupplierItems()
  350. this.getGoodsTagItems()
  351. if (this.id) {
  352. getGoodsDetail(this.id).then(res => {
  353. const {
  354. goodsId,
  355. title,
  356. type,
  357. goodsCode,
  358. picUrl,
  359. merchantInfo,
  360. exchangeShow,
  361. multiSku,
  362. value,
  363. exchangePrice,
  364. originPrice,
  365. discountRate,
  366. cost,
  367. quantity,
  368. description,
  369. skuList,
  370. categoryId,
  371. supplierId,
  372. shoppingLink,
  373. tagIds
  374. } = res.data
  375. this.addData = {
  376. value: accDiv(value, 100),
  377. cost: cost == '' || cost == null ? '' : accDiv(cost, 100),
  378. goodsId,
  379. title,
  380. type,
  381. goodsCode,
  382. picUrl,
  383. merchantInfo,
  384. exchangeShow,
  385. multiSku,
  386. exchangePrice,
  387. discountRate,
  388. originPrice,
  389. quantity,
  390. description,
  391. skuList,
  392. categoryId,
  393. supplierId,
  394. shoppingLink,
  395. tagIds
  396. }
  397. if (description) {
  398. this.$refs.editor.setContent(description)
  399. }
  400. if (multiSku && skuList instanceof Array && skuList.length > 0) {
  401. this.$nextTick(() => {
  402. this.$refs.spec.setSkuList(skuList)
  403. })
  404. }
  405. })
  406. }
  407. this.getHttpHeader()
  408. },
  409. methods: {
  410. getGoodsCategoryItems() {
  411. goodsCategoryListTree("", {}).then(res => {
  412. this.goodsCategoryItemsList = res && res.rows
  413. })
  414. },
  415. //获取供应商
  416. getSupplierItems() {
  417. getSupplierList('', {name: ""}).then(res => {
  418. this.SupplierList = res && res.rows
  419. })
  420. },
  421. handleAdd() {
  422. this.createShow = true;
  423. },
  424. close() {
  425. this.createShow = false;
  426. this.getSupplierItems()
  427. },
  428. cancel() {
  429. this.camiloShow = false
  430. },
  431. getGoodsTagItems() {
  432. goodsTagItems({}).then(res => {
  433. this.goodsTagItemsList = res && res.data
  434. })
  435. },
  436. updateItem() {
  437. if (this.addData.multiSku == 1) {
  438. this.$refs.spec.getSkuList()
  439. } else {
  440. this.update()
  441. }
  442. },
  443. // 文件上传中处理
  444. handleFileUploadProgress(event, file, fileList) {
  445. this.upload.isUploading = true;
  446. },
  447. // 文件上传成功处理
  448. handleFileSuccess(response, file, fileList) {
  449. this.upload.isUploading = false;
  450. },
  451. // 超出限制时的提示
  452. exceedMax() {
  453. this.$message({
  454. message: '请移除已有文件后再进行上传',
  455. type: 'warning'
  456. })
  457. },
  458. //请求头
  459. getHttpHeader() {
  460. let timestamp = parseInt(new Date().getTime()),
  461. nonce = randomStr20();
  462. let sign = getSign(this.reqData || {}, timestamp)
  463. let url = process.env.VUE_APP_BASE_API + '/api/v1/mp/admin/deliver/order/batchShip' + '?sign=' + sign + '&nonce=' + nonce;
  464. this.upload.url = url
  465. let headers = {
  466. "Authorization": "Bearer " + getToken(),
  467. "x-zz-timestamp": timestamp
  468. }
  469. this.upload.headers = headers
  470. },
  471. // 自定义文件上传的实现
  472. reqUploadFile(param) {
  473. var data = this.reqData || {}
  474. var params = {
  475. file: param.file,
  476. ...data
  477. }
  478. // setBatchShip(params, this.headers).then(response => {
  479. // this.upload.isUploading = false;
  480. // this.$refs.upload.clearFiles();
  481. // if(response.data){
  482. // }
  483. // })
  484. },
  485. update(skuList) {
  486. this.$refs.addItem.validate((valid, items) => {
  487. if (valid) {
  488. this.addData.skuList = skuList
  489. const {value, categoryId, cost, exchangePrice, description, ...rest} = this.addData
  490. addGoods({
  491. ...rest, ...{
  492. value: accMul(value, 100),
  493. cost: cost == '' || cost == null ? '' : accMul(cost, 100),
  494. exchangePrice: accMul(exchangePrice, 1),
  495. description: encodeURI(description),
  496. categoryId: categoryId[1],
  497. }
  498. }).then(res => {
  499. if (res.code === 0) {
  500. this.$message({
  501. message: this.addData.goodsId ? '修改成功!' : '添加成功!',
  502. type: 'success'
  503. })
  504. this.$store.dispatch('tagsView/delView', this.$route)
  505. this.$router.go(-1)
  506. }
  507. })
  508. } else {
  509. if (items && Object.keys(items).length > 0) {
  510. this.$message({
  511. message: items[Object.keys(items)[0]][0].message,
  512. type: 'warning'
  513. })
  514. }
  515. }
  516. })
  517. }
  518. }
  519. }
  520. </script>
  521. <style lang="scss">
  522. .goods-add {
  523. .tip {
  524. font-size: 12px;
  525. color: #999;
  526. }
  527. .el-divider {
  528. .is-left {
  529. color: #409EFF;
  530. font-size: 20px;
  531. font-weight: bolder;
  532. left: 10px;
  533. }
  534. }
  535. }
  536. </style>