comListEdit.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. <template>
  2. <view class="container">
  3. <u-navbar leftIconColor="#fff" titleStyle="color:#fff;fontSize:36rpx;" :autoBack="true" bgColor="#2C6FF3"
  4. :placeholder="true" :title="title"></u-navbar>
  5. <view class="flex align-center justify-around margintop">
  6. <view class="">共关联({{comList.length}})件商品 </view>
  7. <view class="color">点击图片可以移除</view>
  8. <view class="">
  9. <xbutton size="size" @tap='save'>保存</xbutton>
  10. </view>
  11. </view>
  12. <view class="margintop">
  13. <view style="height: 230rpx;overflow: hidden;" v-if="comList&&comList.length>0">
  14. <u-scroll-list :indicator="indicator" indicatorColor="#fff0f0" indicatorActiveColor="#f56c6c">
  15. <view class="flex justify-around">
  16. <view class="" v-for="(item,index) in comList" :key="item.id">
  17. <view class="flex flex-direction align-center justify-center image-dele-container"
  18. @tap="clean(item)">
  19. <view class="image">
  20. <u--image radius="4" width="120rpx" height="120rpx" :src="item.img"
  21. mode="aspectFit" :lazy-lord="true"></u--image>
  22. </view>
  23. <view class="">{{item.name}}</view>
  24. </view>
  25. </view>
  26. </view>
  27. </u-scroll-list>
  28. </view>
  29. <view class="no-com" v-else style="height: 230rpx;overflow: hidden;">
  30. 请添加商品
  31. </view>
  32. </view>
  33. <view class="search" @click="searchComm">
  34. <view class="search-input">
  35. <u-search placeholder="商品搜索" actionText="取消" :actionStyle="{color:'#2C6FF3'}" :showAction="!leftShow"
  36. :clearabled="false" v-model="keyword" @search="search" @custom="cancle"></u-search>
  37. <view @click="scan" :class="[leftShow?'scan-icon scan-left-show':'scan-icon scan-left-hidden']">
  38. <u-icon name="scan" size="22" color="#909399"></u-icon>
  39. </view>
  40. </view>
  41. <view class="search-history flex flex-wrap flex-start" v-if="!leftShow">
  42. <view class="history-item" v-for="(item,index) in historyList" :key="index" @click="searchFast(item)">
  43. {{item}}
  44. </view>
  45. </view>
  46. </view>
  47. <view class="content">
  48. <view class="swiperitem-content">
  49. <view class="classify-wrap">
  50. <Classify :tabList="perTabList" :status="perStatus"
  51. :commList="perCommList" @switchMenu="perSwitchMenu" @lowerBottom="perLowerBottom"
  52. :isModal="true" :height="fullHeight" @comClick="comClick" :leftShow="leftShow" />
  53. </view>
  54. </view>
  55. </view>
  56. </view>
  57. </template>
  58. <script>
  59. import Classify from "@/components/classify/index.vue"
  60. import {
  61. goodsCategory as perGoodsCategory,
  62. ownerGoodsList as pageByGoodsMerc
  63. } from "@/api/commodity/mercGoods.js"
  64. import {
  65. goodsCategory as pubGoodsCategory,
  66. ownerGoodsList as pageByGoods
  67. } from "@/api/commodity/goods.js"
  68. import {
  69. saveListingGoods,
  70. refGoods
  71. } from "@/api/commoditylist/commoditylist.js"
  72. export default {
  73. components: {
  74. Classify
  75. },
  76. data() {
  77. return {
  78. modelId: '', //清单id
  79. goodsId: [], //商品id列表
  80. fullHeight: "0",
  81. // 私库
  82. perTabList: [], //商品类目
  83. perCommList: [], //商品列表
  84. perPage: 1, //商品分页
  85. perSize: 10,
  86. perStatus: 'loadmore', //加载更多
  87. id: null, //设备id
  88. categoryCode: null,
  89. leftShow: true,
  90. historyList: [],
  91. keyword: '',
  92. oldList:[],
  93. newList:[],
  94. title:null,
  95. deviceId:null,
  96. }
  97. },
  98. async onLoad(o) {
  99. let _this = this;
  100. const query = uni.createSelectorQuery().in(this);
  101. query.select(".classify-wrap").boundingClientRect((data) => {
  102. _this.top = data.top;
  103. uni.getSystemInfo({
  104. success(res) {
  105. // 针对iPhone X等机型底部安全距离做适配
  106. const model = res.model;
  107. const modelInclude = [
  108. "iPhone X",
  109. 'iPhone XR',
  110. "iPhone XS",
  111. "iPhone XS MAX",
  112. "iPhone 12/13 mini",
  113. "iPhone 12/13 (Pro)",
  114. "iPhone 12/13 Pro Max",
  115. "iPhone 14 Pro Max"
  116. ];
  117. let safeDistance = modelInclude.includes(model)
  118. //动态设置商品区域高度
  119. if (safeDistance) {
  120. _this.fullHeight = res.windowHeight - _this.top - 34 + 'px';
  121. } else {
  122. _this.fullHeight = res.windowHeight - _this.top + 'px';
  123. }
  124. },
  125. });
  126. }).exec();
  127. this.title = o.title
  128. this.modelId = o.modelId
  129. this.deviceId=o.deviceId
  130. if (uni.getStorageSync('goods')) {
  131. this.historyList = JSON.parse(uni.getStorageSync('goods'))
  132. }
  133. await this.getrefGoods()
  134. this.getPerCategory()
  135. },
  136. async onShow() {
  137. this.perReset()
  138. await this.getPerCommList()
  139. },
  140. computed:{
  141. comList(){
  142. let list=[]
  143. list=[...this.oldList,...this.newList]
  144. return list
  145. },
  146. },
  147. methods: {
  148. searchComm() {
  149. this.leftShow = false
  150. },
  151. search(val) {
  152. this.saveKeyWord('goods', this.keyword)
  153. this.perReset();
  154. this.getPerCommList()
  155. },
  156. cancle(val) {
  157. this.keyword = ''
  158. this.leftShow = true
  159. this.search()
  160. },
  161. saveKeyWord(type, val) {
  162. if (val) {
  163. let arr = []
  164. if (uni.getStorageSync(type)) {
  165. let arr = JSON.parse(uni.getStorageSync(type))
  166. if (arr.indexOf(val) != -1) {
  167. console.log('arr.indexOf(val)', arr.indexOf(val))
  168. arr.splice(arr.indexOf(val), 1)
  169. }
  170. arr.unshift(val)
  171. if (arr.length > 6) {
  172. arr.pop()
  173. }
  174. this.historyList = JSON.parse(JSON.stringify(arr))
  175. uni.setStorageSync(type, JSON.stringify(arr))
  176. } else {
  177. arr.unshift(val)
  178. this.historyList = JSON.parse(JSON.stringify(arr))
  179. uni.setStorageSync(type, JSON.stringify(arr))
  180. }
  181. } else {
  182. return
  183. }
  184. },
  185. searchFast(e) {
  186. this.keyword = e
  187. this.search()
  188. },
  189. //扫码
  190. scan() {
  191. uni.scanCode({
  192. success: (res) => {
  193. this.keyword = res.result;
  194. this.search()
  195. }
  196. });
  197. },
  198. //获取类目列表
  199. getPerCategory() {
  200. return new Promise((resolve, reject) => {
  201. perGoodsCategory().then(res => {
  202. if (res.data && res.data.length > 0) {
  203. this.perTabList = res.data.map(i => {
  204. if (i.categoryCode == null) {
  205. i.categoryName = '未定义'
  206. return i
  207. } else {
  208. return i
  209. }
  210. });
  211. if (this.perTabList && this.perTabList.length > 0) {
  212. this.categoryCode = this.perTabList[0].categoryCode
  213. }
  214. }
  215. resolve(res)
  216. }).catch(err => {
  217. reject(err)
  218. })
  219. })
  220. },
  221. //商品类目切换
  222. perSwitchMenu(item) {
  223. this.categoryCode = item.categoryCode
  224. this.perReset()
  225. this.getPerCommList()
  226. },
  227. //根据类目获取商品列表
  228. getPerCommList() {
  229. let params = {}
  230. if (this.leftShow) { //搜索
  231. params = {
  232. categoryCode: this.categoryCode,
  233. page: {
  234. current: this.perPage,
  235. size: this.perSize
  236. },
  237. }
  238. } else { //非搜索
  239. params = {
  240. page: {
  241. current: this.perPage,
  242. size: this.perSize
  243. },
  244. keyword: this.keyword
  245. }
  246. }
  247. return new Promise((resolve, reject) => {
  248. pageByGoodsMerc(params).then(res => {
  249. let data = res.data.records;
  250. if (data && data.length > 0) {
  251. data = data.map(i => {
  252. i.name = i.goodsName;
  253. i.barcode = i.goodsBarcode;
  254. i.cover = i.goodsCover;
  255. i.price = i.price != null ? Number(i.price) / 100 : null;
  256. i.categoryName = i.categoryCodeName;
  257. i.noSelect = i.isBind;
  258. return i
  259. })
  260. }
  261. if (data.length < 10) {
  262. this.perStatus = "nomore"
  263. } else {
  264. this.perStatus = "loadmore"
  265. }
  266. this.perCommList = this.perCommList.concat(data)
  267. resolve(res)
  268. }).catch(err => {
  269. reject(err)
  270. })
  271. })
  272. },
  273. //触底加载更多
  274. perLowerBottom() {
  275. if (this.perStatus == 'nomore') return
  276. this.perPage++
  277. this.getPerCommList()
  278. },
  279. //重置
  280. perReset() {
  281. this.perStatus == 'loadmore'
  282. this.perPage = 1;
  283. this.perSize = 10;
  284. this.perCommList = [];
  285. },
  286. //反显清单图片
  287. getrefGoods() {
  288. return new Promise((resolve, reject) => {
  289. refGoods({
  290. modelId: this.modelId
  291. }).then(res => {
  292. res.data.forEach(item => {
  293. this.oldList.push({
  294. name: item.goodsName,
  295. id: item.goodsId,
  296. img:item.goodsImgUrl
  297. })
  298. })
  299. resolve(res)
  300. }).catch(err => {
  301. reject(err)
  302. })
  303. })
  304. },
  305. //点击商品
  306. comClick(e) {
  307. if(e.price==null){
  308. uni.showModal({
  309. title: '提示',
  310. content: '当前商品为新商品需先设置商品价格,是否前往设置?',
  311. success: res => {
  312. if (res.confirm) {
  313. this.$tab.navigateTo('/pages/commodity/comEdit?id=' + e.id)
  314. } else if (res.cancel) {
  315. console.log('用户点击取消');
  316. }
  317. }
  318. });
  319. }else{
  320. this.addToList(e)
  321. }
  322. },
  323. //添加商品至关联
  324. addToList(e){
  325. if(this.comList.some(i=>i.id==e.goodsId)){
  326. this.$modal.msg('该商品已存在~')
  327. return
  328. }
  329. this.newList.push({
  330. name: e.goodsName,
  331. id: e.goodsId,
  332. img:e.imgUrls
  333. })
  334. },
  335. clean(e){
  336. if(e.name=='未知商品'||e.name=='非友好购物商品'){
  337. this.$modal.msg('预设商品不能删除!!!')
  338. return
  339. }
  340. for (let i = 0; i < this.oldList.length; i++) {
  341. let item=this.oldList[i]
  342. if(item.id==e.id){
  343. this.oldList.splice(i,1)
  344. return
  345. }
  346. }
  347. for (let i = 0; i < this.newList.length; i++) {
  348. let item=this.newList[i]
  349. if(item.id==e.id){
  350. this.newList.splice(i,1)
  351. return
  352. }
  353. }
  354. },
  355. save() {
  356. if (!this.comList.length) {
  357. uni.$u.toast('请选择商品')
  358. return;
  359. }
  360. var comList = []
  361. this.comList.forEach(item => {
  362. comList.push(item.id)
  363. })
  364. saveListingGoods({
  365. modelId: this.modelId, //清单ID
  366. goodsId: comList //关联的商品id,不传则表示清空
  367. }).then(res => {
  368. if (res.code == 200) {
  369. uni.$u.toast(res.msg)
  370. setTimeout(() => {
  371. this.$tab.navigateBack()
  372. }, 1000)
  373. }
  374. })
  375. },
  376. }
  377. }
  378. </script>
  379. <style lang="scss" scoped>
  380. .container {
  381. .margin {
  382. margin: 10rpx 20rpx;
  383. }
  384. .margintop {
  385. margin-top: 10rpx;
  386. }
  387. .marginleft {
  388. margin-left: 10rpx;
  389. }
  390. .active {
  391. background-color: #ffffff;
  392. }
  393. .un-active {
  394. background-color: #e5e5e5;
  395. }
  396. .color {
  397. color: red;
  398. }
  399. .image-dele-container {
  400. position: relative;
  401. width: 200rpx;
  402. height: 200rpx;
  403. margin-left: 10rpx;
  404. background-color: #f6f6f6;
  405. border-radius: 15rpx;
  406. view {
  407. text-overflow: ellipsis;
  408. overflow: hidden;
  409. white-space: nowrap;
  410. width: 120rpx;
  411. }
  412. .image {
  413. width: 120rpx;
  414. height: 120rpx;
  415. }
  416. }
  417. .image-container {
  418. width: 150rpx;
  419. height: 200rpx;
  420. background-color: #d9d9d9;
  421. image {
  422. width: 90rpx;
  423. height: 100rpx;
  424. }
  425. }
  426. .no-com{
  427. height:228rpx;
  428. text-align: center;
  429. line-height: 228rpx;
  430. }
  431. .search {
  432. padding: 24rpx 24rpx;
  433. background-color: #fff;
  434. .search-input {
  435. position: relative;
  436. .scan-icon {
  437. position: absolute;
  438. top: 50%;
  439. transform: translateY(-50%);
  440. z-index: 2;
  441. &.scan-left-show {
  442. right: 36rpx;
  443. }
  444. &.scan-left-hidden {
  445. right: 100rpx;
  446. }
  447. }
  448. }
  449. .search-history {
  450. .history-item {
  451. margin-right: 24rpx;
  452. padding: 0 12rpx;
  453. background-color: #f2f2f2;
  454. color: #333;
  455. font-size: 24rpx;
  456. line-height: 40rpx;
  457. border-radius: 40rpx;
  458. margin-top: 24rpx;
  459. }
  460. }
  461. }
  462. .btn {
  463. width: 724rpx;
  464. position: fixed;
  465. left: 13rpx;
  466. bottom: calc(24rpx + env(safe-area-inset-bottom) / 2);
  467. border-radius: 88rpx;
  468. overflow: hidden;
  469. }
  470. }
  471. </style>