index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. <template>
  2. <view class="container">
  3. <view class="title">
  4. <view class="search">
  5. <view class="title_search">
  6. <span class="iconfont">&#xe67d;</span>
  7. <form @submit="search" report-submit="true">
  8. <input type="text" :name="where.keyword" v-model="where.keyword" placeholder="搜索商品" confirm-type='search'/>
  9. </form>
  10. </view>
  11. </view>
  12. <view class="longTab">
  13. <scroll-view scroll-x="true" style="white-space: nowrap; display: flex;" scroll-with-animation class="menu" :scroll-left="tabLeft" show-scrollbar="true">
  14. <view
  15. class="longItem"
  16. :style="'width:' + isWidth + 'px'"
  17. :data-index="index"
  18. :class="index === tabClick ? 'click' : ''"
  19. v-for="(item, index) in menuList"
  20. :key="index"
  21. :id="'id' + index"
  22. @click="selectMenu(item, index)"
  23. >
  24. {{ item.name }}
  25. </view>
  26. <view v-if="menuList.length" class="underlineBox" :style="'transform:translateX(' + isLeft + 'px);width:' + isWidth + 'px'">
  27. <view class="underline bg-color-white"></view>
  28. </view>
  29. </scroll-view>
  30. </view>
  31. </view>
  32. <view v-if="shopList.length">
  33. <block v-for="(item, index) in shopList" :key="index">
  34. <view class="shop_list">
  35. <view class="shop_list_item">
  36. <view class="shop_list_item_shop">
  37. <view class="shop_list_item_shop_image">
  38. <image :src="item.image"></image>
  39. <text v-if="item.spec_type == 1" class="spec">多规格</text>
  40. </view>
  41. <view class="shop_list_item_shop_con">
  42. <view class="shop_list_item_shop_con_title line1">{{ item.store_name }}</view>
  43. <view class="shop_list_item_shop_con_message">
  44. <span>库存:{{ item.stock }}</span>
  45. <span>销量:{{ item.sales }}</span>
  46. </view>
  47. <view class="shop_list_item_shop_con_price">
  48. <span>¥{{ item.price }}</span>
  49. <del>¥{{ item.ot_price }}</del>
  50. </view>
  51. </view>
  52. </view>
  53. <view class="shop_list_item_handle">
  54. <view v-if="item.is_show == 1 && item.status == 1 && type != 5" class="shop_button" @click="upperShelfAndLowerShelf(item, index)">下架</view>
  55. <view v-if="item.is_show == 0 && item.status == 1 && type != 5" class="shop_button" @click="upperShelfAndLowerShelf(item, index)">上架</view>
  56. <view class="shop_button" v-if="type != 1 && type != 3" @click="handleDelete(item, index)">删除</view>
  57. <view class="shop_button" v-if="type == 5" @click="reduction(item, index)">恢复</view>
  58. <navigator :url="`/pages/product/addGoods/index?mer_id=${merId}&product_id=${item.product_id}`" v-if="type != 5" class="shop_button" hover-class="none">编辑</navigator>
  59. </view>
  60. </view>
  61. </view>
  62. </block>
  63. </view>
  64. <Loading :loaded="loaded" :loading="loading"></Loading>
  65. </view>
  66. </template>
  67. <script>
  68. // +----------------------------------------------------------------------
  69. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  70. // +----------------------------------------------------------------------
  71. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  72. // +----------------------------------------------------------------------
  73. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  74. // +----------------------------------------------------------------------
  75. // | Author: CRMEB Team <admin@crmeb.com>
  76. // +----------------------------------------------------------------------
  77. import { productLstApi, productTitle, productDeleteApi, productOffApi, productRestore, productDestory } from 'api/product.js';
  78. import Loading from '@/components/Loading/index.vue';
  79. import { Toast, Modal, navigateTo,getStorage, removeStorage } from 'libs/uniApi.js';
  80. export default {
  81. components: {
  82. Loading
  83. },
  84. data() {
  85. return {
  86. type: 1,
  87. tabClick: 0,
  88. tabLeft: 0,
  89. isLeft: 0, //导航栏下划线位置
  90. isWidth: 0, //每个导航栏占位
  91. childIndex: 0,
  92. menuList: [],
  93. merId: '',
  94. shopList: [],
  95. loaded: false,
  96. loading: false,
  97. where: {
  98. page: 1,
  99. limit: 15,
  100. keyword: '',
  101. },
  102. canNotReade: true
  103. };
  104. },
  105. created() {
  106. var that = this;
  107. // 获取设备宽度
  108. uni.getSystemInfo({
  109. success(e) {
  110. that.isWidth = e.windowWidth / 5;
  111. }
  112. });
  113. },
  114. onLoad(opt) {
  115. this.merId = opt.mer_id;
  116. this.getProductTitle();
  117. this.$set(this, 'type', opt.type ? Number(opt.type) : 1);
  118. this.initData();
  119. },
  120. onShow() {},
  121. // 下拉到底部
  122. onReachBottom() {
  123. this.initData();
  124. },
  125. methods: {
  126. initData() {
  127. var that = this;
  128. if (that.loading || that.loaded) return;
  129. that.loading = true;
  130. productLstApi(this.merId, { ...this.where, type: this.type }).then(
  131. res => {
  132. that.loading = false;
  133. that.loaded = res.data.list.length < that.where.limit;
  134. that.shopList.push.apply(that.shopList, res.data.list);
  135. that.where.page = that.where.page + 1;
  136. },
  137. error => {
  138. that.$util.Tips({
  139. title: error.msg
  140. });
  141. }
  142. );
  143. },
  144. search(){
  145. let that = this;
  146. that.loading = that.loaded = false;
  147. that.where.page = 1;
  148. that.shopList = [];
  149. that.initData();
  150. },
  151. // 获取列表头部
  152. getProductTitle() {
  153. productTitle(this.merId).then(res => {
  154. this.menuList = res.data;
  155. let clickIndex = 1;
  156. this.menuList.forEach((item, index) => {
  157. if (item.type == this.type) {
  158. clickIndex = index;
  159. }
  160. });
  161. this.setMenuLeft(clickIndex);
  162. });
  163. },
  164. // 点击列表头部
  165. selectMenu(item, index) {
  166. this.type = item.type;
  167. this.loading = this.loaded = false;
  168. this.where.page = 1;
  169. this.shopList = [];
  170. this.setMenuLeft(index);
  171. },
  172. /*导航栏移动位置*/
  173. setMenuLeft(index) {
  174. this.childIndex = 0;
  175. if (this.menuList.length > 5) {
  176. var tempIndex = index - 2;
  177. tempIndex = tempIndex <= 0 ? 0 : tempIndex;
  178. let tabLeft = (index - 2) * this.isWidth; //设置下划线位置
  179. this.$nextTick(function() {
  180. this.$set(this, 'tabLeft', tabLeft);
  181. });
  182. }
  183. this.tabClick = index; //设置导航点击了哪一个
  184. this.isLeft = index * this.isWidth; //设置下划线位置
  185. this.initData();
  186. },
  187. //还原
  188. reduction(item, index) {
  189. Modal('温馨提示', `商品"${item.store_name}",将被还原,请问是否继续`).then(() => {
  190. productRestore(this.merId, item.product_id).then(res => {
  191. this.$util.Tips({ title: res.message, icon: 'success' });
  192. this.shopList.splice(index, 1);
  193. });
  194. });
  195. },
  196. editGoods(item) {
  197. console.log(item);
  198. let waitDeleteData = [
  199. 'addGoodsFormData',
  200. 'singleSpecification',
  201. 'attrValue',
  202. 'modifyPriceData',
  203. 'addGoodsSecoundData',
  204. 'goodsDis',
  205. 'editGoodsDetils',
  206. 'canChange',
  207. 'canChangeSecound'
  208. ];
  209. waitDeleteData.forEach(item => {
  210. if (getStorage(item)) {
  211. removeStorage(item);
  212. }
  213. });
  214. navigateTo(1, '/pages/product/addGoods/index', { mer_id: this.merId, type: 'edit', product_id: item.product_id, type: 'edit' });
  215. },
  216. // 加入回收站
  217. handleDelete(item, index) {
  218. item.is_del == 1
  219. ? Modal('温馨提示', `商品"${item.store_name}"将被删除,请问是否继续?`).then(res => {
  220. productDestory(this.merId, item.product_id)
  221. .then(res => {
  222. this.shopList.splice(index, 1);
  223. Toast('删除成功');
  224. })
  225. .catch(rej => {
  226. Toast(`${rej}`);
  227. });
  228. })
  229. : Modal('温馨提示', `商品"${item.store_name}"将被加入回收站,请问是否继续?`).then(res => {
  230. productDeleteApi(this.merId, item.product_id)
  231. .then(res => {
  232. this.shopList.splice(index, 1);
  233. Toast('已加入回收站');
  234. })
  235. .catch(rej => {
  236. Toast(`${rej}, 加入回收站失败`);
  237. });
  238. });
  239. },
  240. // 上架下架
  241. upperShelfAndLowerShelf(obj, index) {
  242. let status = obj.is_show == 1 ? 0 : 1;
  243. productOffApi(this.merId, obj.product_id, { status: status })
  244. .then(res => {
  245. this.$util.Tips({ title: res.message, icon: 'success' });
  246. this.shopList.splice(index, 1);
  247. })
  248. .catch(err => {
  249. return this.$util.Tips({
  250. title: err
  251. });
  252. });
  253. },
  254. handleMethod(item, obj, index) {
  255. if (item.id == 1) {
  256. this.upperShelfAndLowerShelf(obj, index);
  257. return;
  258. }
  259. if (item.id == 2) {
  260. this.addToRecycleBin(obj, index);
  261. return;
  262. }
  263. }
  264. }
  265. };
  266. </script>
  267. <style lang="scss" scoped>
  268. @import './scss/index.scss';
  269. .longTab {
  270. display: flex;
  271. width: 100%;
  272. /* #ifdef H5 */
  273. padding-bottom: 20rpx;
  274. /* #endif */
  275. /* #ifdef MP */
  276. padding-top: 12rpx;
  277. padding-bottom: 12rpx;
  278. /* #endif */
  279. .longItem {
  280. height: 50upx;
  281. display: inline-block;
  282. line-height: 50upx;
  283. text-align: center;
  284. font-size: 30rpx;
  285. color: #282828;
  286. max-width: 160rpx;
  287. white-space: nowrap;
  288. overflow: hidden;
  289. text-overflow: ellipsis;
  290. overflow-x: scroll;
  291. overflow-y: hidden;
  292. /*解决ios上滑动不流畅*/
  293. -webkit-overflow-scrolling: touch;
  294. &.click {
  295. font-weight: bold;
  296. font-size: 30rpx;
  297. color: #e93323;
  298. .underline {
  299. opacity: 1;
  300. }
  301. }
  302. }
  303. .underlineBox {
  304. height: 3px;
  305. width: 20%;
  306. display: flex;
  307. align-content: center;
  308. justify-content: center;
  309. transition: 0.5s;
  310. .underline {
  311. width: 60rpx;
  312. height: 4rpx;
  313. background-color: #e93323;
  314. }
  315. }
  316. }
  317. .title_search {
  318. background: #f5f5f5;
  319. border-radius: 30rpx;
  320. height: 60rpx;
  321. padding-left: 60rpx;
  322. position: relative;
  323. .iconfont {
  324. position: absolute;
  325. top: 50%;
  326. margin-top: -14rpx;
  327. left: 30rpx;
  328. font-size: 28rpx;
  329. }
  330. input {
  331. height: 60rpx;
  332. font-size: 26rpx;
  333. margin-left: 20rpx;
  334. }
  335. }
  336. .shop_button {
  337. margin-left: 18rpx;
  338. padding: 0 34rpx;
  339. height: 60rpx;
  340. border: 1px solid #c7c7c7;
  341. border-radius: 30px;
  342. display: flex;
  343. align-items: center;
  344. justify-content: center;
  345. margin-top: 30rpx;
  346. font-size: 26rpx;
  347. color: #999999;
  348. }
  349. .shop_list {
  350. margin-top: 20rpx;
  351. padding: 0 20rpx;
  352. &_item {
  353. padding: 30rpx;
  354. background: #ffffff;
  355. border-radius: 10px;
  356. margin-bottom: 20rpx;
  357. &_shop {
  358. display: flex;
  359. &_image,
  360. uni-image {
  361. width: 150rpx;
  362. height: 150rpx;
  363. border-radius: 16rpx;
  364. position: relative;
  365. image {
  366. width: 150rpx;
  367. height: 150rpx;
  368. }
  369. }
  370. position: relative;
  371. .spec {
  372. color: #ffffff;
  373. background: rgba(0, 0, 0, 0.5);
  374. border-radius: 16rpx 0 16rpx 0;
  375. text-align: center;
  376. font-size: 18rpx;
  377. display: inline-block;
  378. width: 84rpx;
  379. line-height: 30rpx;
  380. position: absolute;
  381. bottom: 0;
  382. right: 0;
  383. }
  384. &_con {
  385. flex: 1;
  386. display: flex;
  387. flex-direction: column;
  388. margin-left: 20rpx;
  389. padding-bottom: 12rpx;
  390. &_title {
  391. font-size: 28rpx;
  392. color: #282828;
  393. max-width: 500rpx;
  394. padding-top: 4rpx;
  395. }
  396. &_message {
  397. margin-top: 15rpx;
  398. font-size: 22rpx;
  399. color: #868686;
  400. > span:nth-child(1) {
  401. display: inline-block;
  402. margin-right: 20rpx;
  403. }
  404. }
  405. &_price {
  406. margin-top: 10rpx;
  407. > span {
  408. display: inline-block;
  409. margin-right: 7rpx;
  410. font-size: 30rpx;
  411. color: #e93323;
  412. }
  413. > del {
  414. color: #bebebe;
  415. font-size: 26rpx;
  416. }
  417. }
  418. }
  419. }
  420. &_handle {
  421. display: flex;
  422. justify-content: flex-end;
  423. > view {
  424. margin-left: 18rpx;
  425. padding: 0 34rpx;
  426. height: 60rpx;
  427. border: 1px solid #c7c7c7;
  428. border-radius: 30px;
  429. display: flex;
  430. align-items: center;
  431. justify-content: center;
  432. margin-top: 30rpx;
  433. font-size: 26rpx;
  434. color: #999999;
  435. }
  436. }
  437. }
  438. }
  439. </style>