普兆健康管家前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

501 lines
11 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <view class="page__view">
  3. <navbar bgColor="#F3F2F7" >
  4. <image class="nav-icon" src="@/static/image/icon-nav.png" mode="widthFix"></image>
  5. </navbar>
  6. <view class="main">
  7. <view class="top">
  8. <view class="flex header">
  9. <view class="flex label">
  10. <view>购物车</view>
  11. <view v-if="total" class="desc">{{ `${total}` }}</view>
  12. </view>
  13. <button v-if="mode == 'edit'" class="btn" @click="onLeaveEdit">完成</button>
  14. <button v-else class="btn" @click="onEnterEdit">管理</button>
  15. </view>
  16. <!-- 搜索栏 -->
  17. <view class="search">
  18. <uv-search
  19. v-model="keyword"
  20. placeholder="请输入要查询的内容"
  21. placeholderColor="#C6C6C6"
  22. searchIconColor="#8B8B8B"
  23. :searchIconSize="40"
  24. :inputStyle="{
  25. 'font-family': 'PingFang SC',
  26. 'font-weight': 400,
  27. 'font-size': '28rpx',
  28. 'line-height': 1.4,
  29. 'padding': '12rpx 0',
  30. }"
  31. bgColor="#fff"
  32. :showAction="false"
  33. @search="search"
  34. ></uv-search>
  35. </view>
  36. </view>
  37. <template v-if="total">
  38. <view>
  39. <view class="card" v-for="(item, index) in list" :key="item.id">
  40. <productCard
  41. :data="item"
  42. @select="onSelect(index, $event)"
  43. @change="onChange(index, $event)"
  44. ></productCard>
  45. </view>
  46. </view>
  47. </template>
  48. <template v-else>
  49. <view class="flex flex-column empty">
  50. <view class="empty-title">购物车为空</view>
  51. <view class="empty-desc">请将喜欢的商品加入购物袋</view>
  52. </view>
  53. <view class="recommend">
  54. <view v-for="item in recommendList" :key="item.id">
  55. <recommendProductCard
  56. :data="item"
  57. cardStyle="width: 100%; height: 210px;"
  58. imgStyle="width: 100%; height: 110px;"
  59. ></recommendProductCard>
  60. </view>
  61. </view>
  62. </template>
  63. </view>
  64. <view class="flex bottom">
  65. <template v-if="mode == 'edit'">
  66. <view class="flex bar bar-edit">
  67. <button class="btn" @click="onLeaveEdit">取消</button>
  68. <button class="btn" @click="onDelete">删除</button>
  69. </view>
  70. </template>
  71. <template v-else>
  72. <view class="flex bar bar-settle">
  73. <view class="flex info">
  74. <image class="icon" src="@/pages_order/static/cart/cart-icon.png" mode="widthFix"></image>
  75. <view>
  76. <view class="flex row">已选<text class="count">{{ `${selectedList.length}` }}</text>已享受更低优惠</view>
  77. <view class="flex row">合计<text class="unit">¥</text><text class="price">{{ totalPrice }}</text></view>
  78. </view>
  79. </view>
  80. <button class="btn">去结算</button>
  81. </view>
  82. </template>
  83. </view>
  84. <tabber select="cart" />
  85. </view>
  86. </template>
  87. <script>
  88. import mixinsList from '@/mixins/list.js'
  89. import tabber from '@/components/base/tabbar.vue'
  90. import productCard from '@/components/cart/productCard.vue'
  91. import recommendProductCard from '@/components/product/productCard.vue'
  92. export default {
  93. mixins: [mixinsList],
  94. components: {
  95. productCard,
  96. recommendProductCard,
  97. tabber,
  98. },
  99. data() {
  100. return {
  101. // todo
  102. mixinsListApi: '',
  103. // todo
  104. keyword: '',
  105. mode: 'read',
  106. selectedList: [],
  107. recommendList: [],
  108. }
  109. },
  110. computed: {
  111. // selectedList() {
  112. // return this.list.filter(item => item.selected)
  113. // },
  114. totalPrice() {
  115. return this.selectedList.reduce((price, item) => {
  116. // return price + item.price * (item.count || 1)
  117. return price + item.price
  118. }, 0)
  119. },
  120. },
  121. methods: {
  122. // 搜素
  123. search() {
  124. // todo
  125. },
  126. getData() {
  127. this.list = [
  128. {
  129. id: '001',
  130. url: '/pages_order/static/index/recommend-pic.png',
  131. name: '月度装定制营养包',
  132. price: 688,
  133. count: 1,
  134. countDesc: '1月装',
  135. options: [
  136. { id: '001', label: '1月装', count: 1, value: 688 },
  137. { id: '002', label: '3月装', count: 3, value: 688*3 },
  138. { id: '003', label: '6月装', count: 6, value: 688*6 },
  139. ],
  140. customized: true,
  141. checked: false,
  142. },
  143. {
  144. id: '002',
  145. url: '/pages_order/static/index/recommend-pic.png',
  146. name: '月度装定制营养包',
  147. price: 688,
  148. count: 1,
  149. countDesc: '1月装',
  150. options: [
  151. { id: '001', label: '1月装', count: 1, value: 688 },
  152. { id: '002', label: '3月装', count: 3, value: 688*3 },
  153. { id: '003', label: '6月装', count: 6, value: 688*6 },
  154. ],
  155. free: true,
  156. checked: false,
  157. },
  158. {
  159. id: '003',
  160. url: '/pages_order/static/index/recommend-pic.png',
  161. name: '月度装定制营养包',
  162. price: 688,
  163. count: 1,
  164. countDesc: '1月装',
  165. options: [
  166. { id: '001', label: '1月装', count: 1, value: 688 },
  167. { id: '002', label: '3月装', count: 3, value: 688*3 },
  168. { id: '003', label: '6月装', count: 6, value: 688*6 },
  169. ],
  170. free: true,
  171. checked: false,
  172. },
  173. {
  174. id: '004',
  175. url: '/pages_order/static/index/recommend-pic.png',
  176. name: '月度装定制营养包',
  177. price: 688,
  178. count: 1,
  179. countDesc: '1月装',
  180. options: [
  181. { id: '001', label: '1月装', count: 1, value: 688 },
  182. { id: '002', label: '3月装', count: 3, value: 688*3 },
  183. { id: '003', label: '6月装', count: 6, value: 688*6 },
  184. ],
  185. free: true,
  186. checked: false,
  187. },
  188. {
  189. id: '005',
  190. url: '/pages_order/static/index/recommend-pic.png',
  191. name: '月度装定制营养包',
  192. price: 688,
  193. count: 1,
  194. countDesc: '1月装',
  195. options: [
  196. { id: '001', label: '1月装', count: 1, value: 688 },
  197. { id: '002', label: '3月装', count: 3, value: 688*3 },
  198. { id: '003', label: '6月装', count: 6, value: 688*6 },
  199. ],
  200. free: true,
  201. checked: false,
  202. },
  203. ]
  204. this.total = this.list.length
  205. this.getDataThen && this.getDataThen(this.list, this.total)
  206. },
  207. getDataThen(records, total) {
  208. console.log('getDataThen')
  209. // todo
  210. if (total) {
  211. return
  212. }
  213. this.recommendList = [
  214. {
  215. id: '001',
  216. url: '/pages_order/static/index/recommend-pic.png',
  217. name: '月度装定制营养包',
  218. sales: 24770,
  219. price: 688.00,
  220. originalPrice: 1664,
  221. },
  222. {
  223. id: '002',
  224. url: '/pages_order/static/index/recommend-pic.png',
  225. name: '月度装定制营养包',
  226. sales: 24770,
  227. price: 688.00,
  228. originalPrice: 1664,
  229. },
  230. {
  231. id: '003',
  232. url: '/pages_order/static/index/recommend-pic.png',
  233. name: '月度装定制营养包',
  234. sales: 24770,
  235. price: 688.00,
  236. originalPrice: 1664,
  237. },
  238. {
  239. id: '004',
  240. url: '/pages_order/static/index/recommend-pic.png',
  241. name: '月度装定制营养包',
  242. sales: 24770,
  243. price: 688.00,
  244. originalPrice: 1664,
  245. },
  246. ]
  247. },
  248. updateSelectedList() {
  249. this.selectedList = this.list.filter(item => item.selected)
  250. },
  251. onSelect(index, selected) {
  252. console.log('onSelect', index, selected)
  253. this.list[index].selected = selected
  254. // todo
  255. this.updateSelectedList()
  256. },
  257. onChange(index, obj) {
  258. console.log('onChange', index, obj)
  259. // todo: check
  260. this.list[index].price = obj.price
  261. this.list[index].count = obj.count
  262. this.list[index].countDesc = obj.countDesc
  263. // todo
  264. this.updateSelectedList()
  265. },
  266. onEnterEdit() {
  267. this.mode = 'edit'
  268. },
  269. onLeaveEdit() {
  270. this.mode = 'read'
  271. },
  272. onDelete() {
  273. uni.showModal({
  274. title: '确认删除?',
  275. success : e => {
  276. if(e.confirm){
  277. // todo
  278. this.list = this.list.filter(item => !item.selected)
  279. this.total = this.list.length
  280. }
  281. }
  282. })
  283. },
  284. },
  285. }
  286. </script>
  287. <style scoped lang="scss">
  288. .page__view {
  289. width: 100vw;
  290. min-height: 100vh;
  291. background-color: $uni-bg-color;
  292. position: relative;
  293. /deep/ .nav-bar__view {
  294. position: fixed;
  295. top: 0;
  296. left: 0;
  297. }
  298. .nav-icon {
  299. width: 200rpx;
  300. height: auto;
  301. vertical-align: top;
  302. }
  303. /deep/ .tabbar-box .tabbar {
  304. z-index: 9999;
  305. }
  306. }
  307. .main {
  308. padding: calc(var(--status-bar-height) + 288rpx) 32rpx 186rpx 32rpx;
  309. }
  310. .top {
  311. position: fixed;
  312. top: calc(var(--status-bar-height) + 120rpx);
  313. left: 0;
  314. width: 100%;
  315. height: 168rpx;
  316. padding: 16rpx 32rpx 8rpx 32rpx;
  317. background-color: $uni-bg-color;
  318. box-sizing: border-box;
  319. z-index: 1;
  320. }
  321. .header {
  322. justify-content: space-between;
  323. column-gap: 4rpx;
  324. .label {
  325. font-family: PingFang SC;
  326. font-weight: 600;
  327. font-size: 36rpx;
  328. line-height: 1.2;
  329. color: #252545;
  330. }
  331. .desc {
  332. font-family: PingFang SC;
  333. font-weight: 400;
  334. font-size: 24rpx;
  335. line-height: 1.4;
  336. color: #2A2A2A;
  337. }
  338. .btn {
  339. font-family: PingFang SC;
  340. font-weight: 600;
  341. font-size: 28rpx;
  342. line-height: 1.5;
  343. color: #FFFFFF;
  344. padding: 8rpx 32rpx;
  345. background-image: linear-gradient(to right, #4B348F, #845CFA);
  346. border-radius: 30rpx;
  347. }
  348. }
  349. .search {
  350. margin: 24rpx 0 40rpx 0;
  351. /deep/ .uv-search__content__icon {
  352. margin-top: 2rpx;
  353. }
  354. }
  355. .empty {
  356. width: 100%;
  357. font-family: PingFang SC;
  358. line-height: 1.4;
  359. padding: 104rpx 0;
  360. box-sizing: border-box;
  361. &-title {
  362. font-weight: 500;
  363. font-size: 32rpx;
  364. color: #000000;
  365. }
  366. &-desc {
  367. margin-top: 16rpx;
  368. font-weight: 400;
  369. font-size: 26rpx;
  370. color: #8B8B8B;
  371. }
  372. }
  373. .recommend {
  374. margin-top: 40rpx;
  375. display: grid;
  376. grid-template-columns: repeat(2, 1fr);
  377. gap: 32rpx;
  378. }
  379. .card {
  380. margin-top: 32rpx;
  381. }
  382. .bottom {
  383. position: fixed;
  384. left: 0;
  385. bottom: calc(env(safe-area-inset-bottom) + #{$tabbar-height});
  386. width: 100vw;
  387. height: 122rpx;
  388. padding: 0 40rpx;
  389. background: #FFFFFF;
  390. box-sizing: border-box;
  391. }
  392. .bar {
  393. width: 100%;
  394. &-edit {
  395. column-gap: 32rpx;
  396. .btn {
  397. flex: 1;
  398. padding: 16rpx 0;
  399. font-family: PingFang SC;
  400. font-weight: 500;
  401. font-size: 36rpx;
  402. line-height: 1;
  403. color: #252545;
  404. border: 2rpx solid #252545;
  405. border-radius: 41rpx;
  406. }
  407. }
  408. &-settle {
  409. justify-content: space-between;
  410. .info {
  411. column-gap: 16rpx;
  412. font-family: PingFang SC;
  413. font-weight: 400;
  414. font-size: 24rpx;
  415. line-height: 1.4;
  416. color: #626262;
  417. .icon {
  418. width: 76rpx;
  419. height: auto;
  420. }
  421. .row {
  422. justify-content: flex-start;
  423. }
  424. .count,
  425. .unit,
  426. .price {
  427. font-weight: 500;
  428. color: #7451DE;
  429. }
  430. .count {
  431. margin: 0 12rpx;
  432. }
  433. .unit {
  434. margin: 0 8rpx;
  435. }
  436. .price {
  437. font-size: 40rpx;
  438. }
  439. }
  440. .btn {
  441. padding: 16rpx 46rpx;
  442. color: #FFFFFF;
  443. font-family: PingFang SC;
  444. font-weight: 500;
  445. font-size: 36rpx;
  446. line-height: 1;
  447. background-image: linear-gradient(to right, #4B348F, #845CFA);
  448. border-radius: 41rpx;
  449. }
  450. }
  451. }
  452. </style>