index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. <template>
  2. <view class="product">
  3. <view class="top"></view>
  4. <view class="head">
  5. <view class="handle">
  6. <view class="head_left">
  7. <span class="cuIcon-back" @click="back"></span>
  8. </view>
  9. <span class="center">商品管理</span>
  10. <view class="head_right">
  11. <!-- <span class="cuIcon-search" @click="goSearch"></span> -->
  12. <view class="manage" @click="manage">
  13. {{isManage?'退出管理':'管理'}}
  14. </view>
  15. </view>
  16. </view>
  17. <view class="search">
  18. <span class="cuIcon-search"></span>
  19. <!-- <input @blur="InputBlur" :adjust-position="false" type="text" placeholder="请输入关键词" confirm-type="search"> -->
  20. <u-input v-model="productName" />
  21. </input>
  22. <view class="search_btn" @click.stop="getProductList">
  23. <span></span>搜索
  24. </view>
  25. </view>
  26. <view class="type">
  27. <view class="type_item" :class="currentIndex == index?'active':''" v-for="(item,index) in typeList" :key="index"
  28. @click="selectType(item,index)">
  29. {{item.statusName}}({{item.number}})
  30. <span class="line" v-if="currentIndex == index"></span>
  31. </view>
  32. </view>
  33. </view>
  34. <view class="list">
  35. <view class="product_item" v-for="(item,index) in productList" :key="index" @click="goDetails(item)">
  36. <view class="status">
  37. <span class="round" v-if="item.productStatus =='1'">售卖中</span>
  38. <span class="round no" v-if="item.productStatus =='0'" style="color:#666666 ;">未上架</span>
  39. <span class="audit " v-if="item.productStatus =='2'" style="color:#596ABB ;">审核中</span>
  40. <span class="reject " v-if="item.productStatus =='3'" style="color:#F55D65 ;">未通过</span>
  41. <span class="line"></span>
  42. <span v-if="item.saleStartDate">{{item.saleStartDate.slice(0,10)}}-{{item.saleEndDate.slice(0,10)}}</span>
  43. <!-- <span>已售:{{item.num}}</span>
  44. <span>库存:{{item.inventory}}</span> -->
  45. </view>
  46. <view class="details">
  47. <view class="img">
  48. <image :src="item.productImage" mode=""></image>
  49. </view>
  50. <view class="data">
  51. <span>{{item.productName}}</span>
  52. <!-- <span>售卖时间:{{item.time}}</span> -->
  53. <view class="repertory">库存:{{item.stockQuantity}} <span></span> 销量:{{item.soldQuantity}}</view>
  54. <view class="price">
  55. <span style="font-size: 22rpx;margin: 0px;">¥</span>{{item.soldPrice}}
  56. <span style="color:#999 ;font-size: 22rpx; text-decoration: line-through;">¥{{item.price}}</span>
  57. </view>
  58. </view>
  59. <view class="tag" v-if="isManage" @click.stop="select(item)">
  60. <!-- <span>组合套餐</span> -->
  61. <!-- <span class="frame"></span> -->
  62. <image src="/static/product/select.png" mode="" v-if="item.select"></image>
  63. <image src="/static/product/round.png" mode="" v-else></image>
  64. </view>
  65. </view>
  66. <view class="btn_box">
  67. <view class="delist" @click.stop="sell(item)" v-if="item.productStatus==0">
  68. 上架
  69. </view>
  70. <view class="delist" @click.stop="delist(item)" v-if="item.productStatus==1">
  71. 下架
  72. </view>
  73. <view class="edit delist" @click.stop="edit(item)">
  74. 编辑
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. <view class="creat">
  80. <view class="operate" v-if="isManage">
  81. <view class="all" @click="allSelect">
  82. <image src="/static/product/select.png" mode="" v-if="isAll"></image>
  83. <image src="/static/product/round.png" mode="" v-else></image>
  84. 全选
  85. </view>
  86. <view class="delete" @click="remove">删除</view>
  87. <view class="delete delist" @click="deletes">下架</view>
  88. </view>
  89. <view class="btn" @click="creatProduct" v-else>
  90. <image src="/static/product/product.png" mode=""></image>
  91. 创建商品
  92. </view>
  93. </view>
  94. <view class="popup" v-if="isDelete">
  95. <view class="content">
  96. <view class="title">
  97. <span>删除商品</span>
  98. </view>
  99. <view class="center">
  100. <image src="/static/index/close.png" mode="" v-if="canBeDelete"></image>
  101. <image src="/static/product/error.png" mode="" v-else></image>
  102. <view class="error" v-if="canBeDelete">
  103. 确定要删除?
  104. </view>
  105. <view class="error" v-else>
  106. 当前门店还存在有效服务券<br />
  107. <span style="margin-top: 12rpx;">暂时无法关闭门店</span>
  108. </view>
  109. </view>
  110. <view class="sub" @click="isSuccess = false">
  111. <view class="button">
  112. 确定
  113. </view>
  114. </view>
  115. </view>
  116. </view>
  117. </view>
  118. </template>
  119. <script>
  120. export default {
  121. data() {
  122. return {
  123. isManage: false,
  124. currentIndex: 0,
  125. productStatus: 0, //商品状态,默认1售卖中,0未上架,2审核中,3未通过
  126. isAll: false,
  127. isDelete: false,
  128. canBeDelete: true,
  129. productName: '',
  130. typeList: [{
  131. type: '待上架',
  132. productStatus: 0
  133. },
  134. {
  135. type: '售卖中',
  136. productStatus: 1
  137. },
  138. {
  139. type: '审核中',
  140. productStatus: 2
  141. },
  142. {
  143. type: '未通过',
  144. productStatus: 3
  145. }
  146. ],
  147. productList: [],
  148. merchantId: '',
  149. productHandleList: []
  150. }
  151. },
  152. methods: {
  153. //返回
  154. back() {
  155. uni.switchTab({
  156. url: '/pages/index/index'
  157. })
  158. },
  159. handleClear() {
  160. this.getProductList()
  161. // 这里可以添加其他逻辑
  162. },
  163. //切换分类
  164. selectType(item, index) {
  165. if (!this.isManage) {
  166. this.currentIndex = index
  167. this.productStatus = item.code
  168. this.getProductList()
  169. }
  170. },
  171. //是否管理商品
  172. manage() {
  173. this.isManage = !this.isManage
  174. this.isAll = true
  175. this.allSelect()
  176. },
  177. // 跳转至搜索页面
  178. goSearch() {
  179. uni.navigateTo({
  180. url: '/pages/product/search'
  181. })
  182. },
  183. //跳转至详情
  184. goDetails(item) {
  185. uni.navigateTo({
  186. url: '/pages/product/details?productId=' + item.productId
  187. })
  188. },
  189. //跳转至创建商品
  190. creatProduct() {
  191. uni.navigateTo({
  192. url: '/pages/product/creatProduct'
  193. })
  194. },
  195. //编辑
  196. edit(item) {
  197. uni.navigateTo({
  198. url: '/pages/product/creatProduct?productId=' + item.productId
  199. })
  200. },
  201. select(item) {
  202. item.select = !item.select
  203. this.productHandleList.push(item.productId)
  204. },
  205. //批量下架
  206. deletes() {
  207. let shelves = []
  208. this.productHandleList.forEach(item => {
  209. shelves.push({
  210. productId: item.productId,
  211. productStatus: 0
  212. })
  213. })
  214. let that = this
  215. uni.showModal({
  216. title: '确定下架商品?',
  217. success: function(res) {
  218. if (res.confirm) {
  219. that.$http.post("/app/product/shelves", shelves)
  220. .then(res => {
  221. if (res.data.code == 200) {
  222. console.log(res)
  223. uni.showToast({
  224. title: '下架成功',
  225. duration: 2000,
  226. icon: 'none'
  227. });
  228. that.getProductList()
  229. that.isManage = false
  230. that.isAll = false
  231. }
  232. })
  233. } else if (res.cancel) {
  234. console.log('用户点击取消');
  235. that.isAll = false
  236. that.allSelect()
  237. }
  238. }
  239. });
  240. },
  241. //批量删除
  242. remove() {
  243. this.productList.forEach((item => {
  244. this.productHandleList.push(item.productId)
  245. }))
  246. let ids = this.productHandleList.join(',')
  247. console.log(ids)
  248. let that = this
  249. uni.showModal({
  250. title: '确定删除商品?',
  251. success: function(res) {
  252. if (res.confirm) {
  253. that.$http.get("/app/product/deleteBatch?ids=" + ids, )
  254. .then(res => {
  255. if (res.data.code == 200) {
  256. console.log(res)
  257. uni.showToast({
  258. title: '删除成功',
  259. duration: 2000,
  260. icon: 'none'
  261. });
  262. that.getProductList()
  263. that.getStatus()
  264. that.isManage = false
  265. that.isAll = false
  266. }
  267. })
  268. } else if (res.cancel) {
  269. console.log('用户点击取消');
  270. }
  271. }
  272. });
  273. },
  274. //全选
  275. allSelect() {
  276. if (this.isAll) {
  277. this.isAll = false
  278. this.productList.forEach(item => {
  279. item.select = false
  280. })
  281. } else {
  282. this.isAll = true
  283. this.productList.forEach(item => {
  284. item.select = true
  285. })
  286. }
  287. },
  288. getProductList() {
  289. this.$http.get("/app/product/list?merchantId=" + this.merchantId + "&productStatus=" + this.productStatus +
  290. '&productName=' + this.productName, )
  291. .then(res => {
  292. if (res.data.code == 200) {
  293. res.data.result.records.forEach((item) => {
  294. item.select = false;
  295. })
  296. this.productList = res.data.result.records
  297. console.log(this.productList)
  298. }
  299. })
  300. },
  301. delist(item) {
  302. console.log(item)
  303. let shelves = []
  304. shelves.push({
  305. productId: item.productId,
  306. productStatus: 0
  307. })
  308. let that = this
  309. uni.showModal({
  310. title: '确定下架商品',
  311. success: function(res) {
  312. if (res.confirm) {
  313. that.$http.post("/app/product/shelves", shelves)
  314. .then(res => {
  315. if (res.data.code == 200) {
  316. uni.showToast({
  317. title: '下架成功',
  318. duration: 2000,
  319. icon: 'none'
  320. });
  321. that.getProductList()
  322. that.getStatus()
  323. }
  324. })
  325. } else if (res.cancel) {
  326. console.log('用户点击取消');
  327. }
  328. }
  329. });
  330. },
  331. //上架
  332. sell(item) {
  333. console.log(item)
  334. let shelves = []
  335. shelves.push({
  336. productId: item.productId,
  337. productStatus: 1
  338. })
  339. let that = this
  340. uni.showModal({
  341. title: '确定上架商品?',
  342. success: function(res) {
  343. if (res.confirm) {
  344. that.$http.post("/app/product/shelves", shelves)
  345. .then(res => {
  346. if (res.data.code == 200) {
  347. uni.showToast({
  348. title: '上架成功',
  349. duration: 2000,
  350. icon: 'none'
  351. });
  352. that.getProductList()
  353. that.getStatus()
  354. }
  355. })
  356. } else if (res.cancel) {
  357. console.log('用户点击取消');
  358. }
  359. }
  360. });
  361. },
  362. getStatus() {
  363. this.$http.get("/app/product/statusCount?merchantId=" + this.merchantId, ).then(res => {
  364. if (res.data.code == 200) {
  365. this.typeList = res.data.result
  366. }
  367. })
  368. }
  369. },
  370. mounted() {
  371. this.getProductList()
  372. this.getStatus()
  373. },
  374. onShow() {
  375. let that = this
  376. uni.getStorage({
  377. key: 'login_user_info',
  378. success: function(res) {
  379. that.merchantId = res.data.merchantId
  380. }
  381. })
  382. uni.removeStorage({
  383. key: 'smdate',
  384. });
  385. uni.removeStorage({
  386. key: 'group',
  387. });
  388. }
  389. }
  390. </script>
  391. <style lang="scss" scoped>
  392. .product {
  393. width: 100%;
  394. height: 100vh;
  395. display: flex;
  396. flex-direction: column;
  397. justify-content: space-between;
  398. background: #F7F8FC;
  399. .top {
  400. width: 100%;
  401. height: var(--status-bar-height);
  402. background: linear-gradient(87deg, #FFFFFF 0%, #A3CDFF 100%), linear-gradient(360deg, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%);
  403. }
  404. .head {
  405. width: 100%;
  406. background: #ffffff;
  407. .handle {
  408. height: 112rpx;
  409. display: flex;
  410. justify-content: space-between;
  411. align-items: center;
  412. padding: 0px 24rpx;
  413. position: relative;
  414. background: linear-gradient(87deg, #FFFFFF 0%, #A3CDFF 100%), linear-gradient(360deg, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%);
  415. .head_left {
  416. font-size: 40rpx;
  417. }
  418. .center {
  419. position: absolute;
  420. left: 50%;
  421. top: 50%;
  422. transform: translate(-50%, -50%);
  423. font-size: 36rpx;
  424. font-weight: 600;
  425. }
  426. .head_right {
  427. display: flex;
  428. justify-content: space-between;
  429. align-items: center;
  430. span {
  431. width: 40rpx;
  432. height: 40rpx;
  433. display: flex;
  434. justify-content: center;
  435. align-items: center;
  436. }
  437. .manage {
  438. // width: 150rpx;
  439. margin-left: 28rpx;
  440. }
  441. }
  442. }
  443. .search {
  444. width: 93%;
  445. height: 56rpx;
  446. background: #F7F8FC;
  447. border-radius: 12rpx;
  448. display: flex;
  449. align-items: center;
  450. justify-content: space-between;
  451. margin: 16rpx auto;
  452. font-size: 26rpx;
  453. padding: 13rpx 20rpx;
  454. span {
  455. margin-right: 15rpx;
  456. }
  457. input {
  458. flex: 1;
  459. font-size: 26rpx;
  460. }
  461. .search_btn {
  462. width: 72rpx;
  463. color: #333333;
  464. display: flex;
  465. align-items: center;
  466. justify-content: space-between;
  467. span {
  468. display: block;
  469. width: 1px;
  470. height: 26rpx;
  471. background-color: #eeeeee;
  472. }
  473. }
  474. }
  475. .type {
  476. display: flex;
  477. justify-content: space-between;
  478. background-color: #fff;
  479. padding: 8px 24rpx 16rpx;
  480. .type_item {
  481. height: 54rpx;
  482. display: flex;
  483. justify-content: center;
  484. align-items: center;
  485. font-size: 26rpx;
  486. color: #888888;
  487. position: relative;
  488. padding: 8rpx 12rpx;
  489. background: #F2F3F5;
  490. border-radius: 8rpx;
  491. }
  492. .active {
  493. color: #2D88F4;
  494. background: #ECF5FF;
  495. }
  496. }
  497. }
  498. .list {
  499. width: 100%;
  500. flex: 1;
  501. // padding: 0px 20rpx;
  502. overflow-y: auto;
  503. .product_item {
  504. width: 100%;
  505. background-color: #fff;
  506. border-radius: 20rpx;
  507. padding: 20rpx 40rpx;
  508. margin-top: 20rpx;
  509. .status {
  510. display: flex;
  511. align-items: center;
  512. .round {
  513. display: flex;
  514. align-items: center;
  515. color: #49A03F;
  516. }
  517. .round::before {
  518. content: "";
  519. display: inline-block;
  520. width: 9rpx;
  521. height: 9rpx;
  522. background: #49A03F;
  523. border-radius: 50%;
  524. margin-right: 8rpx;
  525. }
  526. .no {
  527. color: #666666;
  528. }
  529. .no::before {
  530. content: "";
  531. display: inline-block;
  532. width: 9rpx;
  533. height: 9rpx;
  534. background: #666666;
  535. border-radius: 50%;
  536. margin-right: 8rpx;
  537. }
  538. .audit {
  539. display: flex;
  540. align-items: center;
  541. color: #596ABB;
  542. }
  543. .audit::before {
  544. content: "";
  545. display: inline-block;
  546. width: 9rpx;
  547. height: 9rpx;
  548. background: #596ABB;
  549. border-radius: 50%;
  550. margin-right: 8rpx;
  551. }
  552. .reject {
  553. display: flex;
  554. align-items: center;
  555. color: #F55D65;
  556. }
  557. .reject::before {
  558. content: "";
  559. display: inline-block;
  560. width: 9rpx;
  561. height: 9rpx;
  562. background: #F55D65;
  563. border-radius: 50%;
  564. margin-right: 8rpx;
  565. }
  566. .line {
  567. display: block;
  568. width: 1rpx;
  569. height: 20rpx;
  570. background: #d9d9d9;
  571. margin: 0 12rpx;
  572. }
  573. }
  574. .details {
  575. width: 100%;
  576. height: auto;
  577. min-height: 132rpx;
  578. height: 132rpx;
  579. display: flex;
  580. align-items: center;
  581. margin-top: 20rpx;
  582. .img {
  583. margin-right: 16rpx;
  584. border-radius: 12rpx;
  585. overflow: hidden;
  586. image {
  587. width: 132rpx;
  588. height: 132rpx;
  589. }
  590. }
  591. .data {
  592. flex: 1;
  593. height: 100%;
  594. display: flex;
  595. flex-direction: column;
  596. justify-content: space-between;
  597. font-weight: 600;
  598. font-style: 28rpx;
  599. .repertory {
  600. font-size: 24rpx;
  601. display: flex;
  602. align-items: center;
  603. color: #666;
  604. font-weight: 400;
  605. span {
  606. display: block;
  607. width: 1rpx;
  608. height: 20rpx;
  609. background: #d9d9d9;
  610. margin: 0 12rpx;
  611. }
  612. }
  613. .price {
  614. display: flex;
  615. align-items: center;
  616. font-size: 30rpx;
  617. font-weight: 600;
  618. span {
  619. font-size: 26rpx;
  620. margin-left: 20rpx;
  621. font-weight: 400;
  622. }
  623. }
  624. }
  625. .tag {
  626. width: 40rpx;
  627. height: 40rpx;
  628. display: flex;
  629. flex-direction: column;
  630. align-items: center;
  631. image {
  632. width: 40rpx;
  633. height: 40rpx;
  634. }
  635. }
  636. }
  637. .btn_box {
  638. width: 100%;
  639. display: flex;
  640. justify-content: flex-end;
  641. align-items: center;
  642. margin-top: 20rpx;
  643. .delist {
  644. width: 100rpx;
  645. height: 50rpx;
  646. border-radius: 8rpx;
  647. border: 1px solid #CCCCCC;
  648. display: flex;
  649. justify-content: center;
  650. align-items: center;
  651. font-size: 26rpx;
  652. color: #666666;
  653. }
  654. .edit {
  655. margin-left: 20rpx;
  656. background: rgba(68, 154, 255, 0.05);
  657. border: 1px solid #449AFF;
  658. color: #449AFF;
  659. }
  660. }
  661. }
  662. }
  663. .creat {
  664. width: 100%;
  665. height: 100rpx;
  666. background-color: #fff;
  667. display: flex;
  668. justify-content: center;
  669. align-items: center;
  670. .btn {
  671. width: 672rpx;
  672. height: 76rpx;
  673. display: flex;
  674. justify-content: center;
  675. align-items: center;
  676. background: linear-gradient(90deg, #77B6FF 0%, #449AFF 100%);
  677. border-radius: 75rpx;
  678. font-size: 28rpx;
  679. color: #FFFFFF;
  680. image {
  681. width: 40rpx;
  682. height: 40rpx;
  683. margin-right: 10rpx;
  684. }
  685. }
  686. .operate {
  687. width: 100%;
  688. display: flex;
  689. // justify-content: space-between;
  690. align-items: center;
  691. padding: 0px 20rpx;
  692. .delete {
  693. width: 205rpx;
  694. height: 76rpx;
  695. background: linear-gradient(90deg, #77B6FF 0%, #449AFF 100%);
  696. border-radius: 49rpx;
  697. font-size: 28rpx;
  698. color: #FFFFFF;
  699. display: flex;
  700. justify-content: center;
  701. align-items: center;
  702. margin-right: 24rpx;
  703. margin-left: 140rpx;
  704. }
  705. .delist {
  706. margin-left: 0rpx;
  707. background: linear-gradient(90deg, #FFA05B 0%, #FF7918 100%);
  708. }
  709. .all {
  710. width: 25%;
  711. // height: 60rpx;
  712. // border: 1px solid #999;
  713. display: flex;
  714. justify-content: center;
  715. align-items: center;
  716. image {
  717. width: 40rpx;
  718. height: 40rpx;
  719. margin-right: 10rpx;
  720. }
  721. }
  722. }
  723. }
  724. .popup {
  725. width: 100vw;
  726. height: 100vh;
  727. position: fixed;
  728. top: 0;
  729. left: 0;
  730. background: rgba(0, 0, 0, 0.4);
  731. display: flex;
  732. align-items: center;
  733. justify-content: center;
  734. .content {
  735. width: 570rpx;
  736. background: #FFFFFF;
  737. border-radius: 16rpx;
  738. padding: 0px 24rpx;
  739. padding-bottom: 16rpx;
  740. .title {
  741. width: 100%;
  742. height: 86rpx;
  743. font-size: 32rpx;
  744. color: #333333;
  745. font-weight: 600;
  746. border-bottom: 1px solid #EEEEEE;
  747. display: flex;
  748. align-items: center;
  749. justify-content: center;
  750. }
  751. .center {
  752. font-size: 30rpx;
  753. color: #333333;
  754. line-height: 35rpx;
  755. display: flex;
  756. flex-direction: column;
  757. align-items: center;
  758. justify-content: center;
  759. padding-top: 28rpx;
  760. border-bottom: 1px solid #EEEEEE;
  761. padding-bottom: 40rpx;
  762. margin-bottom: 16rpx;
  763. .error {
  764. text-align: center;
  765. }
  766. image {
  767. width: 100rpx;
  768. height: 100rpx;
  769. margin-bottom: 10rpx;
  770. }
  771. }
  772. .sub {
  773. width: 320rpx;
  774. height: 68rpx;
  775. border-radius: 66rpx;
  776. font-size: 28rpx;
  777. color: #FFFFFF;
  778. display: flex;
  779. align-items: center;
  780. justify-content: center;
  781. margin: 0rpx auto;
  782. .button {
  783. width: 320rpx;
  784. height: 68rpx;
  785. background: #449AFF;
  786. border-radius: 66rpx;
  787. display: flex;
  788. align-items: center;
  789. justify-content: center;
  790. }
  791. }
  792. .start {
  793. background: #53CC48;
  794. }
  795. .rest {
  796. background: #FF8024;
  797. }
  798. }
  799. }
  800. }
  801. </style>