shopList.vue 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  1. <template>
  2. <div class="m-container">
  3. <h2>
  4. <div class="squrt"></div>
  5. 商品列表
  6. </h2>
  7. <div class="m-core">
  8. <el-button
  9. class="btn-primary"
  10. @click="onShopOperation('create')"
  11. v-permission="'/shopOperation'"
  12. >添加</el-button
  13. >
  14. <el-upload
  15. v-permission="'import/goods'"
  16. style="display: inline-block; margin: 0 10px"
  17. action="/api-web/import/goods"
  18. :show-file-list="false"
  19. :before-upload="beforeUpload"
  20. accept=".xlsx,.xls"
  21. :headers="headers"
  22. :on-error="handleError"
  23. :on-success="handleSuccess"
  24. >
  25. <el-button class="btn-primary">商品导入</el-button>
  26. </el-upload>
  27. <!-- <el-upload v-permission="'export/goods'"
  28. style="display: inline-block; margin: 0 10px;"
  29. action="/api-web/export/goods"
  30. :show-file-list="false"
  31. :before-upload="beforeUpload"
  32. accept=".xlsx,.xls"
  33. :headers="headers"
  34. :on-error="handleError"
  35. :on-success="handleSuccess">
  36. <el-button class="btn-primary">商品导出</el-button>
  37. </el-upload> -->
  38. <el-button
  39. v-permission="'export/goods'"
  40. class="btn-primary"
  41. @click="exportShopList"
  42. >商品导出</el-button
  43. >
  44. <el-button
  45. class="btn-primary"
  46. @click="onDownload"
  47. v-permission="'import/downloadTemplate'"
  48. >下载模板</el-button
  49. >
  50. <el-button
  51. class="btn-primary"
  52. permission="'goods/update'"
  53. @click="onShopComAdd"
  54. >添加组合商品</el-button
  55. >
  56. <!-- 搜索类型 -->
  57. <save-form
  58. :inline="true"
  59. class="searchForm"
  60. ref="searchForm"
  61. @submit="onSearch"
  62. @reset="onReset"
  63. :model="searchForm"
  64. >
  65. <el-form-item prop="search">
  66. <el-input
  67. v-model.trim="searchForm.search"
  68. clearable
  69. placeholder="商品编号/货号/商品名称"
  70. ></el-input>
  71. </el-form-item>
  72. <el-form-item prop="type">
  73. <el-select
  74. v-model.trim="searchForm.type"
  75. clearable
  76. placeholder="商品类型"
  77. >
  78. <el-option
  79. v-for="(item, index) in goodsType"
  80. :key="index"
  81. :label="item.label"
  82. :value="item.value"
  83. ></el-option>
  84. </el-select>
  85. </el-form-item>
  86. <el-form-item prop="goodsCategoryId">
  87. <el-select
  88. v-model.trim="searchForm.goodsCategoryId"
  89. clearable
  90. placeholder="商品分类"
  91. >
  92. <el-option
  93. v-for="(item, index) in categoryList"
  94. :key="index"
  95. :label="item.label"
  96. :value="item.value"
  97. ></el-option>
  98. </el-select>
  99. </el-form-item>
  100. <el-form-item prop="status">
  101. <el-select
  102. v-model.trim="searchForm.status"
  103. clearable
  104. placeholder="是否是上架"
  105. >
  106. <el-option label="是" value="1"></el-option>
  107. <el-option label="否" value="0"></el-option>
  108. </el-select>
  109. </el-form-item>
  110. <el-form-item prop="groupGoods">
  111. <el-select
  112. v-model.trim="searchForm.groupGoods"
  113. clearable
  114. placeholder="是否是组合商品"
  115. >
  116. <el-option label="是" value="1"></el-option>
  117. <el-option label="否" value="0"></el-option>
  118. </el-select>
  119. </el-form-item>
  120. <el-form-item prop="clientShow">
  121. <el-select
  122. v-model.trim="searchForm.clientShow"
  123. clearable
  124. placeholder="学生端是否是展示"
  125. >
  126. <el-option label="是" value="1"></el-option>
  127. <el-option label="否" value="0"></el-option>
  128. </el-select>
  129. </el-form-item>
  130. <el-form-item prop="educationalShow">
  131. <el-select
  132. v-model.trim="searchForm.educationalShow"
  133. clearable
  134. placeholder="管理端是否是展示"
  135. >
  136. <el-option label="是" value="1"></el-option>
  137. <el-option label="否" value="0"></el-option>
  138. </el-select>
  139. </el-form-item>
  140. <el-form-item prop="musicGroupShow">
  141. <el-select
  142. v-model.trim="searchForm.musicGroupShow"
  143. clearable
  144. placeholder="乐团是否是展示"
  145. >
  146. <el-option label="是" value="1"></el-option>
  147. <el-option label="否" value="0"></el-option>
  148. </el-select>
  149. </el-form-item>
  150. <el-form-item prop="courseViewType">
  151. <el-select
  152. v-model.trim="searchForm.courseViewType"
  153. placeholder="乐团收费模式"
  154. clearable
  155. >
  156. <el-option label="课程收费" value="0"></el-option>
  157. <el-option label="系统收费" value="1"></el-option>
  158. <el-option label="云教练收费" value="2"></el-option>
  159. </el-select>
  160. </el-form-item>
  161. <el-form-item prop="replacementShow">
  162. <el-select
  163. v-model.trim="searchForm.replacementShow"
  164. clearable
  165. placeholder="是否参与置换"
  166. >
  167. <el-option label="是" value="1"></el-option>
  168. <el-option label="否" value="0"></el-option>
  169. </el-select>
  170. </el-form-item>
  171. <!-- <el-form-item>
  172. <el-date-picker v-model.trim="orderDate" style="width:410px;" type="daterange" value-format="yyyy-MM-dd"
  173. @change="searchOrderDate" range-separator="至" :picker-options="{ firstDayOfWeek: 1 }" start-placeholder="开始日期"
  174. end-placeholder="结束日期"></el-date-picker>
  175. </el-form-item> -->
  176. <el-form-item>
  177. <el-button type="danger" native-type="submit">搜索</el-button>
  178. <el-button type="primary" native-type="reset">重置</el-button>
  179. </el-form-item>
  180. </save-form>
  181. <!-- 列表 -->
  182. <div class="tableWrap">
  183. <el-table
  184. :data="tableList"
  185. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  186. >
  187. <el-table-column align="center" prop="id" label="商品编号">
  188. </el-table-column>
  189. <el-table-column align="center" prop="sn" label="货号">
  190. </el-table-column>
  191. <el-table-column align="center" prop="brand" label="品牌">
  192. </el-table-column>
  193. <el-table-column align="center" prop="name" label="商品名称">
  194. <template slot-scope="scope">
  195. <overflow-text :text="scope.row.name" width="100%" />
  196. </template>
  197. </el-table-column>
  198. <el-table-column align="center" label="是否组合商品">
  199. <template slot-scope="scope">
  200. {{ scope.row.complementGoodsIdList ? "是" : "否" }}
  201. </template>
  202. </el-table-column>
  203. <el-table-column align="center" label="学员是否展示">
  204. <template slot-scope="scope">
  205. {{ scope.row.clientShow ? "是" : "否" }}
  206. </template>
  207. </el-table-column>
  208. <el-table-column align="center" label="教务端是否展示">
  209. <template slot-scope="scope">
  210. {{ scope.row.educationalShow ? "是" : "否" }}
  211. </template>
  212. </el-table-column>
  213. <el-table-column align="center" label="乐团是否展示">
  214. <template slot-scope="scope">
  215. {{ scope.row.musicGroupShow ? "是" : "否" }}
  216. </template>
  217. </el-table-column>
  218. <el-table-column align="center" label="乐团收费模式">
  219. <template slot-scope="scope">
  220. <Tooltip :content="scope.row.courseViewType | courseViewTypeFormat" />
  221. </template>
  222. </el-table-column>
  223. <el-table-column align="center" label="是否库存预警">
  224. <template slot-scope="scope">
  225. <span v-if="!scope.row.complementGoodsIdList">
  226. {{ scope.row.stockWarning ? "是" : "否" }}
  227. </span>
  228. </template>
  229. </el-table-column>
  230. <el-table-column align="center" label="是否参与置换">
  231. <template slot-scope="scope">
  232. <span>
  233. {{ scope.row.replacementShow ? "是" : "否" }}
  234. </span>
  235. </template>
  236. </el-table-column>
  237. <el-table-column align="center" label="商品类型">
  238. <template slot-scope="scope">
  239. {{ scope.row.type | shopType }}
  240. </template>
  241. </el-table-column>
  242. <el-table-column
  243. align="center"
  244. prop="goodsCategoryName"
  245. label="商品分类"
  246. >
  247. </el-table-column>
  248. <el-table-column align="center" prop="specification" label="具体型号">
  249. <template slot-scope="scope">
  250. <span style="max-height: 64px; display: block">{{
  251. scope.row.specification
  252. }}</span>
  253. </template>
  254. </el-table-column>
  255. <el-table-column align="center" prop="stockCount" label="内部库存">
  256. <template slot-scope="scope">
  257. <!-- 先判断是否是组合商品 -->
  258. <span v-if="scope.row.complementGoodsIdList">
  259. {{ scope.row.stockCount ? scope.row.stockCount : "" }}
  260. </span>
  261. <span v-else>{{ scope.row.stockCount }}</span>
  262. </template>
  263. </el-table-column>
  264. <el-table-column align="center" prop="taxStockCount" label="税务库存">
  265. <template slot-scope="scope">
  266. <!-- 先判断是否是组合商品 -->
  267. <span v-if="scope.row.complementGoodsIdList">
  268. {{ scope.row.taxStockCount ? scope.row.taxStockCount : "" }}
  269. </span>
  270. <span v-else>{{ scope.row.taxStockCount }}</span>
  271. </template>
  272. </el-table-column>
  273. <el-table-column align="center" prop="stockType" label="库存类型">
  274. <template slot-scope="scope">
  275. {{ scope.row.stockType | stockTypeStatus }}
  276. </template>
  277. </el-table-column>
  278. <el-table-column align="center" prop="marketPrice" label="市场价(元)">
  279. <template slot-scope="scope">
  280. {{ scope.row.marketPrice | moneyFormat }}
  281. </template>
  282. </el-table-column>
  283. <el-table-column align="center" prop="marketPrice" label="零售价(元)">
  284. <template slot-scope="scope">
  285. {{ scope.row.discountPrice | moneyFormat }}
  286. </template>
  287. </el-table-column>
  288. <el-table-column
  289. align="center"
  290. prop="groupPurchasePrice"
  291. label="商品团购价(元)"
  292. >
  293. <template slot-scope="scope">
  294. {{ scope.row.groupPurchasePrice | moneyFormat }}
  295. </template>
  296. </el-table-column>
  297. <el-table-column
  298. align="center"
  299. cell-style="padding: 0"
  300. label="商品缩略图"
  301. >
  302. <template slot-scope="scope">
  303. <img class="shopImage" :src="scope.row.image" alt="" srcset="" />
  304. </template>
  305. </el-table-column>
  306. <el-table-column align="center" label="商品描述">
  307. <template slot-scope="scope">
  308. <Tooltip :content="scope.row.brief" />
  309. </template>
  310. </el-table-column>
  311. <el-table-column align="center" label="商品详情">
  312. <template slot-scope="scope">
  313. <Tooltip :content="scope.row.desc" />
  314. </template>
  315. </el-table-column>
  316. <el-table-column
  317. align="center"
  318. width="180px"
  319. label="操作"
  320. fixed="right"
  321. >
  322. <template slot-scope="scope">
  323. <!-- 组合商品没有进货清单按钮 v-permission="'/purchaseLlist'" -->
  324. <el-button
  325. v-if="
  326. !scope.row.complementGoodsIdList &&
  327. permission('/purchaseLlist')
  328. "
  329. @click="onPurchaseList(scope.row)"
  330. type="text"
  331. >进货清单</el-button
  332. >
  333. <!-- <el-popconfirm title="你是否上架该商品?"
  334. @confirm="onUpdate(scope.row)"
  335. v-if="scope.row.status == 0"
  336. v-permission="'goods/updateGoodsStatus'">
  337. <el-button slot="reference"
  338. type="text">上架</el-button>
  339. </el-popconfirm> -->
  340. <!-- v-permission="'goods/updateGoodsStatus'" -->
  341. <el-button
  342. v-if="
  343. scope.row.status == 0 && permission('goods/updateGoodsStatus')
  344. "
  345. @click="onUpdate(scope.row, 0)"
  346. type="text"
  347. >上架</el-button
  348. >
  349. <el-button
  350. v-if="
  351. scope.row.status == 1 && permission('goods/updateGoodsStatus')
  352. "
  353. @click="onUpdate(scope.row, 1)"
  354. type="text"
  355. >下架</el-button
  356. >
  357. <!-- <el-popconfirm title="你是否下架该商品?"
  358. @confirm="onUpdate(scope.row)"
  359. v-if="scope.row.status == 1"
  360. v-permission="'goods/updateGoodsStatus'">
  361. <el-button slot="reference"
  362. type="text">下架</el-button>
  363. </el-popconfirm> -->
  364. <!-- {{ scope.row.status }} -->
  365. <!-- v-permission="scope.row.complementGoodsIdList ? 'goods/update' : '/shopOperation'" -->
  366. <el-button
  367. v-if="
  368. scope.row.status == 0 &&
  369. (scope.row.complementGoodsIdList
  370. ? 'goods/update'
  371. : '/shopOperation')
  372. "
  373. @click="onShopOperation('update', scope.row)"
  374. type="text"
  375. >修改</el-button
  376. >
  377. <el-button
  378. v-if="
  379. scope.row.status == 1 &&
  380. permission(
  381. scope.row.complementGoodsIdList
  382. ? 'goods/update'
  383. : '/shopOperation'
  384. )
  385. "
  386. @click="onShopOperation('look', scope.row)"
  387. type="text"
  388. >查看</el-button
  389. >
  390. <!-- <el-button v-if="scope.row.status == 0"
  391. v-permission="'goods/del'"
  392. @click="onDelete(scope.row)"
  393. type="text">删除</el-button> -->
  394. </template>
  395. </el-table-column>
  396. </el-table>
  397. <pagination
  398. sync
  399. :total.sync="pageInfo.total"
  400. :page.sync="pageInfo.page"
  401. :limit.sync="pageInfo.limit"
  402. :page-sizes="pageInfo.page_size"
  403. @pagination="getList"
  404. />
  405. </div>
  406. </div>
  407. <el-dialog
  408. :title="addString[addType] + '组合商品'"
  409. destroy-on-close
  410. :visible.sync="routeShopStatus"
  411. @close="onFormClose('ruleForm')"
  412. width="600px"
  413. >
  414. <el-form :model="form" :rules="rules" ref="ruleForm">
  415. <el-form-item
  416. label="商品名称"
  417. prop="name"
  418. :label-width="formLabelWidth"
  419. >
  420. <el-input
  421. placeholder="请输入商品名称"
  422. type="text"
  423. :disabled="addDisabled"
  424. v-model.trim="form.name"
  425. ></el-input>
  426. </el-form-item>
  427. <el-form-item label="货号" prop="sn" :label-width="formLabelWidth">
  428. <el-input
  429. placeholder="请输入货号"
  430. type="text"
  431. :disabled="addDisabled"
  432. v-model.trim="form.sn"
  433. ></el-input>
  434. </el-form-item>
  435. <el-form-item label="品牌" prop="brand" :label-width="formLabelWidth">
  436. <el-input
  437. v-model.trim="form.brand"
  438. :disabled="addDisabled"
  439. placeholder="请输入品牌"
  440. ></el-input>
  441. </el-form-item>
  442. <el-form-item
  443. label="商品类型"
  444. prop="type"
  445. :label-width="formLabelWidth"
  446. >
  447. <el-select
  448. v-model.trim="form.type"
  449. :disabled="addDisabled"
  450. style="width: 100% !important"
  451. placeholder="请选择商品类型"
  452. >
  453. <el-option
  454. v-for="(item, index) in goodsType"
  455. :key="index"
  456. :label="item.label"
  457. :value="item.value"
  458. ></el-option>
  459. </el-select>
  460. </el-form-item>
  461. <el-form-item
  462. label="商品分类"
  463. prop="goodsCategoryId"
  464. :label-width="formLabelWidth"
  465. >
  466. <el-select
  467. v-model.trim="form.goodsCategoryId"
  468. style="width: 100% !important"
  469. placeholder="请选择商品分类"
  470. :disabled="addDisabled"
  471. filterable
  472. >
  473. <el-option
  474. v-for="item in categoryList"
  475. :key="item.value"
  476. :label="item.label"
  477. :value="item.value"
  478. >
  479. </el-option>
  480. </el-select>
  481. </el-form-item>
  482. <el-form-item
  483. label="商品型号"
  484. prop="specification"
  485. :label-width="formLabelWidth"
  486. >
  487. <el-input
  488. v-model.trim="form.specification"
  489. :disabled="addDisabled"
  490. placeholder="请输入商品型号"
  491. ></el-input>
  492. </el-form-item>
  493. <div v-for="(goodsList, index) in form.goodsList" :key="index">
  494. <el-form-item
  495. :label="'商品' + (index + 1)"
  496. :label-width="formLabelWidth"
  497. style="display: inline-block; width: 80% !important"
  498. :prop="'goodsList.' + index + '.id'"
  499. :rules="[
  500. { required: true, message: '请选择商品', trigger: 'change' },
  501. ]"
  502. >
  503. <el-select
  504. v-model.trim="goodsList.id"
  505. @change="onGoodsChange"
  506. filterable
  507. style=" width: 100% !important"
  508. :disabled="addDisabled"
  509. placeholder="请选择商品"
  510. >
  511. <el-option
  512. v-for="(item, index) in selectGoodsList"
  513. :key="index"
  514. :disabled="item.disabled"
  515. :label="item.name"
  516. :value="item.id"
  517. ></el-option>
  518. </el-select>
  519. </el-form-item>
  520. <div v-if="!addDisabled" style="display: inline-block">
  521. <el-button
  522. icon="el-icon-minus"
  523. v-if="form.goodsList.length > 1"
  524. @click.prevent="removeGoodsList(goodsList)"
  525. circle
  526. ></el-button>
  527. <el-button
  528. icon="el-icon-plus"
  529. @click.prevent="addGoodsList"
  530. circle
  531. style="margin-left: 5px"
  532. ></el-button>
  533. </div>
  534. </div>
  535. <el-form-item
  536. label="市场价"
  537. prop="marketPrice"
  538. :label-width="formLabelWidth"
  539. >
  540. <el-input
  541. type="number"
  542. placeholder="请输入市场价"
  543. :disabled="addDisabled"
  544. @mousewheel.native.prevent
  545. v-model.trim="form.marketPrice"
  546. ></el-input>
  547. </el-form-item>
  548. <el-form-item
  549. label="零售价"
  550. prop="discountPrice"
  551. :label-width="formLabelWidth"
  552. >
  553. <el-input
  554. type="number"
  555. placeholder="请输入零售价"
  556. :disabled="addDisabled"
  557. @mousewheel.native.prevent
  558. v-model.trim="form.discountPrice"
  559. ></el-input>
  560. </el-form-item>
  561. <el-form-item
  562. label="商品团购价"
  563. prop="groupPurchasePrice"
  564. :label-width="formLabelWidth"
  565. >
  566. <el-input
  567. type="number"
  568. placeholder="请输入商品团购价"
  569. :disabled="addDisabled"
  570. @mousewheel.native.prevent
  571. v-model.trim="form.groupPurchasePrice"
  572. ></el-input>
  573. </el-form-item>
  574. <el-form-item
  575. label="学员是否展示"
  576. prop="clientShow"
  577. :label-width="formLabelWidth"
  578. >
  579. <el-select v-model="form.clientShow" style="width: 100% !important" :disabled="addDisabled" placeholder="请选择学员是否展示">
  580. <el-option label="是" :value="1"></el-option>
  581. <el-option label="否" :value="0"></el-option>
  582. </el-select>
  583. </el-form-item>
  584. <el-form-item
  585. label="教务端是否展示"
  586. prop="educationalShow"
  587. :label-width="formLabelWidth"
  588. >
  589. <el-select
  590. v-model="form.educationalShow"
  591. style="width: 100% !important"
  592. :disabled="addDisabled"
  593. placeholder="请选择教务端是否展示"
  594. >
  595. <el-option label="是" :value="1"></el-option>
  596. <el-option label="否" :value="0"></el-option>
  597. </el-select>
  598. </el-form-item>
  599. <el-form-item
  600. label="乐团是否展示"
  601. prop="musicGroupShow"
  602. :label-width="formLabelWidth"
  603. >
  604. <el-select
  605. v-model="form.musicGroupShow"
  606. style="width: 100% !important"
  607. :disabled="addDisabled"
  608. placeholder="请选择乐团是否展示"
  609. >
  610. <el-option label="是" :value="1"></el-option>
  611. <el-option label="否" :value="0"></el-option>
  612. </el-select>
  613. </el-form-item>
  614. <el-form-item label="乐团收费模式" :label-width="formLabelWidth" prop="courseViewType">
  615. <select-all v-model.trim="form.courseViewType"
  616. filterable
  617. placeholder="请选择乐团收费模式"
  618. multiple
  619. :disabled="addDisabled || (form.musicGroupShow != 0 && form.musicGroupShow != 1)"
  620. clearable>
  621. <el-option label="课程收费" value="0"></el-option>
  622. <el-option label="系统收费" value="1"></el-option>
  623. <el-option label="云教练收费" value="2"></el-option>
  624. </select-all>
  625. <!-- <el-select
  626. v-model="form.courseViewType"
  627. multiple
  628. placeholder="请选择乐团收费模式"
  629. :disabled="addDisabled"
  630. >
  631. <el-option label="课程收费" :value="0"></el-option>
  632. <el-option label="系统收费" :value="1"></el-option>
  633. <el-option label="云教练收费" :value="2"></el-option>
  634. </el-select> -->
  635. </el-form-item>
  636. <el-form-item
  637. label="是否参与置换"
  638. prop="replacementShow"
  639. :label-width="formLabelWidth"
  640. >
  641. <el-select v-model="form.replacementShow" style="width: 100% !important" :disabled="addDisabled" placeholder="是否参与置换">
  642. <el-option label="是" :value="1"></el-option>
  643. <el-option label="否" :value="0"></el-option>
  644. </el-select>
  645. </el-form-item>
  646. <el-form-item
  647. label="商品图片"
  648. prop="image"
  649. :label-width="formLabelWidth"
  650. >
  651. <upload
  652. v-model="form.image"
  653. :imageWidthM="400"
  654. :disabled="addDisabled"
  655. :imageHeightM="400"
  656. ></upload>
  657. </el-form-item>
  658. <el-form-item
  659. label="商品描述"
  660. prop="brief"
  661. :label-width="formLabelWidth"
  662. >
  663. <el-input
  664. type="textarea"
  665. :disabled="addDisabled"
  666. v-model.trim="form.brief"
  667. ></el-input>
  668. </el-form-item>
  669. <el-form-item
  670. label="商品详情"
  671. prop="desc"
  672. :label-width="formLabelWidth"
  673. >
  674. <el-input
  675. type="textarea"
  676. :disabled="addDisabled"
  677. v-model.trim="form.desc"
  678. ></el-input>
  679. </el-form-item>
  680. </el-form>
  681. <span slot="footer" v-if="!addDisabled" class="dialog-footer">
  682. <el-button @click="routeShopStatus = false">取 消</el-button>
  683. <el-button @click="onShopSubmit('ruleForm')" type="primary"
  684. >确 定</el-button
  685. >
  686. </span>
  687. </el-dialog>
  688. </div>
  689. </template>
  690. <script>
  691. import pagination from "@/components/Pagination/index";
  692. import Upload from "@/components/Upload/index";
  693. import {
  694. categoryListTree,
  695. goodsQuery,
  696. goodsAdd,
  697. goodsUpdate,
  698. goodsDelete,
  699. updateGoodsStatus,
  700. } from "@/api/businessManager";
  701. import qs from "qs";
  702. import cleanDeep from "clean-deep";
  703. import store from "@/store";
  704. import Tooltip from "@/components/Tooltip/index";
  705. import { Export } from "@/utils/downLoadFile";
  706. import { getToken } from "@/utils/auth";
  707. import { goodsType } from "@/utils/searchArray";
  708. import load from "@/utils/loading";
  709. import { permission } from "@/utils/directivePage";
  710. import courseEvaluateVue from '@/views/teamDetail/componentCourse/courseEvaluate.vue';
  711. let validPrice = (rule, value, callback) => {
  712. if ((value == "" && typeof value == "string") || value == null) {
  713. callback(new Error("请输入金额"));
  714. } else if (value < 0) {
  715. callback(new Error("输入金额必须大于或等于0"));
  716. } else if (value >= 100000) {
  717. callback(new Error("输入金额必须小于100000"));
  718. } else {
  719. callback();
  720. }
  721. };
  722. let validStock = (rule, value, callback) => {
  723. if ((value == "" && typeof value == "string") || value == null) {
  724. callback(new Error("请输入库存"));
  725. } else if (value < 0) {
  726. callback(new Error("库存数量必须大于或等于0"));
  727. } else {
  728. callback();
  729. }
  730. };
  731. export default {
  732. components: {
  733. pagination,
  734. Tooltip,
  735. Upload,
  736. },
  737. name: "shopList",
  738. data() {
  739. return {
  740. goodsType: goodsType,
  741. categoryList: [],
  742. goodsLoading: false,
  743. organId: null,
  744. orderDate: null,
  745. searchForm: {
  746. search: null,
  747. groupGoods: null,
  748. type: null,
  749. status: null,
  750. goodsCategoryId: null,
  751. startTime: null,
  752. endTime: null,
  753. status: null,
  754. clientShow: null,
  755. educationalShow: null,
  756. musicGroupShow: null,
  757. courseViewType: null,
  758. replacementShow: null,
  759. },
  760. headers: {
  761. Authorization: getToken(),
  762. },
  763. searchLsit: [],
  764. tableList: [],
  765. pageInfo: {
  766. // 分页规则
  767. limit: 10, // 限制显示条数
  768. page: 1, // 当前页
  769. total: 0, // 总条数
  770. page_size: [10, 20, 40, 50], // 选择限制显示条数
  771. },
  772. formLabelWidth: "120px",
  773. routeShopStatus: false,
  774. addType: "create",
  775. addString: {
  776. create: "添加",
  777. update: "修改",
  778. look: "查看",
  779. },
  780. addDisabled: false,
  781. form: {
  782. sn: null,
  783. brand: null,
  784. supplyChannel: null,
  785. name: null,
  786. type: null,
  787. goodsCategoryId: null,
  788. specification: null,
  789. marketPrice: null,
  790. discountPrice: null,
  791. groupPurchasePrice: null,
  792. clientShow: null,
  793. educationalShow: null,
  794. musicGroupShow: null,
  795. courseViewType: [],
  796. stockWarning: null,
  797. image: null,
  798. complementGoodsIdList: null,
  799. goodsList: [
  800. {
  801. id: null,
  802. },
  803. ],
  804. brief: null,
  805. desc: null,
  806. replacementShow: null,
  807. },
  808. goodsTree: [], // 选择商品列表
  809. rules: {
  810. sn: [
  811. {
  812. required: true,
  813. message: "请输入商品货号",
  814. trigger: "blur",
  815. },
  816. ],
  817. brand: [
  818. {
  819. required: true,
  820. message: "请输入品牌",
  821. trigger: "blur",
  822. },
  823. {
  824. min: 2,
  825. max: 30,
  826. message: "长度在 2 到 30 个字符",
  827. trigger: "blur",
  828. },
  829. ],
  830. supplyChannel: [
  831. {
  832. required: true,
  833. message: "请输入备查货号",
  834. trigger: "blur",
  835. },
  836. ],
  837. name: [
  838. {
  839. required: true,
  840. message: "请输入商品名称",
  841. trigger: "blur",
  842. },
  843. {
  844. min: 2,
  845. max: 30,
  846. message: "长度在 2 到 30 个字符",
  847. trigger: "blur",
  848. },
  849. ],
  850. type: [
  851. {
  852. required: true,
  853. message: "请选择商品分类",
  854. trigger: "change",
  855. },
  856. ],
  857. goodsCategoryId: [
  858. {
  859. required: true,
  860. message: "请选择商品类型",
  861. trigger: "change",
  862. },
  863. ],
  864. specification: [
  865. {
  866. required: true,
  867. message: "请输入商品型号",
  868. trigger: "blur",
  869. },
  870. {
  871. min: 2,
  872. max: 30,
  873. message: "长度在 2 到 30 个字符",
  874. trigger: "blur",
  875. },
  876. ],
  877. marketPrice: [
  878. {
  879. required: true,
  880. validator: validPrice,
  881. trigger: "blur",
  882. },
  883. ],
  884. discountPrice: [
  885. {
  886. required: true,
  887. validator: validPrice,
  888. trigger: "blur",
  889. },
  890. ],
  891. groupPurchasePrice: [
  892. {
  893. required: true,
  894. validator: validPrice,
  895. trigger: "blur",
  896. },
  897. ],
  898. clientShow: [
  899. {
  900. required: true,
  901. message: "请选择学员是否展示",
  902. trigger: "change",
  903. },
  904. ],
  905. educationalShow: [
  906. {
  907. required: true,
  908. message: "请选择教务端是否展示",
  909. trigger: "change",
  910. },
  911. ],
  912. musicGroupShow: [
  913. {
  914. required: true,
  915. message: "请选择乐团是否展示",
  916. trigger: "change",
  917. },
  918. ],
  919. courseViewType: [
  920. { required: true, message: "请选乐团收费模式", trigger: 'change' },
  921. ],
  922. replacementShow: [
  923. {
  924. required: true,
  925. message: "请选择是否参与置换",
  926. trigger: "change",
  927. },
  928. ],
  929. stockWarning: [
  930. {
  931. required: true,
  932. message: "请选择是否库存预警",
  933. trigger: "change",
  934. },
  935. ],
  936. image: [
  937. {
  938. required: true,
  939. message: "请选择图片",
  940. trigger: "blur",
  941. },
  942. ],
  943. brief: [
  944. {
  945. required: true,
  946. message: "请输入商品描述",
  947. trigger: "blur",
  948. },
  949. ],
  950. desc: [
  951. {
  952. required: true,
  953. message: "请输入商品详情",
  954. trigger: "blur",
  955. },
  956. ],
  957. },
  958. selectGoodsList: [],
  959. };
  960. },
  961. mounted() {
  962. this.init();
  963. },
  964. methods: {
  965. permission(str) {
  966. return permission(str);
  967. },
  968. init() {
  969. this.getList();
  970. this.getCategory();
  971. },
  972. getCategory() {
  973. let params = {
  974. delFlag: 0,
  975. rows: 9999,
  976. };
  977. categoryListTree(params).then((res) => {
  978. let result = res.data;
  979. if (res.code == 200) {
  980. let tempArray = [];
  981. result.rows.forEach((row) => {
  982. tempArray.push({
  983. label: row.name,
  984. value: row.id,
  985. });
  986. });
  987. this.categoryList = tempArray;
  988. }
  989. });
  990. },
  991. async onUpdate(row, type) {
  992. let title = type == 1 ? "你是否下架该商品?" : "你是否上架该商品?";
  993. this.$confirm(title, "提示", {
  994. confirmButtonText: "确定",
  995. cancelButtonText: "取消",
  996. type: "warning",
  997. })
  998. .then(async () => {
  999. await updateGoodsStatus({
  1000. goodsId: row.id,
  1001. status: row.status ? 0 : 1,
  1002. }).then((res) => {
  1003. this.messageTips(row.status ? "下架" : "上架", res);
  1004. });
  1005. })
  1006. .catch(() => {});
  1007. },
  1008. onPurchaseList(row) {
  1009. this.$router.push({
  1010. path: "/shopManager/purchaseLlist",
  1011. query: {
  1012. name: row.name,
  1013. goodsId: row.id,
  1014. },
  1015. });
  1016. },
  1017. onDelete(row) {
  1018. this.$confirm("您确定删除该商品吗?", "提示", {
  1019. confirmButtonText: "确定",
  1020. cancelButtonText: "取消",
  1021. type: "warning",
  1022. })
  1023. .then(() => {
  1024. goodsDelete(row.id).then((res) => {
  1025. this.messageTips("删除", res);
  1026. });
  1027. })
  1028. .catch(() => {});
  1029. },
  1030. searchOrderDate(value) {
  1031. if (value) {
  1032. this.searchForm.startTime = value[0];
  1033. this.searchForm.endTime = value[1];
  1034. } else {
  1035. this.searchForm.startTime = null;
  1036. this.searchForm.endTime = null;
  1037. }
  1038. },
  1039. messageTips(title, res) {
  1040. if (res.code == 200) {
  1041. this.$message.success(title + "成功");
  1042. this.typeStatus = false;
  1043. this.getList();
  1044. } else {
  1045. this.$message.error(res.msg);
  1046. }
  1047. },
  1048. getList() {
  1049. let params = Object.assign({}, this.searchForm);
  1050. params.organId = this.organId;
  1051. params.rows = this.pageInfo.limit;
  1052. params.page = this.pageInfo.page;
  1053. goodsQuery(params).then((res) => {
  1054. if (res.code == 200 && res.data) {
  1055. this.tableList = res.data.rows;
  1056. this.pageInfo.total = res.data.total;
  1057. }
  1058. });
  1059. },
  1060. getAllGoodsList() {
  1061. // 获取所有商品
  1062. goodsQuery({
  1063. rows: 9999,
  1064. page: 1,
  1065. groupGoods: 0,
  1066. status: 1,
  1067. }).then((res) => {
  1068. if (res.code == 200 && res.data) {
  1069. this.selectGoodsList = res.data.rows;
  1070. }
  1071. });
  1072. },
  1073. onSearch() {
  1074. this.pageInfo.page = 1;
  1075. this.getList();
  1076. },
  1077. onReset() {
  1078. // 重置
  1079. this.$refs.searchForm.resetFields();
  1080. this.getList();
  1081. },
  1082. onShopComAdd() {
  1083. this.form = {
  1084. sn: null,
  1085. brand: null,
  1086. supplyChannel: null,
  1087. name: null,
  1088. type: null,
  1089. goodsCategoryId: null,
  1090. specification: null,
  1091. marketPrice: null,
  1092. discountPrice: null,
  1093. groupPurchasePrice: null,
  1094. clientShow: null,
  1095. educationalShow: null,
  1096. musicGroupShow: null,
  1097. courseViewType: [],
  1098. stockWarning: null,
  1099. image: null,
  1100. complementGoodsIdList: null,
  1101. goodsList: [
  1102. {
  1103. id: null,
  1104. },
  1105. ],
  1106. brief: null,
  1107. desc: null,
  1108. replacementShow: null,
  1109. };
  1110. this.onValidGoodsStatus();
  1111. this.routeShopStatus = true;
  1112. this.addType = "create";
  1113. this.addDisabled = false;
  1114. if (this.$refs["ruleForm"]) {
  1115. this.$refs["ruleForm"].resetFields();
  1116. }
  1117. // 获取所有商品
  1118. this.getAllGoodsList();
  1119. },
  1120. onValidGoodsStatus() {
  1121. // 更新商品选择状态
  1122. let goodsList = this.form.goodsList;
  1123. let tempIds = [];
  1124. goodsList.forEach((item) => {
  1125. tempIds.push(item.id);
  1126. });
  1127. this.selectGoodsList.forEach((item) => {
  1128. item.disabled = false;
  1129. if (tempIds.includes(item.id)) {
  1130. item.disabled = true;
  1131. }
  1132. });
  1133. },
  1134. onShopOperation(type, row) {
  1135. // 添加或修改
  1136. let params = {
  1137. type: type,
  1138. };
  1139. if (row) {
  1140. params.id = row.id;
  1141. }
  1142. let paramInfo = JSON.stringify(params);
  1143. this.addType = type;
  1144. this.addDisabled = type == "look" ? true : false;
  1145. // 判断是否是修改组合商品
  1146. if ((type == "update" || type == "look") && row.complementGoodsIdList) {
  1147. this.routeShopStatus = true;
  1148. let form = this.form;
  1149. for (let i in form) {
  1150. form[i] = row[i];
  1151. }
  1152. let ids = row.complementGoodsIdList.split(",");
  1153. let goodsList = [];
  1154. ids.forEach((item) => {
  1155. goodsList.push({
  1156. id: Number(item),
  1157. });
  1158. });
  1159. form.goodsList = goodsList;
  1160. form.id = row.id;
  1161. if(row.courseViewType) {
  1162. form.courseViewType = row.courseViewType.split(',')
  1163. }
  1164. this.onValidGoodsStatus();
  1165. this.getAllGoodsList();
  1166. } else {
  1167. let pageTitle = "添加";
  1168. if (type == "update") {
  1169. pageTitle = "修改";
  1170. } else if (type == "look") {
  1171. pageTitle = "查看";
  1172. }
  1173. this.$router.push(
  1174. {
  1175. path: "/shopManager/shopOperation",
  1176. query: {
  1177. paramInfo,
  1178. },
  1179. },
  1180. (route) => {
  1181. route.meta.title = pageTitle + "商品";
  1182. }
  1183. );
  1184. }
  1185. },
  1186. beforeUpload(file) {
  1187. // console.log(file.type)
  1188. // const isJPG = file.type === '.xlsx' || file.type === '.xls';
  1189. // // const isLt2M = file.size / 1024 / 1024 < 2;
  1190. // if (!isJPG) {
  1191. // this.$message.error('上传头像图片只能是 JPG 格式!');
  1192. // }
  1193. // return isJPG;
  1194. // this.goodsLoading = true
  1195. load.startLoading();
  1196. },
  1197. handleSuccess(response, file, fileList) {
  1198. // 导入商品
  1199. // 报表导出
  1200. load.endLoading();
  1201. if (response.code == 200) {
  1202. this.$message.success("导入成功");
  1203. this.getList();
  1204. } else {
  1205. this.$message.error(response.msg);
  1206. }
  1207. },
  1208. handleError(err, file, fileList) {
  1209. load.endLoading();
  1210. console.log(err, file, fileList);
  1211. },
  1212. onDownload() {
  1213. // 下载模板
  1214. // // 报表导出
  1215. Export(this, {
  1216. url: "/api-web/import/downloadTemplate",
  1217. params: {
  1218. templateType: "GOODS",
  1219. },
  1220. fileName: "商品导入模板.xls",
  1221. });
  1222. },
  1223. exportShopList() {
  1224. Export(
  1225. this,
  1226. {
  1227. url: "/api-web/export/goods",
  1228. params: qs.stringify(cleanDeep(this.searchForm)),
  1229. fileName: "商品导出.xls",
  1230. method: "post",
  1231. },
  1232. "确定导出商品"
  1233. );
  1234. },
  1235. onFormClose(formName) {
  1236. // 关闭弹窗重置验证
  1237. this.$refs[formName].resetFields();
  1238. },
  1239. onGoodsChange() {
  1240. let selectGoodsList = this.selectGoodsList;
  1241. let goodsList = this.form.goodsList;
  1242. let tempIds = [];
  1243. goodsList.forEach((item) => {
  1244. if (item.id) {
  1245. tempIds.push(item.id);
  1246. }
  1247. });
  1248. selectGoodsList.forEach((item) => {
  1249. if (tempIds.includes(item.id)) {
  1250. item.disabled = true;
  1251. } else {
  1252. item.disabled = false;
  1253. }
  1254. });
  1255. this.calcPrice();
  1256. },
  1257. removeGoodsList(item) {
  1258. let tempId = item.id;
  1259. let selectGoodsList = this.selectGoodsList;
  1260. selectGoodsList.forEach((item) => {
  1261. if (item.id == tempId) {
  1262. item.disabled = false;
  1263. }
  1264. });
  1265. const index = this.form.goodsList.indexOf(item);
  1266. if (index !== -1) {
  1267. this.form.goodsList.splice(index, 1);
  1268. }
  1269. this.calcPrice();
  1270. },
  1271. addGoodsList() {
  1272. this.form.goodsList.push({
  1273. id: null,
  1274. });
  1275. },
  1276. onShopSubmit(formName) {
  1277. this.$refs[formName].validate((valid) => {
  1278. if (valid) {
  1279. let form = Object.assign({}, this.form);
  1280. let tempIds = [];
  1281. form.goodsList.forEach((item) => {
  1282. if (item.id) {
  1283. tempIds.push(item.id);
  1284. }
  1285. });
  1286. form.complementGoodsIdList = tempIds.join(",");
  1287. form.courseViewType = form.courseViewType.join(',')
  1288. form.goodsList = null;
  1289. if (this.addType == "create") {
  1290. if (this.form.id) {
  1291. // 判断有没有Id,如果有则删除
  1292. delete this.form.id;
  1293. }
  1294. form.status = "NO"; // 默认上架
  1295. goodsAdd(cleanDeep(form)).then((res) => {
  1296. this.messageTips("添加", res);
  1297. });
  1298. } else if (this.addType == "update") {
  1299. goodsUpdate(cleanDeep(form)).then((res) => {
  1300. this.messageTips("修改", res);
  1301. });
  1302. }
  1303. } else {
  1304. this.$nextTick(() => {
  1305. let isError = document.getElementsByClassName("is-error");
  1306. isError[0].scrollIntoView({
  1307. block: "center",
  1308. behavior: "smooth",
  1309. });
  1310. });
  1311. return false;
  1312. }
  1313. });
  1314. },
  1315. messageTips(title, res) {
  1316. if (res.code == 200) {
  1317. this.$message.success(title + "成功");
  1318. this.getList();
  1319. this.routeShopStatus = false;
  1320. } else {
  1321. this.$message.error(res.msg);
  1322. }
  1323. },
  1324. calcPrice() {
  1325. let selectGoodsList = this.selectGoodsList;
  1326. let form = this.form;
  1327. let goodsList = form.goodsList;
  1328. let tempIds = [];
  1329. goodsList.forEach((item) => {
  1330. if (item.id) {
  1331. tempIds.push(item.id);
  1332. }
  1333. });
  1334. let groupPurchasePrice = 0,
  1335. marketPrice = 0,
  1336. discountPrice = 0;
  1337. selectGoodsList.forEach((item) => {
  1338. if (tempIds.includes(item.id)) {
  1339. groupPurchasePrice += item.groupPurchasePrice;
  1340. marketPrice += item.marketPrice;
  1341. discountPrice += item.discountPrice;
  1342. }
  1343. });
  1344. form.groupPurchasePrice = Number(groupPurchasePrice.toFixed(2));
  1345. form.discountPrice = Number(discountPrice.toFixed(2));
  1346. form.marketPrice = Number(marketPrice.toFixed(2));
  1347. },
  1348. },
  1349. filters: {
  1350. courseViewTypeFormat(value) {
  1351. let template = ['课程收费', '系统收费', '云教练收费']
  1352. if(!value) {
  1353. return ''
  1354. }
  1355. let ids = value.split(',')
  1356. let str = []
  1357. ids.forEach(item => {
  1358. str.push(template[item])
  1359. })
  1360. return str.join(',')
  1361. }
  1362. }
  1363. };
  1364. </script>
  1365. <style lang="scss">
  1366. .shopImage {
  1367. width: 60px;
  1368. height: 60px;
  1369. }
  1370. .shopDesc {
  1371. max-height: 70px;
  1372. overflow: hidden;
  1373. }
  1374. .el-select__tags .el-tag.el-tag--info.el-tag--small.el-tag--light {
  1375. max-width: 95px;
  1376. }
  1377. </style>