index.vue 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. <template>
  2. <div class="app-container">
  3. <!-- 查询 -->
  4. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  5. <el-form-item prop="goodsName">
  6. <el-input v-model="queryParams.goodsName" placeholder="请输入商品名称" clearable @keyup.enter.native="handleQuery" />
  7. </el-form-item>
  8. <el-form-item prop="brandId">
  9. <el-select v-model="queryParams.brandId" placeholder="请选择商品分类" clearable>
  10. <el-option v-for="brand in brandList" :key="brand.id" :label="brand.brandName" :value="brand.id" />
  11. </el-select>
  12. </el-form-item>
  13. <el-form-item prop="goodsCategoryId">
  14. <el-select v-model="queryParams.goodsCategoryId" placeholder="请选择商品分类" clearable>
  15. <el-option v-for="category in categoryList" :key="category.id" :label="category.categoryName" :value="category.id" />
  16. </el-select>
  17. </el-form-item>
  18. <el-form-item prop="goodsCode">
  19. <el-input v-model="queryParams.goodsCode" placeholder="请输入商品编号" clearable @keyup.enter.native="handleQuery" />
  20. </el-form-item>
  21. <el-form-item>
  22. <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
  23. <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
  24. </el-form-item>
  25. </el-form>
  26. <el-row :gutter="10" class="mb8">
  27. <el-col :span="1.5">
  28. <el-button type="primary" plain icon="el-icon-plus" @click="handleAdd" v-hasPermi="['goods:commonGoods:add']" v-if="userInfoVO.userType == '00'">新增</el-button>
  29. </el-col>
  30. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  31. </el-row>
  32. <!-- 列表 -->
  33. <Page uri="/mapi/core/goods/list" :request-params="queryParams" ref="pagination">
  34. <el-table-column label="ID" align="center" prop="id" />
  35. <el-table-column label="商品编号" align="center" prop="goodsCode" />
  36. <el-table-column label="商品名称" align="center" prop="goodsName" />
  37. <el-table-column label="图片" align="center" prop="goodsImg" width="100">
  38. <template slot-scope="scope">
  39. <el-image style="width: 80px; height: 80px" :src="scope.row.goodsImg" :preview-src-list="[scope.row.goodsImg]"> </el-image>
  40. </template>
  41. </el-table-column>
  42. <el-table-column label="品牌" align="center" prop="brandName" />
  43. <el-table-column label="商品分类" align="center" prop="goodsCategoryId">
  44. <template slot-scope="scope">
  45. <span v-if="scope.row.goodsCategoryId == item.id" v-for="item in categoryList" :key="item.id"> {{ item.categoryName }}</span>
  46. </template>
  47. </el-table-column>
  48. <el-table-column label="促销标识" align="center" prop="isSell">
  49. <template slot-scope="scope">
  50. <el-tag v-if="scope.row.isSell == dict.value" v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code"> {{ dict.label }}</el-tag>
  51. </template>
  52. </el-table-column>
  53. <el-table-column label="规格数量" align="center" prop="goodsItemNum">
  54. <template slot-scope="scope">
  55. <el-button type="text" @click="handleSkuUpdate(scope.row)">{{ scope.row.goodsItemNum }}种规格</el-button>
  56. </template>
  57. </el-table-column>
  58. <el-table-column label="余额支付" align="center" prop="isBalancePay">
  59. <template slot-scope="scope">
  60. <el-tag v-if="scope.row.isBalancePay == dict.value" v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code"> {{ dict.label }}</el-tag>
  61. </template>
  62. </el-table-column>
  63. <!-- <el-table-column label="金额(元)" align="center" prop="cashMoney" />-->
  64. <el-table-column label="排序值" align="center" prop="sort" />
  65. <el-table-column label="启用状态" align="center" prop="status">
  66. <template slot-scope="scope">
  67. <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
  68. </template>
  69. </el-table-column>
  70. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  71. <template slot-scope="scope">
  72. <el-button type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['goods:commonGoods:edit']" v-if="userInfoVO.userType == '00'">修改</el-button>
  73. <el-button type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['goods:commonGoods:remove']" v-if="userInfoVO.userType == '00'">删除</el-button>
  74. <el-button type="text" icon="el-icon-s-shop" @click="handleSkuUpdate(scope.row)" v-hasPermi="['goods:commonGoods:list']">查看规格</el-button>
  75. <el-button type="text" icon="el-icon-view" v-if="goodsType != 1" @click="gotoComment(scope.row)">查看评论</el-button>
  76. </template>
  77. </el-table-column>
  78. </Page>
  79. <!-- 分页 -->
  80. <!-- 添加或修改商品管理对话框 -->
  81. <el-dialog :title="title" :visible.sync="open" width="70%" append-to-body>
  82. <el-form ref="form" :model="form" :rules="rules" label-width="120px">
  83. <el-tabs v-model="activeTab">
  84. <!-- 基本信息 tab -->
  85. <el-tab-pane label="基本信息" name="basic">
  86. <el-row :gutter="15">
  87. <el-col :span="12">
  88. <el-form-item label="商品名称" prop="goodsName">
  89. <el-input v-model="form.goodsName" placeholder="请输入商品名称" />
  90. </el-form-item>
  91. </el-col>
  92. <el-col :span="12">
  93. <el-form-item label="商品编码" prop="goodsCode">
  94. <el-input v-model="form.goodsCode" placeholder="请输入商品编码" />
  95. </el-form-item>
  96. </el-col>
  97. </el-row>
  98. <el-row :gutter="15">
  99. <el-col :span="12">
  100. <el-form-item label="品牌" prop="brandId">
  101. <el-select v-model="form.brandId" placeholder="请选择品牌" clearable>
  102. <el-option v-for="brand in brandList" :key="brand.id" :label="brand.brandName" :value="brand.id" />
  103. </el-select>
  104. </el-form-item>
  105. </el-col>
  106. <el-col :span="12">
  107. <el-form-item label="商品分类" prop="goodsCategoryId">
  108. <el-select v-model="form.goodsCategoryId" placeholder="请选择商品分类" clearable>
  109. <el-option v-for="category in categoryList" :key="category.id" :label="category.categoryName" :value="category.id" />
  110. </el-select>
  111. </el-form-item>
  112. </el-col>
  113. </el-row>
  114. <el-form-item label="商品图片" prop="goodsImg">
  115. <image-upload v-model="form.goodsImg" />
  116. </el-form-item>
  117. <el-form-item label="商品图片集" prop="goodsImgs">
  118. <image-upload v-model="form.goodsImgs" :limit="limit" />
  119. </el-form-item>
  120. <el-form-item label="商品简介" prop="goodsSynopsis">
  121. <editor v-model="form.goodsSynopsis" :min-height="192" />
  122. </el-form-item>
  123. </el-tab-pane>
  124. <!-- 规格设置 tab -->
  125. <el-tab-pane label="规格设置" name="sku">
  126. <el-form-item label="规格类型">
  127. <el-radio-group v-model="form.skuType" @change="handleSkuTypeChange">
  128. <el-radio :label="0">单规格</el-radio>
  129. <el-radio :label="1">多规格</el-radio>
  130. </el-radio-group>
  131. </el-form-item>
  132. <!-- 单规格设置 -->
  133. <template v-if="form.skuType === 0">
  134. <el-form-item label="销售价格" prop="singleSkuPrice">
  135. <el-input-number v-model="form.singleSkuPrice" :precision="2" :step="0.1" :min="0" />
  136. </el-form-item>
  137. <el-form-item label="批发价格" prop="singleSkuWholesalePrice">
  138. <el-input-number v-model="form.singleSkuWholesalePrice" :precision="2" :step="0.1" :min="0" />
  139. </el-form-item>
  140. <el-form-item label="进货价格" prop="singleSkuPurchasePrice">
  141. <el-input-number v-model="form.singleSkuPurchasePrice" :precision="2" :step="0.1" :min="0" />
  142. </el-form-item>
  143. <el-form-item label="库存数量" prop="singleSkuStock">
  144. <el-input-number v-model="form.singleSkuStock" :min="0" :step="1" />
  145. </el-form-item>
  146. </template>
  147. <!-- 多规格设置 -->
  148. <template v-if="form.skuType === 1">
  149. <!-- 规格项设置 -->
  150. <div class="spec-group" v-for="(spec, index) in form.specList" :key="index">
  151. <el-row :gutter="10">
  152. <el-col :span="8">
  153. <el-form-item :label="'规格项' + (index + 1)">
  154. <el-input v-model="spec.name" placeholder="如: 颜色、尺码" />
  155. </el-form-item>
  156. </el-col>
  157. <el-col :span="14">
  158. <el-form-item label="规格值">
  159. <el-tag
  160. :key="tag"
  161. v-for="tag in spec.specValues"
  162. closable
  163. :disable-transitions="false"
  164. @close="handleRemoveSpecValue(spec.specValues, tag)">
  165. {{tag}}
  166. </el-tag>
  167. <el-input
  168. class="input-new-tag"
  169. v-if="spec.inputVisible"
  170. v-model="spec.inputValue"
  171. :ref="'saveTagInput' + index"
  172. size="small"
  173. @keyup.enter.native="handleInputConfirm(spec, index)"
  174. @blur="handleInputConfirm(spec, index)">
  175. </el-input>
  176. <el-button v-else class="button-new-tag" size="small" @click="showInput(spec, index)">
  177. + 添加规格值
  178. </el-button>
  179. </el-form-item>
  180. </el-col>
  181. <el-col :span="2">
  182. <el-button type="text" @click="removeSpec(index)" icon="el-icon-delete">删除</el-button>
  183. </el-col>
  184. </el-row>
  185. </div>
  186. <el-button type="primary" plain @click="addSpec">添加规格项</el-button>
  187. <!-- 规格组合列表 -->
  188. <el-table :data="form.skuList" border style="margin-top: 20px">
  189. <el-table-column
  190. v-for="(spec, index) in form.specList"
  191. :key="index"
  192. :label="spec.name"
  193. align="center">
  194. <template slot-scope="scope">
  195. {{scope.row.specValLists[index]}}
  196. </template>
  197. </el-table-column>
  198. <el-table-column label="销售价格" align="center" width="150">
  199. <template slot-scope="scope">
  200. <el-input-number
  201. v-model="scope.row.salePrice"
  202. :precision="2"
  203. :step="0.1"
  204. :min="0"
  205. controls-position="right"
  206. size="mini" />
  207. </template>
  208. </el-table-column>
  209. <el-table-column label="批发价格" align="center" width="150">
  210. <template slot-scope="scope">
  211. <el-input-number
  212. v-model="scope.row.wholesalePrice"
  213. :precision="2"
  214. :step="0.1"
  215. :min="0"
  216. controls-position="right"
  217. size="mini" />
  218. </template>
  219. </el-table-column>
  220. <el-table-column label="进货价格" align="center" width="150">
  221. <template slot-scope="scope">
  222. <el-input-number
  223. v-model="scope.row.purchasePrice"
  224. :precision="2"
  225. :step="0.1"
  226. :min="0"
  227. controls-position="right"
  228. size="mini" />
  229. </template>
  230. </el-table-column>
  231. <el-table-column label="库存" align="center" width="150">
  232. <template slot-scope="scope">
  233. <el-input-number
  234. v-model="scope.row.stock"
  235. :min="0"
  236. :step="1"
  237. controls-position="right"
  238. size="mini" />
  239. </template>
  240. </el-table-column>
  241. </el-table>
  242. </template>
  243. </el-tab-pane>
  244. <!-- 其他设置 tab -->
  245. <el-tab-pane label="其他设置" name="other">
  246. <el-form-item label="促销标识" prop="isSell">
  247. <el-radio-group v-model="form.isSell">
  248. <el-radio-button v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code">
  249. {{dict.label}}
  250. </el-radio-button>
  251. </el-radio-group>
  252. </el-form-item>
  253. <el-form-item label="余额支付" prop="isBalancePay">
  254. <el-radio-group v-model="form.isBalancePay">
  255. <el-radio-button v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code">
  256. {{dict.label}}
  257. </el-radio-button>
  258. </el-radio-group>
  259. </el-form-item>
  260. <el-form-item label="显示顺序" prop="sort">
  261. <el-input-number v-model="form.sort" :min="0" :step="1" />
  262. </el-form-item>
  263. </el-tab-pane>
  264. </el-tabs>
  265. </el-form>
  266. <div slot="footer" class="dialog-footer">
  267. <el-button type="primary" @click="submitForm">确 定</el-button>
  268. <el-button @click="cancel">取 消</el-button>
  269. </div>
  270. </el-dialog>
  271. </div>
  272. </template>
  273. <script>
  274. import { listGoods, getGoods, delGoods, addGoods, updateGoods, updateGoodsStatus } from '@/api/core/goods'
  275. import { listCategory } from '@/api/core/category'
  276. import { listBrand } from '@/api/core/brand'
  277. import { status } from 'nprogress'
  278. export default {
  279. name: 'appGoods',
  280. dicts: ['goods_type', 'sys_yes_no'],
  281. data() {
  282. return {
  283. userInfoVO: null,
  284. uploadAction: `${process.env.VUE_APP_BASE_API}` + '/common/uploadOSS',
  285. imgsList: [],
  286. fileSize: 3,
  287. // 遮罩层
  288. loading: true,
  289. // 选中数组
  290. ids: [],
  291. // 非单个禁用
  292. single: true,
  293. // 非多个禁用
  294. multiple: true,
  295. // 显示搜索条件
  296. showSearch: true,
  297. // 总条数
  298. total: 0,
  299. // 商品管理表格数据
  300. goodsList: [],
  301. // 弹出层标题
  302. title: '',
  303. // 是否显示弹出层
  304. open: false,
  305. // 查询参数
  306. queryParams: {
  307. goodsName: null,
  308. goodsType: null,
  309. status: null,
  310. goodsCategoryId: null,
  311. goodsCode: null
  312. },
  313. queryParams2: {
  314. pageNum: 1,
  315. pageSize: 9999,
  316. status: '0',
  317. goodsType: null
  318. },
  319. // 表单参数
  320. form: {
  321. id: null,
  322. goodsName: null,
  323. goodsCategoryId: null,
  324. goodsSynopsis: null,
  325. brandId: null,
  326. goodsImg: null,
  327. goodsImgs: [],
  328. goodsCode: null,
  329. isSell: 'N',
  330. isCashPay: 'Y',
  331. cashMoney: null,
  332. isBalancePay: 'Y',
  333. createBy: null,
  334. createById: null,
  335. createTime: null,
  336. updateBy: null,
  337. updateById: null,
  338. updateTime: null,
  339. remark: null,
  340. skuType: 0,
  341. status: '0',
  342. specList: [],
  343. skuList: [],
  344. sort: '0',
  345. singleSkuPrice: 0,
  346. singleSkuWholesalePrice: 0,
  347. singleSkuPurchasePrice: 0,
  348. singleSkuStock: 0
  349. },
  350. // 表单校验
  351. rules: {
  352. goodsName: [
  353. {
  354. required: true,
  355. message: '商品名称不能为空',
  356. trigger: 'blur'
  357. }
  358. ],
  359. brandId: [
  360. {
  361. required: true,
  362. message: '品牌不能为空',
  363. trigger: 'blur'
  364. }
  365. ],
  366. goodsCategoryId: [
  367. {
  368. required: true,
  369. message: '商品分类不能为空',
  370. trigger: 'blur'
  371. }
  372. ],
  373. goodsCode: [
  374. {
  375. required: true,
  376. message: '商品编号不能为空',
  377. trigger: 'blur'
  378. }
  379. ],
  380. goodsSynopsis: [
  381. {
  382. required: true,
  383. message: '商品简介不能为空',
  384. trigger: 'blur'
  385. }
  386. ],
  387. goodsImg: [
  388. {
  389. required: true,
  390. message: '商品头图不能为空',
  391. trigger: 'blur'
  392. }
  393. ],
  394. goodsImgs: [
  395. {
  396. required: true,
  397. message: '商品图片集不能为空',
  398. trigger: 'blur'
  399. }
  400. ],
  401. isBalancePay: [
  402. {
  403. required: true,
  404. message: '是否余额支付不能为空',
  405. trigger: 'blur'
  406. }
  407. ],
  408. isCashPay: [
  409. {
  410. required: true,
  411. message: '是否现金支付不能为空',
  412. trigger: 'blur'
  413. }
  414. ],
  415. isSell: [
  416. {
  417. required: true,
  418. message: '是否促销不能为空',
  419. trigger: 'blur'
  420. }
  421. ],
  422. cashMoney: [
  423. {
  424. required: true,
  425. message: '现金金额不能为空',
  426. trigger: 'blur'
  427. }
  428. ]
  429. },
  430. categoryList: {},
  431. brandList: {},
  432. goodsType: '',
  433. limit: 9,
  434. activeTab: 'basic',
  435. skuType: 0
  436. }
  437. },
  438. created() {
  439. this.handleUser()
  440. this.goodsType = this.getUrlParam('goodsType')
  441. this.form.goodsType = this.goodsType
  442. this.getList()
  443. this.getCategoryList()
  444. this.getBrandList()
  445. },
  446. methods: {
  447. handleUser() {
  448. this.userInfoVO = this.getUserInfo()
  449. },
  450. getBrandList() {
  451. listBrand({ ...this.queryParams2, ...{ goodsType: this.goodsType } }).then((response1) => {
  452. this.brandList = response1.rows
  453. })
  454. },
  455. getCategoryList() {
  456. listCategory({ ...this.queryParams2, ...{ goodsType: this.goodsType } }).then((response2) => {
  457. this.categoryList = response2.rows
  458. })
  459. },
  460. /** 查询商品管理列表 */
  461. getList() {
  462. this.queryParams.goodsType = this.goodsType
  463. this.$nextTick(() => {
  464. this.$refs.pagination.handleSearch(true)
  465. })
  466. },
  467. // 取消按钮
  468. cancel() {
  469. this.open = false
  470. this.reset()
  471. },
  472. // 表单重置
  473. reset() {
  474. this.form = {
  475. id: null,
  476. goodsType: this.goodsType,
  477. goodsName: null,
  478. goodsCategoryId: null,
  479. goodsSynopsis: null,
  480. brandId: null,
  481. goodsImg: null,
  482. goodsImgs: [],
  483. goodsCode: null,
  484. isSell: 'N',
  485. skuType: 0,
  486. isCashPay: 'Y',
  487. cashMoney: null,
  488. isBalancePay: 'Y',
  489. createBy: null,
  490. createById: null,
  491. createTime: null,
  492. updateBy: null,
  493. updateById: null,
  494. updateTime: null,
  495. remark: null,
  496. status: '0',
  497. sort: '0',
  498. specList: [],
  499. skuList: [],
  500. singleSkuPrice: 0,
  501. singleSkuWholesalePrice: 0,
  502. singleSkuPurchasePrice: 0,
  503. singleSkuStock: 0
  504. }
  505. this.resetForm('form')
  506. },
  507. /** 搜索按钮操作 */
  508. handleQuery() {
  509. this.getList()
  510. },
  511. /** 重置按钮操作 */
  512. resetQuery() {
  513. this.resetForm('queryForm')
  514. this.handleQuery()
  515. },
  516. // 多选框选中数据
  517. handleSelectionChange(selection) {
  518. this.ids = selection.map((item) => item.id)
  519. this.single = selection.length !== 1
  520. this.multiple = !selection.length
  521. },
  522. /** 新增按钮操作 */
  523. handleAdd() {
  524. this.reset()
  525. this.open = true
  526. this.title = '添加商品管理'
  527. },
  528. /** 修改按钮操作 */
  529. handleUpdate(row) {
  530. this.reset()
  531. this.imgsList = []
  532. const id = row.id || this.ids
  533. getGoods(id).then((response) => {
  534. this.form = response.data
  535. if (this.form.goodsImgs != null && this.form.goodsImgs != '') {
  536. this.form.goodsImgs.split(',').forEach((item) => {
  537. const vo = {
  538. name: '',
  539. url: item
  540. }
  541. this.imgsList.push(vo)
  542. })
  543. }
  544. this.open = true
  545. this.title = '修改商品管理'
  546. })
  547. },
  548. /** 提交按钮 */
  549. submitForm() {
  550. this.$refs['form'].validate(valid => {
  551. if (valid) {
  552. const formData = { ...this.form }
  553. // 处理SKU数据
  554. if (this.form.skuType === 0) {
  555. formData.skuList = [{
  556. specValLists: [],
  557. salePrice: this.form.singleSkuPrice,
  558. wholesalePrice: this.form.singleSkuWholesalePrice,
  559. purchasePrice: this.form.singleSkuPurchasePrice,
  560. stock: this.form.singleSkuStock
  561. }]
  562. } else {
  563. formData.skuList = this.form.skuList
  564. }
  565. // 提交数据
  566. if (formData.id) {
  567. updateGoods(formData).then(response => {
  568. this.$modal.msgSuccess('修改成功')
  569. this.open = false
  570. this.getList()
  571. })
  572. } else {
  573. addGoods(formData).then(response => {
  574. this.$modal.msgSuccess('新增成功')
  575. this.open = false
  576. this.getList()
  577. })
  578. }
  579. }
  580. })
  581. },
  582. /** 删除按钮操作 */
  583. handleDelete(row) {
  584. const ids = row.id || this.ids
  585. this.$modal
  586. .confirm('是否确认删除商品管理编号为"' + ids + '"的数据项?')
  587. .then(function () {
  588. return delGoods(ids)
  589. })
  590. .then(() => {
  591. this.getList()
  592. this.$modal.msgSuccess('删除成功')
  593. })
  594. .catch(() => {})
  595. },
  596. /** 导出按钮操作 */
  597. handleExport() {
  598. this.download(
  599. 'commonGoods/commonGoods/export',
  600. {
  601. ...this.queryParams
  602. },
  603. `goods_${new Date().getTime()}.xlsx`
  604. )
  605. },
  606. checkClose(done) {
  607. this.$confirm('是否关闭表单,关闭后数据将丢失?')
  608. .then(function () {
  609. done()
  610. })
  611. .then(() => {})
  612. .catch(() => {})
  613. },
  614. handleStatusChange(row) {
  615. let text = row.status === '0' ? '启用' : '停用'
  616. this.$confirm('确认要' + text + '吗?')
  617. .then(function () {
  618. return updateGoodsStatus(row.id, row.status)
  619. })
  620. .then(() => {
  621. this.$modal.msgSuccess(text + '成功')
  622. })
  623. .catch(function () {
  624. row.status = row.status === '0' ? '1' : '0'
  625. })
  626. },
  627. /** 设置物料 */
  628. handleSkuUpdate(row) {
  629. this.$tab.openPage(row.goodsName + '的物料', '/goods/setSku/' + row.id)
  630. },
  631. handleRemove(file, fileList) {
  632. console.log(fileList)
  633. this.imgsList = []
  634. fileList.forEach((item) => {
  635. const vo = {
  636. name: item.name,
  637. url: item.url
  638. }
  639. this.imgsList.push(vo)
  640. console.log(fileList)
  641. })
  642. },
  643. // 上传前校检格式和大小
  644. handleBeforeUpload(file) {
  645. // 校检文件大小
  646. if (this.fileSize) {
  647. const isLt = file.size / 1024 / 1024 < this.fileSize
  648. if (!isLt) {
  649. this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
  650. return false
  651. }
  652. }
  653. return true
  654. },
  655. handleUploadSuccessByImg(res, file) {
  656. // 获取富文本组件实例
  657. let quill = this.Quill
  658. // 如果上传成功
  659. if (res.code == 200) {
  660. // 获取光标所在位置
  661. this.form.goodsImg = res.data.src
  662. this.$forceUpdate()
  663. } else {
  664. this.$message.error('图片插入失败')
  665. }
  666. },
  667. handleUploadSuccessByImgs(res, file, fileList) {
  668. // 获取富文本组件实例
  669. let quill = this.Quill
  670. // 如果上传成功
  671. if (res.code == 200) {
  672. const vo = {
  673. name: '',
  674. url: res.data.src
  675. }
  676. this.imgsList.push(vo)
  677. this.$forceUpdate()
  678. } else {
  679. this.$message.error('图片插入失败')
  680. }
  681. },
  682. handleUploadError() {
  683. this.$message.error('图片插入失败')
  684. },
  685. handleExceed() {
  686. //提示最多只能上传9个
  687. this.$message.error('最多上传9个图片!')
  688. },
  689. gotoComment(row) {
  690. this.$router.push({ path: `/platform/goodsComment/appGoodsComment?goodsType=${this.goodsType}&goodsId=${row.id}` })
  691. },
  692. handleSkuTypeChange(val) {
  693. if (val === 0) {
  694. this.form.specList = []
  695. this.form.skuList = []
  696. } else {
  697. // 如果已有规格数据,重新生成组合
  698. if (this.form.specList.length > 0) {
  699. this.generateSkuList()
  700. }
  701. }
  702. },
  703. addSpec() {
  704. if (!this.form.specList) {
  705. this.form.specList = []
  706. }
  707. this.form.specList.push({
  708. name: '',
  709. specValues: [],
  710. inputVisible: false,
  711. inputValue: ''
  712. })
  713. },
  714. removeSpec(index) {
  715. this.form.specList.splice(index, 1)
  716. this.$nextTick(() => {
  717. this.generateSkuList()
  718. })
  719. },
  720. handleRemoveSpecValue(values, tag) {
  721. values.splice(values.indexOf(tag), 1)
  722. this.$nextTick(() => {
  723. this.generateSkuList()
  724. })
  725. },
  726. showInput(spec, index) {
  727. spec.inputVisible = true
  728. this.$nextTick(_ => {
  729. this.$refs['saveTagInput' + index][0].$refs.input.focus()
  730. })
  731. },
  732. handleInputConfirm(spec, index) {
  733. let inputValue = spec.inputValue
  734. if (inputValue && spec.specValues.indexOf(inputValue) === -1) {
  735. if (!spec.specValues) {
  736. spec.specValues = []
  737. }
  738. spec.specValues.push(inputValue)
  739. this.$nextTick(() => {
  740. this.generateSkuList()
  741. })
  742. }
  743. spec.inputVisible = false
  744. spec.inputValue = ''
  745. },
  746. generateSkuList() {
  747. const specs = this.form.specList
  748. if (specs.length === 0 || specs.some(spec => spec.specValues.length === 0)) {
  749. this.form.skuList = []
  750. return
  751. }
  752. // 获取所有规格值的组合
  753. const values = specs.map(spec => spec.specValues)
  754. const combinations = this.cartesianProduct(values)
  755. // 保存现有的价格和库存数据
  756. const existingSkus = this.form.skuList || []
  757. // 生成新的SKU列表,保留已存在的价格和库存
  758. this.form.skuList = combinations.map(specs => {
  759. // 查找是否存在相同规格的旧数据
  760. const existingSku = existingSkus.find(old =>
  761. JSON.stringify(old.specValLists) === JSON.stringify(specs)
  762. )
  763. return {
  764. specValLists: specs,
  765. salePrice: existingSku ? existingSku.salePrice : 0,
  766. wholesalePrice: existingSku ? existingSku.wholesalePrice : 0,
  767. purchasePrice: existingSku ? existingSku.purchasePrice : 0,
  768. stock: existingSku ? existingSku.stock : 0
  769. }
  770. })
  771. },
  772. cartesianProduct(arrays) {
  773. return arrays.reduce((a, b) => {
  774. return a.map(x => {
  775. return b.map(y => {
  776. return Array.isArray(x) ? [...x, y] : [x, y]
  777. })
  778. }).flat()
  779. }, [[]])
  780. },
  781. /**
  782. * @description 添加规格值
  783. * @param {number} index 规格索引
  784. */
  785. addSpecValue(index) {
  786. // 确保规格值数组已初始化
  787. if (!this.form.specList[index].specValueList) {
  788. this.$set(this.form.specList[index], 'specValueList', [])
  789. }
  790. this.form.specList[index].specValueList.push({
  791. specValue: '',
  792. image: ''
  793. })
  794. }
  795. }
  796. }
  797. </script>
  798. <style lang="scss" scoped>
  799. .spec-group {
  800. padding: 10px;
  801. border: 1px solid #EBEEF5;
  802. margin-bottom: 10px;
  803. }
  804. .el-tag + .el-tag {
  805. margin-left: 10px;
  806. }
  807. .button-new-tag {
  808. margin-left: 10px;
  809. height: 32px;
  810. line-height: 30px;
  811. padding-top: 0;
  812. padding-bottom: 0;
  813. }
  814. .input-new-tag {
  815. width: 90px;
  816. margin-left: 10px;
  817. vertical-align: bottom;
  818. }
  819. </style>