Goods.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. <template>
  2. <div>
  3. <div v-if="!shop_com" class="right-main clearfix">
  4. <div class="float_left h-goods-div">
  5. <el-input
  6. ref="barCodeInput"
  7. v-model="shop"
  8. :placeholder="'请输入' + goods_key_sel"
  9. clearable
  10. class="input-with-select"
  11. style="width: 88%; margin-left: 20px"
  12. @keyup.enter.native="searchGoods"
  13. >
  14. <el-select
  15. slot="prepend"
  16. v-model="goods_key_sel"
  17. style="width: 120px"
  18. placeholder="请选择"
  19. >
  20. <el-option label="条形码" value="商品条形码"></el-option>
  21. <el-option label="商品名称" value="商品名称"></el-option>
  22. </el-select>
  23. <!-- @click="pageChange(1)"-->
  24. <el-button
  25. slot="append"
  26. icon="el-icon-search"
  27. @click="searchGoods"
  28. ></el-button>
  29. </el-input>
  30. <ul v-if="allShop === true">
  31. <li
  32. v-for="(item, index) in shop_shop"
  33. :key="index"
  34. class="shop_info clearfix"
  35. @click="selGoods(item.id)"
  36. >
  37. <div class="float_left">
  38. <img :src="item.images[0]" alt="" />
  39. </div>
  40. <div class="float_left goods-info">
  41. <p>{{ item.title }}</p>
  42. <div>
  43. <span class="price-color" style="margin-right: 8px">
  44. ¥{{ item.minSalePrice }}
  45. </span>
  46. <span style="font-size: 12px; color: #999">
  47. 库存:{{ item.inventorTotal }}
  48. </span>
  49. </div>
  50. </div>
  51. </li>
  52. </ul>
  53. <FooterPage
  54. :page-size="pageSize"
  55. :total-page.sync="total"
  56. :current-page.sync="page"
  57. @pageChange="pageChange"
  58. @sizeChange="sizeChange"
  59. ></FooterPage>
  60. </div>
  61. <!-- 商品分类-->
  62. <div class="cate-div">
  63. <p
  64. class="cate-li"
  65. :class="[!cate_id ? 'cate-on' : '']"
  66. @click="changeCate()"
  67. >
  68. 全部
  69. </p>
  70. <p
  71. v-for="(item, index) in classify_list"
  72. :key="index"
  73. class="cate-li"
  74. :class="[cate_id === item.id ? 'cate-on' : '']"
  75. @click="changeCate(item)"
  76. >
  77. {{ item.title }}
  78. </p>
  79. </div>
  80. </div>
  81. <div v-else class="right-main">
  82. <div>
  83. <div class="head_back">
  84. <i class="el-icon-back"></i>
  85. <span style="margin-left: 6px" @click="goShop">返回</span>
  86. <span class="head_line"></span>
  87. <span class="head-back-tit">选择规格</span>
  88. </div>
  89. <div class="shop_info clearfix">
  90. <div class="float_left">
  91. <img :src="shop_all.images[0]" alt="" />
  92. </div>
  93. <div class="float_right goods-info">
  94. <p>
  95. {{ shop_all.title }}
  96. </p>
  97. <div v-if="now_sku_data.id">
  98. <span class="price-color" style="margin-right: 10px">
  99. ¥{{ now_sku_data.salePrice }}
  100. </span>
  101. <span style="font-size: 12px; color: #999">
  102. 库存:{{ now_sku_data.inventory }}
  103. </span>
  104. </div>
  105. <div v-else>
  106. <span class="price-color" style="margin-right: 10px">
  107. ¥{{ shop_all.minSalePrice }}
  108. </span>
  109. <span style="font-size: 12px; color: #999">
  110. 库存:{{ shop_all.inventorTotal }}
  111. </span>
  112. </div>
  113. </div>
  114. </div>
  115. <div style="color: #333333">
  116. <p style="margin-left: 10px">单位</p>
  117. <ul>
  118. <li
  119. v-for="(item, index) in shop_all.unitData"
  120. :key="index"
  121. class="shop_color"
  122. :class="
  123. parseInt(spec_id_group[1]) === parseInt(item.unitId)
  124. ? 'shop_color_li'
  125. : 'shop_color'
  126. "
  127. @click="bindPickerChange(item.unitId, 1)"
  128. >
  129. {{ item.unitName }}
  130. </li>
  131. </ul>
  132. </div>
  133. <div
  134. v-for="(item, index) in shop_all.specGroup"
  135. :key="index"
  136. style="color: #333333"
  137. >
  138. <p style="margin-left: 10px">
  139. {{ item.groupSpec.specName }}
  140. </p>
  141. <ul>
  142. <li
  143. v-for="(res, resIndex) in item.params"
  144. :key="resIndex"
  145. class="shop_color"
  146. :class="
  147. parseInt(spec_id_group[index + 2]) === parseInt(res.specValueId)
  148. ? 'shop_color_li'
  149. : 'shop_color'
  150. "
  151. @click="
  152. bindPickerChange(
  153. res.specValueId,
  154. index + 2,
  155. item.groupSpec.specId,
  156. res
  157. )
  158. "
  159. >
  160. {{ res.specValueName }}
  161. </li>
  162. </ul>
  163. </div>
  164. <div style="color: #333333">
  165. <p style="margin-left: 10px">
  166. {{
  167. ["KG", "kg"].includes(now_sku_data.unitName) ? "重量/kg" : "数量"
  168. }}
  169. </p>
  170. <el-popover v-model="keyboard_visible" placement="bottom">
  171. <keyboard :lb-num="false" @click="numFnThree"></keyboard>
  172. <div slot="reference" style="width: 200px">
  173. <el-input v-model="num2"></el-input>
  174. </div>
  175. </el-popover>
  176. </div>
  177. <div
  178. v-if="['KG', 'kg'].includes(now_sku_data.unitName)"
  179. style="color: #333333"
  180. >
  181. <p style="margin-left: 10px">皮重/kg</p>
  182. <el-input
  183. v-model="pack_weight"
  184. style="width: 200px"
  185. readonly
  186. ></el-input>
  187. </div>
  188. </div>
  189. <div style="text-align: right; padding-right: 40px">
  190. <div
  191. v-if="['KG', 'kg'].includes(now_sku_data.unitName)"
  192. style="display: inline-block; padding-right: 10px"
  193. >
  194. <el-button @click="clearPack">去皮</el-button>
  195. <el-button @click="plusPack">清皮</el-button>
  196. </div>
  197. <el-button type="primary" @click="addCart">确定</el-button>
  198. </div>
  199. </div>
  200. </div>
  201. </template>
  202. <script>
  203. import { getAllCategory, getGoodsByBarCode } from "@/api/goods";
  204. import Keyboard from "./Keyboard";
  205. import {
  206. addCartCashier,
  207. getCartByUser,
  208. getGoodsDetail,
  209. GoodsByCategory,
  210. updateBuyNumCashier,
  211. } from "@/api/Cashier";
  212. export default {
  213. name: "Goods",
  214. components: {
  215. Keyboard,
  216. },
  217. props: {
  218. shopCom: {
  219. type: Boolean,
  220. default: false,
  221. },
  222. allShop: {
  223. type: Boolean,
  224. default: false,
  225. },
  226. userCenterId: {
  227. type: [String, Number],
  228. default: 0,
  229. },
  230. numList: {
  231. type: Array,
  232. default: () => {
  233. return [];
  234. },
  235. },
  236. nowSelShop: {
  237. type: Object,
  238. default: () => {
  239. return {};
  240. },
  241. },
  242. },
  243. data() {
  244. return {
  245. shop: "",
  246. goods_key_sel: "商品条形码",
  247. shop_shop: [],
  248. total: 0,
  249. page: 1,
  250. pageSize: 10,
  251. goodsId: "",
  252. spec_id_group: [],
  253. shop_all: {
  254. images: [],
  255. },
  256. goodsBasicId: "",
  257. shopId: 1,
  258. now_sku_data: {},
  259. input_key_num: "",
  260. num2: "1",
  261. pack_weight: 0, // 商品皮重
  262. keyboard_visible: false, // 商品数量输入弹窗
  263. cate_id: "", // 当前已选择分类id
  264. add_cart_lodaing: false, // 加入购物车按钮加载中
  265. discount_list: [], // 优惠活动
  266. classify_list: [],
  267. shop_com: false,
  268. };
  269. },
  270. mounted() {
  271. this.shop_com = this.shopCom;
  272. // 获取焦点
  273. this.$nextTick(() => {
  274. this.$refs["barCodeInput"].focus();
  275. });
  276. this.getAllCategory();
  277. this.GoodsByCategory();
  278. },
  279. methods: {
  280. pageChange(val) {
  281. this.page = val;
  282. this.GoodsByCategory();
  283. },
  284. // 每页数据大小改变
  285. sizeChange(val) {
  286. this.pageSize = val;
  287. this.pageChange(1);
  288. },
  289. numFnThree(e, num) {
  290. if (!["x", "清除", "确定"].includes(num)) {
  291. this.numList.push(num);
  292. }
  293. if (num === "x") {
  294. this.num2 = this.num2.substring(0, this.num2.length - 1);
  295. } else if (num === "清除") {
  296. this.num2 = "";
  297. this.numList = [];
  298. } else if (num === "确定") {
  299. this.keyboard_visible = false;
  300. } else {
  301. this.num2 += num;
  302. }
  303. },
  304. // 去皮
  305. clearPack() {
  306. this.pack_weight = this.num2;
  307. this.num2 = 0;
  308. },
  309. // 清皮
  310. plusPack() {
  311. this.num2 = this.$NP.plus(this.num2, this.pack_weight);
  312. this.pack_weight = 0;
  313. },
  314. // 搜索商品
  315. searchGoods() {
  316. if (this.goods_key_sel === "商品条形码") {
  317. this.getGoodsByBarCode();
  318. } else {
  319. this.pageChange(1);
  320. }
  321. },
  322. // 根据条码获取商品
  323. async getGoodsByBarCode() {
  324. if (!this.shop) {
  325. this.$message.warning("请输入条形码");
  326. return;
  327. }
  328. const { data } = await getGoodsByBarCode({
  329. barCode: this.shop,
  330. userCenterId: this.userCenterId,
  331. });
  332. this.goodsId = data.goodsId;
  333. this.spec_id_group = data.index.split(":");
  334. this.shop_all = data.detail;
  335. this.goodsBasicId = data.detail.basicGoodsId;
  336. this.shopId = data.detail.shopId;
  337. this.now_sku_data = data.detail.specMultiple.find((item) => {
  338. return item.id === data.skuId;
  339. });
  340. // 选择商品后清除key
  341. this.shop = "";
  342. this.$refs["barCodeInput"].focus();
  343. if (["KG"].includes(this.now_sku_data.unitName)) {
  344. //打开输入弹窗
  345. this.$emit("openKeyboard", "-2");
  346. this.input_key_num = data.setNum || 1;
  347. this.$emit("inputKey", this.input_key_num);
  348. } else {
  349. this.num2 = data.setNum || 1;
  350. await this.addCart();
  351. }
  352. },
  353. // 切换分类
  354. changeCate(cate) {
  355. this.cate_id = cate ? cate.id : "";
  356. this.page = 1;
  357. this.GoodsByCategory();
  358. },
  359. // 商品列表
  360. async GoodsByCategory() {
  361. const data = await GoodsByCategory({
  362. page: this.page,
  363. pageSize: this.pageSize,
  364. categoryId: this.cate_id,
  365. keyword: this.shop,
  366. userCenterId: this.userCenterId,
  367. shopId: this.nowSelShop.id,
  368. });
  369. this.shop_shop = data.data;
  370. this.total = data.pageTotal;
  371. },
  372. // 选择商品
  373. selGoods(id) {
  374. // this.now_sku_data = {}
  375. this.goodsId = id;
  376. this.$emit("goodsId", this.goodsId);
  377. this.getGoodsDetail(id);
  378. },
  379. // 商品详情
  380. async getGoodsDetail(id) {
  381. // 选择商品后清除商品数量
  382. this.num2 = 1;
  383. const data = await getGoodsDetail(id, {
  384. userCenterId: this.userCenterId,
  385. });
  386. this.spec_id_group[0] = id;
  387. this.shop_all = data.data;
  388. this.goodsBasicId = data.data.basicGoodsId;
  389. this.shopId = data.data.shopId;
  390. if (["KG", "kg"].includes(this.shop_all.unitData.unitName)) {
  391. this.num2 = 0;
  392. }
  393. if (this.shop_all.specMultiple.length === 1) {
  394. this.num2 = 1;
  395. this.now_sku_data = this.shop_all.specMultiple[0];
  396. this.addCart();
  397. } else {
  398. this.shop_com = true;
  399. }
  400. },
  401. // 选择规格
  402. bindPickerChange(id, index, specId) {
  403. this.$set(this.spec_id_group, index, parseInt(id));
  404. // console.log(this.spec_id_group);
  405. if (this.spec_id_group.every((item) => !!item)) {
  406. const indexGroup = this.spec_id_group.join(":");
  407. // console.log(indexGroup);
  408. const nowSkuData = this.shop_all.specMultiple.find(
  409. (item) => item.index === indexGroup
  410. );
  411. if (nowSkuData) {
  412. this.now_sku_data = nowSkuData;
  413. }
  414. // console.log("now_sku_data:", this.now_sku_data);
  415. }
  416. },
  417. // 加入购物车
  418. async addCart() {
  419. if (!this.now_sku_data.id) {
  420. this.$message.warning("请选择规格");
  421. return;
  422. }
  423. if (!Number(this.num2) || Number(this.num2) <= 0) {
  424. this.$message.warning("请输入正确的商品数量");
  425. return;
  426. }
  427. const data = await addCartCashier({
  428. goodsData: [
  429. {
  430. skuId: this.now_sku_data.id,
  431. goodsId: this.goodsId,
  432. buyNum: this.num2,
  433. shopId: this.shopId,
  434. source: "4",
  435. goodsBasicId: this.goodsBasicId,
  436. },
  437. ],
  438. userCenterId: this.userCenterId,
  439. });
  440. this.$message.success("已选择");
  441. this.goShop();
  442. this.$emit("getCartByUser");
  443. },
  444. // 商品详情返回按钮
  445. goShop() {
  446. // 点击返回按钮重置数据
  447. this.now_sku_data = {};
  448. this.spec_id_group = [];
  449. this.shop_com = false;
  450. },
  451. // 获取分类列表
  452. async getAllCategory() {
  453. const { data } = await getAllCategory();
  454. if (JSON.stringify(data) === "{}") {
  455. this.classify_list = [];
  456. } else {
  457. this.classify_list = data;
  458. }
  459. },
  460. },
  461. };
  462. </script>
  463. <style scoped>
  464. .right-main {
  465. height: calc(99vh - 166px);
  466. overflow: auto;
  467. }
  468. .h-goods-div {
  469. width: 89.8%;
  470. height: 100%;
  471. overflow: auto;
  472. }
  473. .cate-div {
  474. float: right;
  475. overflow: auto;
  476. width: 10%;
  477. height: 100%;
  478. border-left: 1px solid #f2f2f2;
  479. text-align: center;
  480. color: #333333;
  481. }
  482. .shop_info {
  483. display: inline-block;
  484. width: 276px;
  485. border-radius: 4px;
  486. border: 1px solid #ededed;
  487. margin: 20px 10px 15px 10px;
  488. padding: 12px 12px 12px 10px;
  489. cursor: pointer;
  490. color: #333333;
  491. line-height: 18px;
  492. }
  493. .shop_info img {
  494. border: 1px solid #f4f4f4;
  495. border-radius: 4px;
  496. width: 68px;
  497. height: 68px;
  498. }
  499. .shop_info .goods-info {
  500. width: calc(100% - 80px);
  501. margin-left: 10px;
  502. }
  503. .goods-info > p {
  504. padding-bottom: 5px;
  505. color: #333333;
  506. height: 36px;
  507. overflow: hidden;
  508. text-overflow: ellipsis;
  509. display: -webkit-box;
  510. -webkit-box-orient: vertical;
  511. -webkit-line-clamp: 2;
  512. }
  513. .price-color {
  514. color: #f56c6c;
  515. }
  516. .cate-li {
  517. height: auto;
  518. line-height: 16px;
  519. padding: 16px 6px;
  520. cursor: pointer;
  521. /*background: rgba(32,83,212, 0.1);*/
  522. /*color: #409EFF;*/
  523. }
  524. .cate-on {
  525. background: rgb(236, 245, 255);
  526. color: #409eff;
  527. }
  528. .right-main {
  529. height: calc(99vh - 166px);
  530. overflow: auto;
  531. }
  532. .head_back {
  533. color: #ccc;
  534. font-size: 14px;
  535. cursor: pointer;
  536. height: 50px;
  537. line-height: 50px;
  538. padding-left: 20px;
  539. }
  540. .head_back .head-back-tit {
  541. color: #333333;
  542. }
  543. .head_back .head_line {
  544. height: 20px;
  545. width: 1px;
  546. background-color: #ededed;
  547. display: inline-block;
  548. margin: 4px 10px -6px 10px;
  549. }
  550. .shop_color {
  551. width: 148px;
  552. height: 48px;
  553. line-height: 48px;
  554. background: #f5f6fa;
  555. border: 1px solid #f5f6fa;
  556. border-radius: 4px;
  557. padding: 0 20px;
  558. text-align: center;
  559. margin: 0 14px 14px 0;
  560. cursor: pointer;
  561. display: inline-block;
  562. }
  563. .shop_color_li {
  564. background: rgb(236, 245, 255);
  565. color: #409eff;
  566. border: 1px solid #409eff;
  567. }
  568. </style>