product.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. <template>
  2. <!-- #ifdef H5 -->
  3. <zj-page-layout :hasFooter="true">
  4. <template slot="header">
  5. <view class="search-container">
  6. <u-search
  7. shape="round"
  8. :showAction="false"
  9. placeholder="输入分类名称进行搜索"
  10. v-model="keyword"
  11. @search="searchData"
  12. @clear="searchData"
  13. >
  14. </u-search>
  15. </view>
  16. </template>
  17. <view class="main-container">
  18. <view class="left-list" v-if="type == 'M'">
  19. <block v-for="(item, index) in leftList" :key="index">
  20. <view
  21. class="item ellipsis"
  22. :class="leftCurrent == item.categoryId ? 'current' : ''"
  23. @tap="changeLeft(item.categoryId)"
  24. >{{ item.categoryName }}</view
  25. >
  26. </block>
  27. </view>
  28. <view class="right-list">
  29. <scroll-view scroll-y style="height: 100%">
  30. <view class="item" v-for="(item, index) in rightList" :key="index">
  31. <view class="name">{{ item.goodsName }}</view>
  32. <view class="text">代码:{{ item.goodsCode }}</view>
  33. <view class="bottom">
  34. <view class="price"
  35. >¥{{ item.goodsAmount | priceFilter }}<text>/{{ item.goodsUnit }}</text></view
  36. >
  37. <u-number-box
  38. min="0"
  39. :step="item.goodsUnit == '米' ? 1 : 1"
  40. :name="item.goodsId"
  41. v-model="item.num"
  42. @change="changeNum"
  43. >
  44. <view slot="minus" class="ctrl">
  45. <u-icon name="minus" color="#FFFFFF" size="12"></u-icon>
  46. </view>
  47. <text slot="input" class="input">
  48. <u--input
  49. :type="item.goodsUnit == '米' ? 'digit' : 'number'"
  50. placeholder="0"
  51. inputAlign="center"
  52. border="none"
  53. v-model="item.num"
  54. @blur="changeNum({ name: item.goodsId, value: item.num, unit: item.goodsUnit })"
  55. ></u--input>
  56. </text>
  57. <view slot="plus" class="ctrl">
  58. <u-icon name="plus" color="#FFFFFF" size="12"></u-icon>
  59. </view>
  60. </u-number-box>
  61. </view>
  62. </view>
  63. <Loading :type="2" :loadStatus="loadStatus" :dataList="rightList" v-if="type == 'M'" />
  64. <view class="empty-container" v-if="type == 'P' && rightList.length < 1">
  65. <image src="@/packageMaterial/static/empty.jpg" mode="widthFix"></image>
  66. <view class="title">该产品大类下暂无可售配件商品</view>
  67. <view class="text">请联系网点在后台“辅材配件”-“配件资料管理”维护配件商品收费标准,再操作!</view>
  68. </view>
  69. </scroll-view>
  70. </view>
  71. </view>
  72. <u-transition class="dialog-mark" mode="fade" :show="isShowDialog" @tap="isShowDialog = false"></u-transition>
  73. <u-transition class="dialog-container" mode="slide-up" :show="isShowDialog">
  74. <view class="top">
  75. <view class="left">购物车</view>
  76. <view class="right" @tap="clearCart"><text class="iconfont icon-shanchu"></text>清空购物车</view>
  77. </view>
  78. <view class="list">
  79. <view class="item" v-for="(item, index) in cartList" :key="index">
  80. <view class="name">{{ item.goodsName }}</view>
  81. <view class="bottom">
  82. <view class="price"
  83. >¥{{ item.goodsAmount | priceFilter }}<text>/{{ item.goodsUnit }}</text></view
  84. >
  85. <u-number-box
  86. :step="item.goodsUnit == '米' ? 1 : 1"
  87. :min="item.goodsUnit == '米' ? 0.1 : 1"
  88. :name="item.goodsId"
  89. v-model="item.num"
  90. @change="changeCartNum"
  91. @overlimit="overlimitFun(index)"
  92. >
  93. <view slot="minus" class="ctrl">
  94. <u-icon name="minus" color="#FFFFFF" size="12"></u-icon>
  95. </view>
  96. <text slot="input" class="input">
  97. <u--input
  98. :type="item.goodsUnit == '米' ? 'digit' : 'number'"
  99. placeholder="0"
  100. inputAlign="center"
  101. border="none"
  102. v-model="item.num"
  103. @blur="changeCartNum({ name: item.goodsId, value: item.num, unit: item.goodsUnit })"
  104. ></u--input>
  105. </text>
  106. <view slot="plus" class="ctrl">
  107. <u-icon name="plus" color="#FFFFFF" size="12"></u-icon>
  108. </view>
  109. </u-number-box>
  110. </view>
  111. </view>
  112. </view>
  113. </u-transition>
  114. <template slot="footer">
  115. <view class="bottom-container">
  116. <view class="cart" @tap="isShowDialog = !isShowDialog">
  117. <text class="iconfont icon-gouwuche1"></text>
  118. <u-badge max="99" :value="totalNum" :offset="[1, 1]" absolute></u-badge>
  119. </view>
  120. <view class="price"><text>合计:</text>¥{{ totalPrice | priceFilter }}</view>
  121. <view class="btn">
  122. <u-button type="primary" text="提交" @click="submitData"></u-button>
  123. </view>
  124. </view>
  125. </template>
  126. </zj-page-layout>
  127. <!-- #endif -->
  128. <!-- #ifndef H5 -->
  129. <web-view
  130. :src="webViewHref(`/packageMaterial/pages/sale/product`, pam, crossPagePam)"
  131. @message="crossPage.$listener"
  132. ></web-view>
  133. <!-- #endif -->
  134. </template>
  135. <script>
  136. // #ifdef H5
  137. export default {
  138. data() {
  139. return {
  140. type: 'M',
  141. userMobile: '',
  142. orderNo: '',
  143. salesType: 'OUT',
  144. brandId: null,
  145. brandName: null,
  146. categoryId: null,
  147. categoryName: null,
  148. wbId: null, // 维保工单
  149. wbIsAllFee: null, // 维保工单是否包含全部费用
  150. wbPayType: null, // 维保工单费用支付方式
  151. keyword: '',
  152. leftList: [],
  153. leftCurrent: 0,
  154. rightList: [],
  155. loadStatus: 0,
  156. isShowDialog: false,
  157. cartList: [],
  158. }
  159. },
  160. computed: {
  161. totalNum() {
  162. // let val = 0;
  163. // this.cartList.forEach(item => {
  164. // val = val + item.num;
  165. // })
  166. return this.cartList.length;
  167. },
  168. totalPrice() {
  169. let val = 0;
  170. this.cartList.forEach(item => {
  171. val = val + (item.num * (item.goodsAmount * 100) / 100);
  172. })
  173. return val;
  174. },
  175. },
  176. onLoad({type, userMobile, orderNo, salesType, brandId, brandName, categoryId, categoryName, websitId, websitName, wbId, wbIsAllFee, wbPayType}) {
  177. this.type = type;
  178. this.userMobile = userMobile;
  179. this.orderNo = orderNo;
  180. // this.salesType = salesType;
  181. // this.brandId = brandId;
  182. // this.brandName = brandName;
  183. this.categoryId = categoryId;
  184. this.categoryName = categoryName;
  185. this.websitId = websitId;
  186. this.websitName = websitName;
  187. this.wbId = wbId;
  188. this.wbIsAllFee = wbIsAllFee;
  189. this.wbPayType = wbPayType;
  190. uni.setNavigationBarTitle({
  191.  title: type == 'M' ? '选择辅材' : '选择配件'
  192. })
  193. if(type === 'M') {
  194. this.getLeftList();
  195. }else {
  196. this.getRightList();
  197. }
  198. },
  199. methods: {
  200. // 获取左侧分类
  201. getLeftList() {
  202. this.$api.post('/pay/websitCategoryList', {
  203. pageNum: 1,
  204. pageSize: -1,
  205. }).then(res => {
  206. this.leftList = res.data.records;
  207. this.leftCurrent = res.data.records.length > 0 ? res.data.records[0].categoryId : 0;
  208. this.getRightList();
  209. })
  210. },
  211. // 获取右侧产品
  212. getRightList() {
  213. this.loadStatus = 1;
  214. let url = '', params = {};
  215. if(this.type === 'M') {
  216. url = '/pay/chargeList';
  217. params = {
  218. categoryId: this.leftCurrent,
  219. orderId: this.orderNo,
  220. }
  221. }else {
  222. url = '/pay/websitGoodsList';
  223. params = {
  224. categoryName: this.categoryName,
  225. brand: this.brandName,
  226. orderId: this.orderNo,
  227. // normType: 'M'
  228. }
  229. }
  230. this.$api.post(url, {
  231. pageNum: 1,
  232. pageSize: -1,
  233. name: this.keyword,
  234. ...params
  235. }).then(res => {
  236. this.loadStatus = 0;
  237. let list = res.data.records.map(item => {
  238. return this.type === 'M' ? {
  239. goodsId: item.normId,
  240. goodsName: item.normName,
  241. goodsCode: item.normCode,
  242. goodsUnit: item.unit,
  243. goodsAmount: item.normAmount,
  244. num: 0
  245. } : {
  246. goodsId: item.goodsId,
  247. goodsName: item.goodsName,
  248. goodsCode: item.goodsCode,
  249. goodsUnit: item.goodsSalesUnit,
  250. goodsAmount: item.normAmount,
  251. normType: item.normType,
  252. num: 0
  253. }
  254. });
  255. for(let i = 0; i < list.length; i++) {
  256. for(let j = 0; j < this.cartList.length; j++) {
  257. if(list[i].goodsId == this.cartList[j].goodsId) {
  258. list[i].num = this.cartList[j].num;
  259. }
  260. }
  261. }
  262. if(list.length < 1){
  263. this.loadStatus = 2;
  264. }
  265. this.rightList = list;
  266. }).catch(() => {
  267. this.loadStatus = 2;
  268. })
  269. },
  270. // 切换一级菜单
  271. changeLeft(pid) {
  272. this.leftCurrent = pid;
  273. this.getRightList();
  274. },
  275. // 搜索
  276. searchData() {
  277. this.getRightList();
  278. },
  279. changeNum(e) {
  280. let obj = this.rightList.find((item) => item.goodsId === e.name);
  281. if(e.unit && e.unit != '米') {
  282. e.value = Math.floor(e.value);
  283. obj.num = Math.floor(obj.num);
  284. }
  285. // 判断对象数组中是否存在该对象
  286. let index = this.cartList.findIndex((item) => item.goodsId === obj.goodsId);
  287. // 如果是0,就删除
  288. if(index !== -1 && e.value == 0) {
  289. this.cartList.splice(index, 1);
  290. }
  291. // 如果有就替换,没有就添加
  292. else if (index !== -1) {
  293. this.cartList.splice(index, 1, obj);
  294. }
  295. else {
  296. if(e.value > 0) {
  297. this.cartList.push(obj);
  298. }
  299. }
  300. },
  301. changeCartNum(e) {
  302. let obj = this.cartList.find((item) => item.goodsId === e.name);
  303. if(e.unit && e.unit != '米') {
  304. e.value = Math.floor(e.value);
  305. obj.num = Math.floor(obj.num);
  306. }
  307. let index = this.cartList.findIndex((item) => item.goodsId === obj.goodsId);
  308. this.cartList.splice(index, 1, obj);
  309. this.getRightList();
  310. },
  311. overlimitFun(index) {
  312. this.$modal({
  313. content: '把该产品从购物车移除?'
  314. }).then(() => {
  315. this.cartList.splice(index, 1);
  316. this.getRightList();
  317. }).catch(() => {})
  318. },
  319. clearCart() {
  320. this.$modal({
  321. content: '确定清空购物车?'
  322. }).then(() => {
  323. this.cartList = [];
  324. this.getRightList();
  325. }).catch(() => {})
  326. },
  327. submitData() {
  328. if(this.cartList.length < 1) return this.$toast('请选择');
  329. this.$setStorage('materialSaleData', {
  330. type: this.type,
  331. salesType: this.salesType,
  332. brandId: this.brandId,
  333. brandName: this.brandName,
  334. categoryId: this.type == 'P' ? this.categoryId : '',
  335. categoryName: this.type == 'P' ? this.categoryName : '',
  336. websitId: this.websitId,
  337. websitName: this.websitName,
  338. userMobile: this.userMobile,
  339. orderNo: this.orderNo,
  340. wbIsAllFee: this.wbIsAllFee,
  341. wbPayType: this.wbPayType,
  342. goodsList: this.cartList
  343. });
  344. this.$navToPage({
  345. url: `/packageMaterial/pages/sale/order`
  346. })
  347. },
  348. },
  349. }
  350. // #endif
  351. // #ifndef H5
  352. export default {
  353. data() {
  354. return {
  355. pam: {},
  356. }
  357. },
  358. onLoad(pam) {
  359. this.pam = pam;
  360. }
  361. }
  362. // #endif
  363. </script>
  364. <style lang="scss" scoped>
  365. .search-container {
  366. background: #ffffff;
  367. padding: 0 20rpx 20rpx;
  368. ::v-deep .u-search {
  369. height: 60rpx;
  370. input {
  371. background: #f7f8ff !important;
  372. }
  373. .u-search__content {
  374. background: #f7f8ff !important;
  375. height: 60rpx;
  376. }
  377. }
  378. }
  379. .empty-container {
  380. height: 100%;
  381. background: #ffffff;
  382. display: flex;
  383. flex-direction: column;
  384. align-items: center;
  385. padding: 0 100rpx;
  386. image {
  387. width: 300rpx;
  388. margin-top: 100rpx;
  389. }
  390. .title {
  391. font-size: 32rpx;
  392. }
  393. .text {
  394. margin-top: 20rpx;
  395. font-size: 28rpx;
  396. line-height: 32rpx;
  397. color: $sec-font;
  398. text-align: center;
  399. }
  400. }
  401. .main-container {
  402. display: flex;
  403. height: 100%;
  404. .left-list {
  405. width: 220rpx;
  406. height: 100%;
  407. overflow-y: scroll;
  408. box-sizing: border-box;
  409. flex-shrink: 0;
  410. .item {
  411. font-size: 28rpx;
  412. color: #333333;
  413. height: 88rpx;
  414. display: flex;
  415. align-items: center;
  416. padding: 0 20rpx;
  417. &.current {
  418. color: #ffffff;
  419. background: $theme-color;
  420. }
  421. }
  422. }
  423. .right-list {
  424. flex: 1;
  425. background: #ffffff;
  426. background: #ffffff;
  427. height: 100%;
  428. box-sizing: border-box;
  429. .item {
  430. padding: 20rpx;
  431. border-bottom: 1px solid #f5f5f5;
  432. .name {
  433. font-size: 32rpx;
  434. font-weight: 500;
  435. }
  436. .text {
  437. font-size: 28rpx;
  438. color: $sec-font;
  439. margin-top: 12rpx;
  440. }
  441. .bottom {
  442. display: flex;
  443. align-items: center;
  444. justify-content: space-between;
  445. margin-top: 12rpx;
  446. .price {
  447. font-size: 28rpx;
  448. font-weight: 500;
  449. color: $minor-color;
  450. text {
  451. font-weight: normal;
  452. color: $sec-font;
  453. margin-left: 8rpx;
  454. }
  455. }
  456. .input {
  457. width: 50rpx;
  458. text-align: center;
  459. padding: 0 10px;
  460. }
  461. .ctrl {
  462. width: 40rpx;
  463. height: 40rpx;
  464. background-color: $theme-color;
  465. border-radius: 50%;
  466. display: flex;
  467. justify-content: center;
  468. align-items: center;
  469. }
  470. }
  471. }
  472. }
  473. }
  474. .bottom-container {
  475. display: flex;
  476. align-items: center;
  477. padding: 20rpx;
  478. .cart {
  479. flex-shrink: 0;
  480. width: 110rpx;
  481. height: 110rpx;
  482. border-radius: 50%;
  483. background: $theme-color;
  484. position: relative;
  485. display: flex;
  486. align-items: center;
  487. justify-content: center;
  488. margin-top: -40rpx;
  489. .iconfont {
  490. font-size: 52rpx;
  491. color: #ffffff;
  492. font-weight: 600;
  493. }
  494. }
  495. .price {
  496. margin-left: 20rpx;
  497. flex: 1;
  498. font-size: 32rpx;
  499. color: $minor-color;
  500. font-weight: 500;
  501. text {
  502. font-weight: normal;
  503. color: $sec-font;
  504. }
  505. }
  506. .btn {
  507. width: 180rpx;
  508. // ::v-deep .u-button {
  509. // height: 60rpx;
  510. // }
  511. }
  512. }
  513. .dialog-mark {
  514. position: fixed;
  515. top: 0;
  516. left: 0;
  517. width: 100%;
  518. height: 100%;
  519. background: rgba($color: #000000, $alpha: 0.6);
  520. }
  521. .dialog-container {
  522. width: 100%;
  523. box-sizing: border-box;
  524. background: #ffffff;
  525. position: fixed;
  526. bottom: 100rpx;
  527. left: 0;
  528. padding: 30rpx;
  529. .top {
  530. display: flex;
  531. align-items: center;
  532. justify-content: space-between;
  533. .left {
  534. font-size: 32rpx;
  535. font-weight: 500;
  536. }
  537. .right {
  538. display: flex;
  539. align-items: center;
  540. font-size: 28rpx;
  541. color: $sec-font;
  542. text {
  543. font-size: 32rpx;
  544. margin-right: 8rpx;
  545. }
  546. }
  547. }
  548. .list {
  549. max-height: 400rpx;
  550. overflow-y: scroll;
  551. margin-top: 20rpx;
  552. .item {
  553. padding: 20rpx 0;
  554. border-bottom: 1px solid #f5f5f5;
  555. &:last-child {
  556. border: none;
  557. }
  558. .name {
  559. font-size: 32rpx;
  560. font-weight: 500;
  561. }
  562. .text {
  563. font-size: 28rpx;
  564. color: $sec-font;
  565. margin-top: 12rpx;
  566. }
  567. .bottom {
  568. display: flex;
  569. align-items: center;
  570. justify-content: space-between;
  571. margin-top: 12rpx;
  572. .price {
  573. font-size: 28rpx;
  574. font-weight: 500;
  575. color: $minor-color;
  576. text {
  577. font-weight: normal;
  578. color: $sec-font;
  579. margin-left: 8rpx;
  580. }
  581. }
  582. .input {
  583. width: 50rpx;
  584. text-align: center;
  585. padding: 0 10px;
  586. }
  587. .ctrl {
  588. width: 40rpx;
  589. height: 40rpx;
  590. background-color: $theme-color;
  591. border-radius: 50%;
  592. display: flex;
  593. justify-content: center;
  594. align-items: center;
  595. }
  596. }
  597. }
  598. }
  599. }
  600. </style>