shopList.vue 43 KB

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