purui 2 månader sedan
förälder
incheckning
cf98ad2559
100 ändrade filer med 2811 tillägg och 178 borttagningar
  1. 1 4
      package.json
  2. 3 0
      packages/app/manifest.config.ts
  3. 13 0
      packages/app/package-lock.json
  4. 481 9
      packages/app/pages.config.ts
  5. 2 2
      packages/app/src/components/hot-activity-item.vue
  6. 24 16
      packages/app/src/components/moment-item.vue
  7. 1 1
      packages/app/src/components/swiper-evo.vue
  8. 20 0
      packages/app/src/composables/honor-dialog.ts
  9. 11 11
      packages/app/src/composables/permissions.ts
  10. 4 4
      packages/app/src/composables/share.ts
  11. 2 2
      packages/app/src/core/libs/actions.ts
  12. 17 17
      packages/app/src/core/libs/message-types.ts
  13. 6 5
      packages/app/src/core/libs/requests.ts
  14. 1 1
      packages/app/src/core/utils/common.ts
  15. 2 2
      packages/app/src/core/utils/router.ts
  16. 1 1
      packages/app/src/interceptors/route.ts
  17. 5 5
      packages/app/src/layouts/tabbar.vue
  18. 5 2
      packages/app/src/manifest.json
  19. 0 0
      packages/app/src/pages-sub/about/about.vue
  20. 0 0
      packages/app/src/pages-sub/about/components/request.vue
  21. 0 0
      packages/app/src/pages-sub/about/components/upload.vue
  22. 0 0
      packages/app/src/pages-sub/common/components/avatar.vue
  23. 0 0
      packages/app/src/pages-sub/common/components/coupon-card.vue
  24. 0 0
      packages/app/src/pages-sub/common/components/coupon-record.vue
  25. 0 0
      packages/app/src/pages-sub/common/components/coupons-selector.vue
  26. 82 0
      packages/app/src/pages-sub/common/components/honor-dialog.vue
  27. 171 0
      packages/app/src/pages-sub/common/components/honor-dialog/honor-dialog.vue
  28. 0 0
      packages/app/src/pages-sub/common/components/honor-dialog/index.ts
  29. 0 0
      packages/app/src/pages-sub/common/components/share-action-sheet.vue
  30. 0 0
      packages/app/src/pages-sub/common/content-html/index.vue
  31. 0 0
      packages/app/src/pages-sub/common/status/success/index.vue
  32. 0 0
      packages/app/src/pages-sub/common/webview/index.vue
  33. 0 20
      packages/app/src/pages-sub/demo/index.vue
  34. 0 0
      packages/app/src/pages-sub/home/about/index.vue
  35. 1 1
      packages/app/src/pages-sub/home/activity/detail/index.vue
  36. 0 0
      packages/app/src/pages-sub/home/activity/images/index.vue
  37. 0 0
      packages/app/src/pages-sub/home/classmates-detail/index.vue
  38. 0 0
      packages/app/src/pages-sub/home/classmates/index.vue
  39. 0 0
      packages/app/src/pages-sub/home/components/activity-as-of.vue
  40. 60 0
      packages/app/src/pages-sub/home/components/activity-count-down.vue
  41. 0 0
      packages/app/src/pages-sub/home/components/article.vue
  42. 50 0
      packages/app/src/pages-sub/home/components/banner.vue
  43. 1 1
      packages/app/src/pages-sub/home/components/class-item.vue
  44. 1 1
      packages/app/src/pages-sub/home/components/comment-item.vue
  45. 1 1
      packages/app/src/pages-sub/home/components/elegant-info-card.vue
  46. 77 0
      packages/app/src/pages-sub/home/components/home-banner.vue
  47. 0 0
      packages/app/src/pages-sub/home/components/info-card.vue
  48. 62 0
      packages/app/src/pages-sub/home/components/menus.vue
  49. 0 0
      packages/app/src/pages-sub/home/components/moment-video.vue
  50. 1 1
      packages/app/src/pages-sub/home/components/offline-activity-item.vue
  51. 1 1
      packages/app/src/pages-sub/home/components/register-card.vue
  52. 124 0
      packages/app/src/pages-sub/home/components/schedule-card.vue
  53. 0 0
      packages/app/src/pages-sub/home/components/test.vue
  54. 0 0
      packages/app/src/pages-sub/home/content/index.vue
  55. 1 1
      packages/app/src/pages-sub/home/mall/components/product.vue
  56. 2 2
      packages/app/src/pages-sub/home/mall/confirm-order/index.vue
  57. 0 0
      packages/app/src/pages-sub/home/mall/confirm-order/test.java
  58. 242 0
      packages/app/src/pages-sub/home/mall/detail/index.vue
  59. 10 9
      packages/app/src/pages-sub/home/mall/index.vue
  60. 2 2
      packages/app/src/pages-sub/home/mall/purchased/success/index.vue
  61. 1 1
      packages/app/src/pages-sub/home/mall/shopping-cart/index.vue
  62. 3 4
      packages/app/src/pages-sub/home/moment/index.vue
  63. 0 0
      packages/app/src/pages-sub/home/offline-activity/cycling-rankings/index.vue
  64. 13 11
      packages/app/src/pages-sub/home/offline-activity/index.vue
  65. 147 0
      packages/app/src/pages-sub/home/offline-activity/list/index.vue
  66. 1 1
      packages/app/src/pages-sub/home/schedule/index.vue
  67. 1 1
      packages/app/src/pages-sub/home/spread/case-shooting/index.vue
  68. 0 0
      packages/app/src/pages-sub/home/spread/case-shooting/photographer/index.vue
  69. 0 0
      packages/app/src/pages-sub/home/spread/design-awards/index.vue
  70. 3 3
      packages/app/src/pages-sub/home/spread/index.vue
  71. 218 0
      packages/app/src/pages-sub/home/spread/product-detail/index.vue
  72. 1 1
      packages/app/src/pages-sub/home/spread/wx-agent-operation/index.vue
  73. 1 1
      packages/app/src/pages-sub/home/study-tour/components/register-card.vue
  74. 1 1
      packages/app/src/pages-sub/home/study-tour/components/study-tour-card.vue
  75. 1 1
      packages/app/src/pages-sub/home/study-tour/components/time-line.vue
  76. 0 0
      packages/app/src/pages-sub/home/study-tour/detail.vue
  77. 13 11
      packages/app/src/pages-sub/home/study-tour/index.vue
  78. 0 0
      packages/app/src/pages-sub/home/study-tour/list.vue
  79. 0 0
      packages/app/src/pages-sub/login/index.vue
  80. 1 1
      packages/app/src/pages-sub/mine/agents/index.vue
  81. 2 2
      packages/app/src/pages-sub/mine/authentication/index.vue
  82. 0 0
      packages/app/src/pages-sub/mine/authentication/submit/success/index.vue
  83. 88 0
      packages/app/src/pages-sub/mine/components/coupon-card.vue
  84. 90 0
      packages/app/src/pages-sub/mine/components/coupon-record.vue
  85. 106 0
      packages/app/src/pages-sub/mine/components/coupons-selector.vue
  86. 261 0
      packages/app/src/pages-sub/mine/components/message-card.vue
  87. 151 0
      packages/app/src/pages-sub/mine/components/tasks-card.vue
  88. 0 0
      packages/app/src/pages-sub/mine/convention/index.vue
  89. 1 1
      packages/app/src/pages-sub/mine/coupons/index.vue
  90. 0 0
      packages/app/src/pages-sub/mine/homepage/channels/index.vue
  91. 1 1
      packages/app/src/pages-sub/mine/homepage/consult/index.vue
  92. 0 0
      packages/app/src/pages-sub/mine/homepage/consult/success/index.vue
  93. 0 0
      packages/app/src/pages-sub/mine/homepage/edit/index.vue
  94. 6 6
      packages/app/src/pages-sub/mine/homepage/index.vue
  95. 5 5
      packages/app/src/pages-sub/mine/homepage/qr-code/index.vue
  96. 203 0
      packages/app/src/pages-sub/mine/homepage/statistics/index.vue
  97. 0 0
      packages/app/src/pages-sub/mine/honors/detail/collection.vue
  98. 1 1
      packages/app/src/pages-sub/mine/honors/detail/index.vue
  99. 3 3
      packages/app/src/pages-sub/mine/honors/index.vue
  100. 0 0
      packages/app/src/pages-sub/mine/honors/leaderboard/index.vue

+ 1 - 4
package.json

@@ -8,12 +8,9 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
-    "wot-design-uni": "1.5.1"
+    "wot-design-uni": "1.3.13"
   },
   "resolutions": {
     "bin-wrapper": "npm:bin-wrapper-china"
-  },
-  "devDependencies": {
-    "@types/qs": "^6.9.17"
   }
 }

+ 3 - 0
packages/app/manifest.config.ts

@@ -115,6 +115,9 @@ export default defineManifestConfig({
       urlCheck: false,
     },
     usingComponents: true,
+	optimization:{
+		subPackages:true
+	}
     // __usePrivacyCheck__: true,
   },
   'mp-alipay': {

+ 13 - 0
packages/app/package-lock.json

@@ -0,0 +1,13 @@
+{
+  "name": "@designer-hub/app",
+  "version": "2.4.3",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "pnpm": {
+      "version": "9.15.0",
+      "resolved": "https://registry.npmmirror.com/pnpm/-/pnpm-9.15.0.tgz",
+      "integrity": "sha512-duI3l2CkMo7EQVgVvNZije5yevN3mqpMkU45RBVsQpmSGon5djge4QfUHxLPpLZmgcqccY8GaPoIMe1MbYulbA=="
+    }
+  }
+}

+ 481 - 9
packages/app/pages.config.ts

@@ -48,21 +48,493 @@ export default defineUniPages({
     current: -1,
     list: [
       { name: '设计游学', path: 'pages/index/study-tour/index' },
-      { name: '登录', path: 'pages/login/index' },
-      { name: '开发登录', path: 'pages/login/index', query: 'type=test' },
+      { name: '登录', path: 'pages-sub/login/index' },
+      { name: '开发登录', path: 'pages-sub/login/index', query: 'type=test' },
       { name: '我的', path: 'pages/mine/index' },
-      { name: '设计师认证', path: 'pages/mine/authentication/index' },
-      { name: '设计师认证提交成功', path: 'pages/mine/authentication/submit/success/index' },
-      { name: '设计师个人主页', path: 'pages/mine/homepage/index' },
+      { name: '设计师认证', path: 'pages-sub/mine/authentication/index' },
+      { name: '设计师认证提交成功', path: 'pages-sub/mine/authentication/submit/success/index' },
+      { name: '设计师个人主页', path: 'pages-sub/mine/homepage/index' },
       {
         name: '确认订单',
-        path: '/pages/home/mall/confirm-order/index',
+        path: '/pages-sub/home/mall/confirm-order/index',
         query:
           'data={"isShoppingCart":1,"userId":287,"list":[{"orderNo":"241030170642FX00009","productId":"67131ee4e4b06312aac7e0e9","productName":null,"points":123,"nums":1,"orderImgUrl":"https://image.zhuchaohui.com/zhucaohui/8e5ed57d8a1c8826c9cadb01d2ee39f584c6af1c0269f82c72d60c5461b5f790.png"},{"orderNo":"241030170642FX00010","productId":"67208f37d5c1cec120ffcaae","productName":null,"points":30,"nums":3,"orderImgUrl":"https://image.zhuchaohui.com/zhucaohui/8a4db4e05845032124460e1eeda0a9f2419dd1014947e3f26652da1fa1cc4b54.jpeg"}],"couponList":[],"totalsPoints":213,"totalsCouponPoints":0,"totalsCurrPoints":0}',
       },
-      { name: '商品兑换成功', path: '/pages/home/mall/purchased/success/index' },
-      { name: '购物车', path: '/pages/home/mall/shopping-cart/index' },
-      { name: '支付成功', path: '/pages/mine/scan/pay/success/index' },
+      { name: '商品兑换成功', path: '/pages-sub/home/mall/purchased/success/index' },
+      { name: '购物车', path: '/pages-sub/home/mall/shopping-cart/index' },
+      { name: '支付成功', path: '/pages-sub/mine/scan/pay/success/index' },
     ],
   },
+  subPackages:[
+	  {
+		  root:"pages-sub",
+		  pages:[
+				{
+				  "path": "home/about/index",
+				  "type": "page",
+				  "style": {
+					"navigationStyle": "custom",
+					"navigationBarTitleText": "1分钟快速了解筑巢荟"
+				  }
+				},
+				{
+				  "path": "home/classmates/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "同学荟",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/classmates-detail/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "详情",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/content/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "详情",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/mall/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "品质商城",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/moment/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "详情",
+					"navigationBarBackgroundColor": "#fff",
+					"navigationStyle": "custom"
+				  }
+				},
+				{
+				  "path": "home/offline-activity/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "线下活动",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/schedule/index",
+				  "type": "page",
+				  "style": {
+					"navigationStyle": "custom",
+					"navigationBarTitleText": "游学日程"
+				  }
+				},
+				{
+				  "path": "home/spread/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "设计传播",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/study-tour/detail",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "游学计划",
+					"navigationBarBackgroundColor": "#fff",
+					"navigationStyle": "custom"
+				  }
+				},
+				{
+				  "path": "home/study-tour/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "设计游学",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/study-tour/list",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "游学计划",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/activity/detail/index",
+				  "type": "page",
+				  "style": {
+					"navigationStyle": "custom"
+				  }
+				},
+				{
+				  "path": "home/activity/images/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "活动图片",
+					"navigationBarBackgroundColor": "#ffffff"
+				  }
+				},
+				{
+				  "path": "home/mall/confirm-order/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "确认订单",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/mall/detail/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "品质商城",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/mall/shopping-cart/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "购物车",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/offline-activity/cycling-rankings/index",
+				  "type": "page",
+				  "style": {
+					"navigationStyle": "custom"
+				  }
+				},
+				{
+				  "path": "home/offline-activity/list/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "线下活动",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/spread/case-shooting/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "案例拍摄",
+					"navigationBarBackgroundColor": "#ffffff"
+				  }
+				},
+				{
+				  "path": "home/spread/design-awards/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "设计奖项",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/spread/product-detail/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "",
+					"navigationBarBackgroundColor": "#fff"
+				  }
+				},
+				{
+				  "path": "home/spread/wx-agent-operation/index",
+				  "type": "page",
+				  "style": {
+					"navigationBarTitleText": "微信代运营",
+					"navigationBarBackgroundColor": "#ffffff"
+				  }
+				},
+				 {
+					  "path": "home/mall/purchased/success/index",
+					  "type": "page",
+					  "style": {
+						"navigationBarTitleText": "",
+						"navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "home/spread/case-shooting/photographer/index",
+					  "type": "page",
+					  "style": {
+						"navigationBarTitleText": "案例拍摄",
+						"navigationBarBackgroundColor": "#ffffff"
+					  }
+					},
+					{
+					  "path": "about/about",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "关于"
+					  }
+					},
+					{
+					  "path": "login/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "登录"
+					  }
+					},
+					{
+					  "path": "common/content-html/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "common/webview/index",
+					  "type": "page"
+					},
+					{
+					  "path": "publish/moment/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "个人动态",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "publish/tags/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "添加标签",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "common/status/success/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/agents/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "客服",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/authentication/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "设计师认证",
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/convention/index",
+					  "type": "page",
+					  "style": {
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/coupons/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "优惠券包",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/homepage/index",
+					  "type": "page",
+					  "style": {
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/honors/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "我的荣誉",
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/invite/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "邀请设计师",
+					    "navigationBarBackgroundColor": "#fff",
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/levels/index",
+					  "type": "page",
+					  "style": {
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/orders/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "我的订单",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/points/index",
+					  "type": "page",
+					  "style": {
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/setting/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "个人设置"
+					  }
+					},
+					{
+					  "path": "mine/homepage/channels/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "关联视频号",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/homepage/consult/index",
+					  "type": "page",
+					  "style": {
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/homepage/edit/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "编辑",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/homepage/qr-code/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "个人码",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/homepage/statistics/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "主页数据",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/honors/detail/collection",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "我的典藏",
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/honors/detail/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "我的荣誉",
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/honors/leaderboard/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "获取榜单",
+					    "navigationStyle": "custom"
+					  }
+					},
+					{
+					  "path": "mine/levels/rules/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "等级规则",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/orders/code/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "兑换码",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/orders/detail/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "订单详情",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/scan/result/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "扫码结果",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/setting/mobile/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "手机号"
+					  }
+					},
+					{
+					  "path": "mine/authentication/submit/success/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "提交成功"
+					  }
+					},
+					{
+					  "path": "mine/homepage/consult/success/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "提交成功"
+					  }
+					},
+					{
+					  "path": "mine/scan/pay/success/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "",
+					    "navigationBarBackgroundColor": "#fff"
+					  }
+					},
+					{
+					  "path": "mine/setting/mobile/modify/index",
+					  "type": "page",
+					  "style": {
+					    "navigationBarTitleText": "修改手机号"
+					  }
+					}
+			]
+	  }
+  ]
 })

+ 2 - 2
packages/app/src/components/hot-activity-item.vue

@@ -19,7 +19,7 @@ const { listItemButtonText, statusText, status, difference, startAt, endAt, refr
 <template>
   <view
     class="relative w-full h-full box-border flex m-a"
-    @click="router.push(`/pages/home/activity/detail/index?id=${options?.id}&type=${type}`)"
+    @click="router.push(`/pages-sub/home/activity/detail/index?id=${options?.id}&type=${type}`)"
   >
     <view class="w-full h-full flex flex-col justify-between pt-14 box-border px-3.5">
       <!-- <view class="flex"></view> -->
@@ -65,7 +65,7 @@ const { listItemButtonText, statusText, status, difference, startAt, endAt, refr
         ></ActivityCountDown>
         <div
           @click.stop="
-            router.push(`/pages/home/activity/detail/index?id=${options?.id}&type=${type}`)
+            router.push(`/pages-sub/home/activity/detail/index?id=${options?.id}&type=${type}`)
           "
         >
           <ButtonEvo size="md">

+ 24 - 16
packages/app/src/components/moment-item.vue

@@ -20,6 +20,7 @@ const props = withDefaults(
     options: CircleRes
     isOwn?: boolean
     isShared?: boolean
+	dict?:Object
   }>(),
   {},
 )
@@ -32,8 +33,8 @@ const router = useRouter()
 const { features, clickByPermission } = usePermissions()
 const memberLevelsStore = useMemberLevelsStore()
 const { getMemberLevelLogo, getMemberAvatarFrame } = memberLevelsStore
-const dictStore = useDictStore()
-const { getOptionLabel } = dictStore
+// const dictStore = useDictStore()
+// const { getOptionLabel } = dictStore
 const imgClass = ref('')
 // const isVideo = ref(false)
 const isVideo = computed(
@@ -41,12 +42,21 @@ const isVideo = computed(
 )
 const toDetail = () => {
   uni.navigateTo({
-    url: `/pages/home/moment/index?${stringify({ id: props.options.id })}${props.isShared ? '&isShared=true' : ''}`,
+    url: `/pages-sub/home/moment/index?${stringify({ id: props.options.id })}${props.isShared ? '&isShared=true' : ''}`,
   })
 }
 const handleDelete = async () => {
   emits('delete', props.options.id)
 }
+
+const dictLabelChange = (dictArr:any, value:any) => {
+	for(let i in dictArr){
+		if(dictArr[i].value === value){
+			return dictArr[i].label
+		}
+	}
+}
+
 onMounted(async () => {
   if (
     props.options.circleType === '1' &&
@@ -80,8 +90,8 @@ onMounted(async () => {
           @click.stop="
             features.toDesignerHomePage &&
             ['1', '2'].includes(options?.circleType) &&
-            currRoute().path !== '/pages/mine/homepage/index' &&
-            router.push(`/pages/mine/homepage/index?id=${options.stylistId}`)
+            currRoute().path !== '/pages-sub/mine/homepage/index' &&
+            router.push(`/pages-sub/mine/homepage/index?id=${options.stylistId}`)
           "
         >
           <wd-img
@@ -161,23 +171,21 @@ onMounted(async () => {
       </div>
       <view class="text-[rgba(0,0,0,0.85)] text-4 font-400 my-1 flex items-center">
         <template v-if="options.circleType === '2'">
-          <!--          <span>-->
-          <!--            {{ getOptionLabel(DictType.circleSpaceType, options.spaceType) }}-->
-          <!--          </span>-->
-          <!--          <div class="mx-2 h-3.5 w-[1.5px] bg-black/40"></div>-->
-          <!--          <span>-->
-          <!--            {{ getOptionLabel(DictType.memberDesignStyle, options.designStyle) }}-->
-          <!--          </span>-->
-          <!--          <div class="mx-2 h-3.5 w-[1.5px] bg-black/40"></div>-->
-          <!--          <span>{{ options.caseName }}</span>-->
           <div class="w-full mt-4 flex items-center justify-between text-black/40 text-sm">
-            <div class="font-normal font-['PingFang_SC']">
+            <!-- <div class="font-normal font-['PingFang_SC']">
               类别:{{ getOptionLabel(DictType.circleSpaceType, options?.spaceType) }}
             </div>
             |
             <div class="text-black/40 text-sm font-normal font-['PingFang_SC']">
               风格:{{ getOptionLabel(DictType.memberDesignStyle, options.designStyle) }}
-            </div>
+            </div> -->
+			<div class="font-normal font-['PingFang_SC']">
+			  类别:{{ dictLabelChange(dict?.spaceType, options?.spaceType) }}
+			</div>
+			|
+			<div class="text-black/40 text-sm font-normal font-['PingFang_SC']">
+			  风格:{{ dictLabelChange(dict?.designStyle, options.designStyle) }}
+			</div>
             |
             <div class="text-black/40 text-sm font-normal font-['PingFang_SC']">
               面积:{{ options.spaceExtent }}

+ 1 - 1
packages/app/src/components/swiper-evo.vue

@@ -9,7 +9,7 @@ const handleSwiperChange = async ({ detail: { current } }) => {
   <swiper class="w-full h-full" autoplay :current="modelValue" @change="handleSwiperChange">
     <template v-for="(it, i) in items" :key="i">
       <swiper-item>
-        <div class="w-full h-full"><slot :item="it"></slot></div>
+        <div class="w-full h-full swiper-item"><slot :item="it"></slot></div>
       </swiper-item>
     </template>
   </swiper>

+ 20 - 0
packages/app/src/composables/honor-dialog.ts

@@ -0,0 +1,20 @@
+import { inject, InjectionKey } from 'vue'
+export interface DialogShowOptions {
+  title: string
+  content: string
+  path: string
+  image: string
+}
+export const HonorDialogSymbol: InjectionKey<{
+  show: (options: DialogShowOptions) => void
+}> = Symbol.for('HonorDialogContext')
+export const useHonorDialog = () => {
+  const honorDialog = inject(HonorDialogSymbol)
+  // if (!honorDialog) {
+  //   throw new Error('useHonorDialog must be used inside setup()')
+  // }
+  const show = computed(() => honorDialog?.show)
+  return {
+    show,
+  }
+}

+ 11 - 11
packages/app/src/composables/permissions.ts

@@ -7,7 +7,7 @@ export const usePermissions = () => {
   const userStore = useUserStore()
   const { isLogined, isDesigner, userInfo } = storeToRefs(userStore)
   const routes = [
-    { path: '/pages/mine/homepage/index', meta: { canNotLogin: false, canNotDesigner: true } },
+    { path: '/pages-sub/mine/homepage/index', meta: { canNotLogin: false, canNotDesigner: true } },
     {
       path: '/pages/material/mini-class/index',
       meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
@@ -17,7 +17,7 @@ export const usePermissions = () => {
       meta: { canNotLogin: false, canNotDesigner: false, toLogin: true },
     },
     {
-      path: '/pages/publish/moment/index',
+      path: '/pages-sub/publish/moment/index',
       meta: { canNotLogin: false, canNotDesigner: false, toLogin: true },
     },
     {
@@ -25,31 +25,31 @@ export const usePermissions = () => {
       meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
     },
     {
-      path: '/pages/mine/setting/index',
+      path: '/pages-sub/mine/setting/index',
       meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
     },
     {
-      path: '/pages/mine/homepage/statistics/index',
+      path: '/pages-sub/mine/homepage/statistics/index',
       meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
     },
     {
-      path: '/pages/mine/points/index',
+      path: '/pages-sub/mine/points/index',
       meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
     },
     {
-      path: '/pages/mine/coupons/index',
+      path: '/pages-sub/mine/coupons/index',
       meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
     },
     {
-      path: '/pages/mine/orders/index',
+      path: '/pages-sub/mine/orders/index',
       meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
     },
     // {
-    //   path: '/pages/mine/agents/index',
+    //   path: '/pages-sub/mine/agents/index',
     //   meta: { canNotLogin: false, canNotDesigner: true, toLogin: true },
     // },
     {
-      path: '/pages/mine/invite/index',
+      path: '/pages-sub/mine/invite/index',
       meta: { canNotLogin: false, canNotDesigner: false, toLogin: true },
     },
     {
@@ -115,14 +115,14 @@ export const usePermissions = () => {
     if (feature) {
       if (!feature.meta.canNotLogin && !isLogined.value) {
         uni.showToast({ title: messages.components.toast.pleaseLogin, icon: 'none' })
-        useRouter().push('/pages/login/index')
+        useRouter().push('/pages-sub/login/index')
         return
       }
       if (!feature.meta.canNotDesigner && !isDesigner.value) {
         uni
           .showToast({ title: messages.components.toast.pleaseAuthentication, icon: 'none' })
           .then()
-        useRouter().push('/pages/mine/authentication/index').then()
+        useRouter().push('/pages-sub/mine/authentication/index').then()
         return
       }
       if (feature.meta.minLevel && userInfo.value.level.level < feature.meta.minLevel) {

+ 4 - 4
packages/app/src/composables/share.ts

@@ -10,10 +10,10 @@ export const useShare = () => {
     //   if (target.dataset.type === 'homepage') {
     //     res.title = `${userInfo.value.nickname}: “${designerInfo.value.designDesc}”`
     //     res.imageUrl = designerInfo.value?.sharePageUrl
-    //     res.path = `/pages/mine/homepage/index?id=${id.value}&isShared=true`
+    //     res.path = `/pages-sub/mine/homepage/index?id=${id.value}&isShared=true`
     //   } else {
     //     await shareCircle(target.dataset.options.id)
-    //     res.path = `/pages/home/moment/index?id=${target.dataset.options.id}&isShared=true`
+    //     res.path = `/pages-sub/home/moment/index?id=${target.dataset.options.id}&isShared=true`
     //     res.imageUrl = target.dataset.options.bannerUrls[0]
     //     res.title = `${target.dataset.options.stylistName}: ${target.dataset.options.circleDesc}`
     //   }
@@ -21,7 +21,7 @@ export const useShare = () => {
     // if (from === 'menu') {
     //   res.title = `${userInfo.value.nickname}: “${designerInfo.value.designDesc}”`
     //   res.imageUrl = designerInfo.value?.sharePageUrl
-    //   res.path = `/pages/mine/homepage/index?id=${id.value}&isShared=true`
+    //   res.path = `/pages-sub/mine/homepage/index?id=${id.value}&isShared=true`
     // }
     // return res
 
@@ -41,7 +41,7 @@ export const useShare = () => {
         if (['1', '2'].includes(target.dataset.options.circleType)) {
           await shareCircle(target.dataset.options.id)
         }
-        res.path = `/pages/home/moment/index?id=${target.dataset.options.id}&isShared=true`
+        res.path = `/pages-sub/home/moment/index?id=${target.dataset.options.id}&isShared=true`
         res.imageUrl = target.dataset.options.bannerUrls[0]
         res.title = `${target.dataset.options.stylistName}: ${target.dataset.options.circleDesc}`
       }

+ 2 - 2
packages/app/src/core/libs/actions.ts

@@ -37,10 +37,10 @@ export const handleUpvoteClick = async (
 export const handleShareClick = () => {
   const userStore = useUserStore()
   if (!userStore.isLogined) {
-    return useRouter().push('/pages/login/index')
+    return useRouter().push('/pages-sub/login/index')
   }
   if (!userStore.isDesigner) {
-    return useRouter().push('/pages/mine/authentication/index')
+    return useRouter().push('/pages-sub/mine/authentication/index')
   }
   if (userStore.userInfo.level?.level < 2) {
     toast('请先升级为设计师')

+ 17 - 17
packages/app/src/core/libs/message-types.ts

@@ -39,36 +39,36 @@
 //     ACTIVE_CLICK_COMMENT_MESSAGE(35, "点赞评论"),
 //     ACTIVE_SHARE_MESSAGE(36, "分享");
 export const messageTypes = [
-  { subType: 1, desc: '欢迎加入', path: '/pages/home/about/index' },
-  { subType: 2, desc: '认证驳回', path: '/pages/mine/authentication/index' },
+  { subType: 1, desc: '欢迎加入', path: '/pages-sub/home/about/index' },
+  { subType: 2, desc: '认证驳回', path: '/pages-sub/mine/authentication/index' },
   { subType: 3, desc: '材料商入住', path: '/pages/material/detail/index?id=0' },
   { subType: 4, desc: '数据仓驾驶' },
   { subType: 5, desc: '消息通知', path: '/pages/messages/detail/index' },
   { subType: 6, desc: '客户预约' },
   { subType: 7, desc: '分享数据' },
-  { subType: 8, desc: '会员变动通知', path: '/pages/mine/levels/index' },
+  { subType: 8, desc: '会员变动通知', path: '/pages-sub/mine/levels/index' },
   {
     subType: 9,
     desc: '开始报名',
-    path: '/pages/home/activity/detail/index?id=29898&type=studyTour',
+    path: '/pages-sub/home/activity/detail/index?id=29898&type=studyTour',
   },
   { subType: 10, desc: '账号恢复通知' },
   { subType: 11, desc: '账号冻结通知' },
-  { subType: 12, desc: '会员升级', path: '/pages/mine/levels/index' },
-  { subType: 13, desc: '会员降级', path: '/pages/mine/levels/index' },
-  { subType: 14, desc: '优惠卷获取', path: '/pages/mine/coupons/index' },
-  { subType: 15, desc: '优惠卷过期', path: '/pages/mine/coupons/index' },
-  { subType: 16, desc: '证书获取', path: '/pages/mine/honors/index' },
-  { subType: 17, desc: '徽章获取', path: '/pages/mine/honors/index' },
+  { subType: 12, desc: '会员升级', path: '/pages-sub/mine/levels/index' },
+  { subType: 13, desc: '会员降级', path: '/pages-sub/mine/levels/index' },
+  { subType: 14, desc: '优惠卷获取', path: '/pages-sub/mine/coupons/index' },
+  { subType: 15, desc: '优惠卷过期', path: '/pages-sub/mine/coupons/index' },
+  { subType: 16, desc: '证书获取', path: '/pages-sub/mine/honors/index' },
+  { subType: 17, desc: '徽章获取', path: '/pages-sub/mine/honors/index' },
   {
     subType: 18,
     desc: '报名游学',
-    path: '/pages/home/activity/detail/index?id=29898&type=studyTour',
+    path: '/pages-sub/home/activity/detail/index?id=29898&type=studyTour',
   },
   {
     subType: 19,
     desc: '报名活动',
-    path: '/pages/home/activity/detail/index?id=29898&type=studyTour',
+    path: '/pages-sub/home/activity/detail/index?id=29898&type=studyTour',
   },
   { subType: 20, desc: '兑换商品' },
   { subType: 21, desc: '后台增加' },
@@ -82,11 +82,11 @@ export const messageTypes = [
   { subType: 29, desc: '取消游学/报名' },
   { subType: 30, desc: '取消订单' },
   { subType: 31, desc: '积分订单确认' },
-  { subType: 32, desc: '评论', path: '/pages/home/moment/index' },
-  { subType: 33, desc: '回复', path: '/pages/home/moment/index' },
-  { subType: 34, desc: '点赞圈子', path: '/pages/home/moment/index' },
-  { subType: 35, desc: '点赞评论', path: '/pages/home/moment/index' },
-  { subType: 36, desc: '分享', path: '/pages/home/moment/index' },
+  { subType: 32, desc: '评论', path: '/pages-sub/home/moment/index' },
+  { subType: 33, desc: '回复', path: '/pages-sub/home/moment/index' },
+  { subType: 34, desc: '点赞圈子', path: '/pages-sub/home/moment/index' },
+  { subType: 35, desc: '点赞评论', path: '/pages-sub/home/moment/index' },
+  { subType: 36, desc: '分享', path: '/pages-sub/home/moment/index' },
 ]
 export const getMessageType = (subType: number) =>
   messageTypes.find((item) => item.subType === subType)

+ 6 - 5
packages/app/src/core/libs/requests.ts

@@ -934,6 +934,11 @@ export const updateHonorPopUp = (query: { bizId: string; bizType: string }) =>
 export const getBadges = (query = {}) =>
   httpGet<{ [key: string]: Badge[] }>('/app-api/member/stylist-honor/get-badge-list', query)
 /**
+* 获取证书列表
+*/
+export const getCertificates = (query = {}) =>
+httpGet<Certificate[]>('/app-api/member/stylist-honor/get-certificate-list', query)
+/**
  * 获取典藏徽章列表
  * */
 export const getListCollectionBadge = (query = {}) =>
@@ -953,11 +958,7 @@ export const getCollectionBadge = (query = {}) =>
  */
 export const getOwnBadges = (query = {}) =>
   httpGet<Badge[]>('/app-api/member/stylist-honor/getConferBadgeList', query)
-/**
- * 获取证书列表
- */
-export const getCertificates = (query = {}) =>
-  httpGet<Certificate[]>('/app-api/member/stylist-honor/get-certificate-list', query)
+
 /**
  * 获取荣誉统计
  */

+ 1 - 1
packages/app/src/core/utils/common.ts

@@ -196,6 +196,6 @@ export const formatDuration = (duration: number) => {
 }
 export const toContentHtml = async (option: { title: string; type: AgreementType }) => {
   await uni.navigateTo({
-    url: `/pages/common/content-html/index?title=${option.title}&type=${option.type}`,
+    url: `/pages-sub/common/content-html/index?title=${option.title}&type=${option.type}`,
   })
 }

+ 2 - 2
packages/app/src/core/utils/router.ts

@@ -13,12 +13,12 @@ export const useRouter = () => {
         uni.showToast({ title: '暂无权限', icon: 'none' })
       }
       if (route.meta.toLogin) {
-        push('/pages/login/index')
+        push('/pages-sub/login/index')
       }
       return false
     }
     if (route && !route.meta.canNotDesigner && !isDesigner.value) {
-      return push('/pages/mine/authentication/index')
+      return push('/pages-sub/mine/authentication/index')
     }
     if (switchTab) {
       uni.switchTab({ url })

+ 1 - 1
packages/app/src/interceptors/route.ts

@@ -8,7 +8,7 @@ import { useUserStore } from '@/store'
 import { getNeedLoginPages, needLoginPages as _needLoginPages } from '@/utils'
 
 // TODO Check
-const loginRoute = '/pages/login/index'
+const loginRoute = '/pages-sub/login/index'
 
 const isLogined = () => {
   const userStore = useUserStore()

+ 5 - 5
packages/app/src/layouts/tabbar.vue

@@ -15,7 +15,7 @@ import {
 import { currRoute } from '../utils'
 import { defaultThemeVars } from '../core/themes/default'
 import { useRouter } from '../core/utils/router'
-import HonorDialog from "@/pages/common/components/honor-dialog/honor-dialog.vue";
+import HonorDialog from "@/pages/home/components/honor-dialog/honor-dialog.vue";
 
 const router = useRouter()
 const publishState = ref(false)
@@ -36,7 +36,7 @@ const items = [
     title: '发布',
     iconPath: publish,
     selectedIconPath: publish,
-    path: '/pages/publish/index',
+    path: '/pages-sub/publish/index',
     hiddenTitle: true,
   },
   {
@@ -53,7 +53,7 @@ const items = [
   },
 ]
 const handleTabbarItemClick = (path: string) => {
-  if (path === '/pages/publish/index') {
+  if (path === '/pages-sub/publish/index') {
     publishState.value = true
     return
   }
@@ -61,11 +61,11 @@ const handleTabbarItemClick = (path: string) => {
   // uni.switchTab({ url: path })
 }
 const toPublishMoment = () => {
-  router.push('/pages/publish/moment/index?circleType=1')
+  router.push('/pages-sub/publish/moment/index?circleType=1')
   publishState.value = false
 }
 const toPublishCase = () => {
-  router.push('/pages/publish/moment/index?circleType=2')
+  router.push('/pages-sub/publish/moment/index?circleType=2')
   publishState.value = false
 }
 </script>

+ 5 - 2
packages/app/src/manifest.json

@@ -1,6 +1,6 @@
 {
   "name": "筑巢荟",
-  "appid": "H57F2ACE4",
+  "appid": "__UNI__BA668E1",
   "description": "",
   "versionName": "1.0.0",
   "versionCode": "100",
@@ -87,7 +87,10 @@
     "setting": {
       "urlCheck": false
     },
-    "usingComponents": true
+    "usingComponents": true,
+    "optimization": {
+      "subPackages": true
+    }
   },
   "mp-alipay": {
     "usingComponents": true,

+ 0 - 0
packages/app/src/pages/about/about.vue → packages/app/src/pages-sub/about/about.vue


+ 0 - 0
packages/app/src/pages/about/components/request.vue → packages/app/src/pages-sub/about/components/request.vue


+ 0 - 0
packages/app/src/pages/about/components/upload.vue → packages/app/src/pages-sub/about/components/upload.vue


+ 0 - 0
packages/app/src/pages/common/components/avatar.vue → packages/app/src/pages-sub/common/components/avatar.vue


+ 0 - 0
packages/app/src/pages/common/components/coupon-card.vue → packages/app/src/pages-sub/common/components/coupon-card.vue


+ 0 - 0
packages/app/src/pages/common/components/coupon-record.vue → packages/app/src/pages-sub/common/components/coupon-record.vue


+ 0 - 0
packages/app/src/pages/common/components/coupons-selector.vue → packages/app/src/pages-sub/common/components/coupons-selector.vue


+ 82 - 0
packages/app/src/pages-sub/common/components/honor-dialog.vue

@@ -0,0 +1,82 @@
+<script setup lang="ts">
+import { close } from '../../../core/libs/svgs'
+import { DialogShowOptions, HonorDialogSymbol } from '../../../composables/honor-dialog'
+import earnBadgeTitle from '@designer-hub/assets/src/libs/assets/earnBadgeTitle'
+import radiation from '@designer-hub/assets/src/libs/assets/radiation'
+import { NetImages } from '../../../core/libs/net-images'
+import { ConfigProviderThemeVars } from 'wot-design-uni'
+
+const modelValue = defineModel({ default: false, type: Boolean })
+const themeVars: ConfigProviderThemeVars = {
+  overlayBg: 'rgba(0,0,0,0.85)',
+}
+const title = ref('东方研习营')
+const content = ref('获得东方研习营游学徽章')
+const path = ref('')
+const src = ref(
+  'https://image.zhuchaohui.com/zhucaohui/e104215c64d39e4a0f8676c48b8e7221c891eade1c8d7f02b2a7f0be862e3f76.png',
+)
+const show = (options: DialogShowOptions) => {
+  title.value = options.title
+  content.value = options.content
+  path.value = options.path
+  src.value = options.image
+  modelValue.value = true
+}
+provide(HonorDialogSymbol, { show })
+</script>
+<template>
+  <wd-config-provider :themeVars="themeVars">
+    <wd-popup v-model="modelValue" custom-class="bg-transparent! bg-[#f6f6f6]!">
+      <div class="flex flex-col items-center relative">
+        <wd-img width="60vw" mode="widthFix" :src="earnBadgeTitle"></wd-img>
+        <div class="w-[100vw] h-[68vw] pt-2 flex">
+          <div class="w-100vw h-100vw absolute left-0 right-0 top--8">
+            <wd-img
+              custom-class="absolute! vertical-bottom"
+              width="68%"
+              height="68%"
+              :src="radiation"
+            ></wd-img>
+            <wd-img
+              custom-class="absolute! left-16 top-4 vertical-bottom"
+              width="58vw"
+              mode="widthFix"
+              :src="NetImages.Stars"
+            ></wd-img>
+            <wd-img
+              custom-class="absolute! ma-a top-50% left-50% translate-[-50%,-50%]  vertical-bottom blur-60"
+              width="40vw"
+              mode="widthFix"
+              :src="src"
+            ></wd-img>
+            <wd-img
+              custom-class="absolute! ma-a top-50% left-50% translate-[-50%,-50%]  vertical-bottom"
+              width="40vw"
+              mode="widthFix"
+              :src="src"
+            ></wd-img>
+          </div>
+        </div>
+        <div class="text-center">
+          <div class="text-white text-2xl font-normal font-['PingFang_SC'] uppercase">
+            {{ title }}
+          </div>
+          <div class="mt-2 text-[#9f9b94] text-base font-normal font-['PingFang_SC'] uppercase">
+            {{ content }}
+          </div>
+        </div>
+        <div
+          class="my-10 w-[155px] px-5 py-2.5 rounded-full border border-solid border-[#c8beab] justify-center items-center gap-1 inline-flex"
+        >
+          <div
+            class="text-center text-[#c7bdab] text-base font-normal font-['PingFang_SC'] leading-normal"
+          >
+            查看奖励
+          </div>
+        </div>
+        <wd-img width="24" height="24" :src="close" @click="modelValue = false"></wd-img>
+      </div>
+    </wd-popup>
+  </wd-config-provider>
+</template>

+ 171 - 0
packages/app/src/pages-sub/common/components/honor-dialog/honor-dialog.vue

@@ -0,0 +1,171 @@
+<script setup lang="ts">
+import { close } from '../../../../core/libs/svgs'
+import { HonorDialogOptions, HonorDialogSymbol, HonorDialogType } from '.'
+import earnBadgeTitle from '@designer-hub/assets/src/libs/assets/earnBadgeTitle'
+import radiation from '@designer-hub/assets/src/libs/assets/radiation'
+import { NetImages } from '@/core/libs/net-images'
+import { ConfigProviderThemeVars } from 'wot-design-uni'
+import { useRouter } from '@/core/utils/router'
+import earnCertificate from '@designer-hub/assets/src/libs/assets/earnCertificate'
+import envelopeFront from '@designer-hub/assets/src/libs/assets/envelopeFront'
+import envelopeBack from '@designer-hub/assets/src/libs/assets/envelopeBack'
+import ribbonTl from '@designer-hub/assets/src/libs/assets/ribbonTl'
+import ribbonBr from '@designer-hub/assets/src/libs/assets/ribbonBr'
+
+const dialogOption = inject(HonorDialogSymbol, ref<HonorDialogOptions>({}))
+const { push } = useRouter()
+const lazyRender = ref<boolean>(true)
+const modelValue = defineModel({ default: false, type: Boolean })
+const themeVars: ConfigProviderThemeVars = {
+  overlayBg: 'rgba(0,0,0,0.85)',
+}
+const title = ref('东方研习营')
+const content = ref('获得东方研习营游学徽章')
+const path = ref('')
+const src = ref(
+  'https://image.zhuchaohui.com/zhucaohui/e104215c64d39e4a0f8676c48b8e7221c891eade1c8d7f02b2a7f0be862e3f76.png',
+)
+const isBadge = computed(() => dialogOption.value?.type === HonorDialogType.Badge)
+const isCertificate = computed(() => dialogOption.value?.type === HonorDialogType.Certificate)
+const reset = (option) => {
+  if (option) {
+    modelValue.value = option.show
+    lazyRender.value = option.lazyRender
+    title.value = option.title || '东方研习营'
+    content.value = option.content || '获得东方研习营游学徽章'
+    path.value = option.path || ''
+    src.value = option.image || src.value
+  }
+}
+const jumpTo = () => {
+  if (dialogOption.value?.type && dialogOption.value?.type === 'certificate') {
+    push('/pages-sub/mine/honors/index?active=certificate')
+  }
+  if (dialogOption.value?.type && dialogOption.value?.type === 'badge') {
+    push('/pages-sub/mine/honors/index?active=badge')
+  }
+  modelValue.value = false
+}
+const handleLoad = () => {
+  if (dialogOption.value?.onLoad && typeof dialogOption.value?.onLoad === 'function') {
+    dialogOption.value.onLoad()
+  }
+}
+watch(
+  () => dialogOption.value,
+  (newVal) => {
+	  console.log("1111")
+    reset(newVal)
+  },
+)
+// provide(HonorDialogSymbol, { show })
+</script>
+<template>
+  <wd-config-provider :themeVars="themeVars">
+    <wd-popup v-model="modelValue" :lazy-render="lazyRender" custom-class="bg-transparent! bg-[#f6f6f6]!">
+      <div class="flex flex-col items-center relative">
+        <wd-img width="60vw" mode="widthFix" :src="isBadge ? earnBadgeTitle : earnCertificate"></wd-img>
+        <div v-if="isBadge" class="w-[100vw] h-[68vw] pt-2 flex">
+          <div class="w-100vw h-100vw absolute left-0 right-0 top--8">
+            <wd-img v-if="isBadge"  custom-class="absolute! top-50% left-50% translate-[-50%,-50%] vertical-bottom" width="68%" height="68%" :src="radiation"></wd-img>
+            <wd-img
+              custom-class="absolute! left-16 top-4 vertical-bottom"
+              width="58vw"
+              mode="widthFix"
+              :src="NetImages.Stars"
+            ></wd-img>
+            <wd-img
+              v-if="isBadge"
+              custom-class="absolute! ma-a top-50% left-50% translate-[-50%,-50%]  vertical-bottom blur-60"
+              width="40vw"
+              mode="widthFix"
+              :src="src"
+            ></wd-img>
+            <wd-img
+              v-if="isBadge"
+              custom-class="absolute! ma-a top-50% left-50% translate-[-50%,-50%]  vertical-bottom"
+              width="40vw"
+              mode="widthFix"
+              @load="handleLoad"
+              :src="src"
+            ></wd-img>
+          </div>
+        </div>
+        <div v-if="isCertificate" class="relative mb-16">
+          <wd-img
+            v-if="isCertificate"
+            custom-class="absolute! bottom-0 left-7.5vw vertical-bottom"
+            width="85%"
+            mode="widthFix"
+            :src="envelopeBack"
+          ></wd-img>
+          <wd-img
+            custom-class="absolute! left-12 top--4 vertical-bottom"
+            width="58vw"
+            mode="widthFix"
+            :src="NetImages.Stars"
+          ></wd-img>
+          <div class="w-[100vw] center">
+            <wd-img
+              v-if="isCertificate"
+              custom-class="mt-9.5 mb-22 vertical-bottom"
+              width="80vw"
+              mode="widthFix"
+              @load="handleLoad"
+              :src="src"
+            ></wd-img>
+          </div>
+          <wd-img custom-class="absolute! top-0 left-0" width="114" height="114" :src="ribbonTl" />
+          <wd-img
+            v-if="isCertificate"
+            custom-class="absolute! bottom-0 left-7.5vw vertical-bottom"
+            width="85vw"
+            mode="widthFix"
+            :src="envelopeFront"
+          ></wd-img>
+          <wd-img
+            custom-class="absolute! bottom-0 right-0"
+            width="76"
+            height="56"
+            :src="ribbonBr"
+          />
+          <div class="absolute bottom-0 left-50% translate-[-50%,-50%]">
+            <div
+              class="w-[115.50px] h-[41.16px] bg-gradient-to-r from-[#f2b36f] to-[#ce995c] rounded-[28.68px] flex center"
+              @click="jumpTo"
+            >
+              <div
+                class="w-[110.71px] h-[37.17px] bg-gradient-to-r from-[#f1bf84] to-[#e6c99f] rounded-[28.19px] shadow shadow-inner flex center"
+              >
+                <div class="text-center text-[#242323] text-base font-normal font-['PingFang_SC']">
+                  去查看
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div v-if="isBadge" class="text-center">
+          <div class="text-white text-2xl font-normal font-['PingFang_SC'] uppercase">
+            {{ title }}
+          </div>
+          <div class="mt-2 text-[#9f9b94] text-base font-normal font-['PingFang_SC'] uppercase">
+            {{ content }}
+          </div>
+        </div>
+        <div
+          v-if="isBadge"
+          class="my-10 w-[155px] px-5 py-2.5 rounded-full border border-solid border-[#c8beab] justify-center items-center gap-1 inline-flex"
+        >
+          <div
+            class="text-center text-[#c7bdab] text-base font-normal font-['PingFang_SC'] leading-normal"
+            @click.stop="jumpTo"
+          >
+            查看奖励
+          </div>
+        </div>
+        <wd-img width="24" height="24" :src="close" @click="modelValue = false"></wd-img>
+      </div>
+    </wd-popup>
+  </wd-config-provider>
+</template>

+ 0 - 0
packages/app/src/pages/common/components/honor-dialog/index.ts → packages/app/src/pages-sub/common/components/honor-dialog/index.ts


+ 0 - 0
packages/app/src/pages/common/components/share-action-sheet.vue → packages/app/src/pages-sub/common/components/share-action-sheet.vue


+ 0 - 0
packages/app/src/pages/common/content-html/index.vue → packages/app/src/pages-sub/common/content-html/index.vue


+ 0 - 0
packages/app/src/pages/common/status/success/index.vue → packages/app/src/pages-sub/common/status/success/index.vue


+ 0 - 0
packages/app/src/pages/common/webview/index.vue → packages/app/src/pages-sub/common/webview/index.vue


+ 0 - 20
packages/app/src/pages-sub/demo/index.vue

@@ -1,20 +0,0 @@
-<route lang="json5" type="page">
-{
-  style: { navigationBarTitleText: '分包页面 标题' },
-}
-</route>
-
-<template>
-  <view class="text-center">
-    <view class="m-8">http://localhost:9000/#/pages-sub/demo/index</view>
-    <view class="text-green-500">分包页面demo</view>
-  </view>
-</template>
-
-<script lang="ts" setup>
-// code here
-</script>
-
-<style lang="scss" scoped>
-//
-</style>

+ 0 - 0
packages/app/src/pages/home/about/index.vue → packages/app/src/pages-sub/home/about/index.vue


+ 1 - 1
packages/app/src/pages/home/activity/detail/index.vue → packages/app/src/pages-sub/home/activity/detail/index.vue

@@ -447,7 +447,7 @@ onShareTimeline(() => ({ title: data.value.name, imageUrl: data.value.thumbnailU
       v-if="photos.total"
       class="fixed bottom-30 right-8 bg-[#0cbe7c] w-15 h-15 rounded-full flex flex-col items-center justify-center"
       @click="
-        router.push(`/pages/home/activity/images/index?id=${id}&type=${type}&title=${data.name}`)
+        router.push(`/pages-sub/home/activity/images/index?id=${id}&type=${type}&title=${data.name}`)
       "
     >
       <div>

+ 0 - 0
packages/app/src/pages/home/activity/images/index.vue → packages/app/src/pages-sub/home/activity/images/index.vue


+ 0 - 0
packages/app/src/pages/home/classmates-detail/index.vue → packages/app/src/pages-sub/home/classmates-detail/index.vue


+ 0 - 0
packages/app/src/pages/home/classmates/index.vue → packages/app/src/pages-sub/home/classmates/index.vue


+ 0 - 0
packages/app/src/pages/home/components/activity-as-of.vue → packages/app/src/pages-sub/home/components/activity-as-of.vue


+ 60 - 0
packages/app/src/pages-sub/home/components/activity-count-down.vue

@@ -0,0 +1,60 @@
+<script setup lang="ts">
+import dayjs from 'dayjs'
+
+const props = defineProps<{ startAt?: string | number; endAt?: string | number }>()
+const emits = defineEmits<{ end: [] }>()
+const status = computed(() => {
+  // 如果当前时间小于开始时间返回等待中,如果当前时间大于等于开始时间小于等于结束时间返回进行中,当前时间大于结束时间返回已结束
+  const now = new Date()
+  if (dayjs(now).isBefore(dayjs(props.startAt))) {
+    return 'waiting'
+  } else if (dayjs(now).isAfter(dayjs(props.startAt)) && dayjs(now).isBefore(dayjs(props.endAt))) {
+    return 'running'
+  } else {
+    return 'overdue'
+  }
+})
+const time = ref(
+  dayjs({ waiting: props.startAt, running: props.endAt }[status.value]).diff(
+    new Date(),
+    'millisecond',
+  ),
+)
+</script>
+<template>
+  <div>
+    <wd-count-down :time="time" @finish="emits('end')">
+      <template #default="{ current }">
+        <div v-if="time" class="flex items-center gap-1.25 text-black/40 text-sm">
+          <div>距{{ { waiting: '报名开始', running: '报名结束' }[status] }}还有</div>
+          <div
+            v-if="current.days"
+            class="w-4 h-4 bg-black/90 rounded text-white text-2.5 flex items-center justify-center"
+          >
+            {{ current.days }}
+          </div>
+          <span v-if="current.days" class="custom-count-down-colon">天</span>
+          <div
+            class="w-4 h-4 bg-black/90 rounded text-white text-2.5 flex items-center justify-center"
+          >
+            {{ current.hours }}
+          </div>
+          <span class="custom-count-down-colon">时</span>
+          <div
+            class="w-4 h-4 bg-black/90 rounded text-white text-2.5 flex items-center justify-center"
+          >
+            {{ current.minutes }}
+          </div>
+          <span class="custom-count-down-colon">分</span>
+          <div
+            v-if="!current.days"
+            class="w-4 h-4 bg-black/90 rounded text-white text-2.5 flex items-center justify-center"
+          >
+            {{ current.seconds }}
+          </div>
+          <span v-if="!current.days" class="custom-count-down-colon">秒</span>
+        </div>
+      </template>
+    </wd-count-down>
+  </div>
+</template>

+ 0 - 0
packages/app/src/pages/home/components/article.vue → packages/app/src/pages-sub/home/components/article.vue


+ 50 - 0
packages/app/src/pages-sub/home/components/banner.vue

@@ -0,0 +1,50 @@
+<script setup lang="ts">
+import { getBanners } from '../../../core/libs/requests'
+import { BannerMode } from '../../../core/libs/models'
+import { useRouter } from '../../../core/utils/router'
+
+const props = defineProps<{ mode: BannerMode; aspect?: string }>()
+const router = useRouter()
+const { data: banners, run: setBanners } = useRequest(() => getBanners({ mode: props.mode }), {
+  initialData: [],
+})
+const current = ref<number>(0)
+const swiperList = computed(() => banners.value.map((it) => it.bannerImgUrl))
+const handleClick = ({ index }: { index: number }) => {
+  const banner = banners.value[index]
+  console.log(banner)
+  if (!banner.bannerLinkUrl && !banner.bannerDetailsContent) return
+  if (banner.bannerDetailsType === '2') {
+    if (banner.bannerLinkUrl?.startsWith('http')) {
+      router.push(`/pages-sub/common/webview/index?url=${banner.bannerLinkUrl}`)
+    } else {
+      router.push(banner.bannerLinkUrl)
+    }
+  }
+  if (banner.bannerDetailsType === '1') {
+    router.push(`/pages-sub/home/content/index?type=banner&id=${banner.id}`)
+  }
+}
+function onChange(e) {
+  //   console.log(e)
+}
+onMounted(() => {
+  setBanners()
+})
+</script>
+<template>
+  <div v-if="swiperList.length">
+    <wd-swiper
+      custom-class="rounded-2xl overflow-hidden aspect-[2.71/1]"
+      :custom-style="`aspect-ratio: ${props.aspect ?? '2.71/1'}`"
+      width="100%"
+      height="100%"
+      :list="swiperList"
+      autoplay
+      v-model:current="current"
+      :indicator="{ type: 'dots-bar' } as any"
+      @click="handleClick"
+      @change="onChange"
+    ></wd-swiper>
+  </div>
+</template>

+ 1 - 1
packages/app/src/pages/home/components/class-item.vue → packages/app/src/pages-sub/home/components/class-item.vue

@@ -25,7 +25,7 @@ const router = useRouter()
   <view
     class="relative h-43 flex items-end"
     :class="[customClass]"
-    @click="router.push(`/pages/home/classmates-detail/index?id=${options.id}`)"
+    @click="router.push(`/pages-sub/home/classmates-detail/index?id=${options.id}`)"
   >
     <view class="absolute left-0 bottom-0 rounded-2xl overflow-hidden">
       <wd-img

+ 1 - 1
packages/app/src/pages/home/components/comment-item.vue → packages/app/src/pages-sub/home/components/comment-item.vue

@@ -12,7 +12,7 @@ import { Comment } from '../../../core/libs/models'
 import { dayjs } from 'wot-design-uni'
 import { storeToRefs } from 'pinia'
 import CommentItem from './comment-item.vue'
-import Avatar from '@/pages/common/components/avatar.vue'
+import Avatar from '@/pages-sub/common/components/avatar.vue'
 import {likeActived} from "@designer-hub/assets/src/icons";
 
 const props = withDefaults(

+ 1 - 1
packages/app/src/pages/home/components/elegant-info-card.vue → packages/app/src/pages-sub/home/components/elegant-info-card.vue

@@ -25,7 +25,7 @@ const router = useRouter()
   <view
     class="relative h-43 flex items-end"
     :class="[customClass]"
-    @click="router.push(`/pages/home/classmates-detail/index?id=${options.id}`)"
+    @click="router.push(`/pages-sub/home/classmates-detail/index?id=${options.id}`)"
   >
     <view class="absolute left-0 bottom-0 rounded-2xl overflow-hidden">
       <wd-img

+ 77 - 0
packages/app/src/pages-sub/home/components/home-banner.vue

@@ -0,0 +1,77 @@
+<script setup lang="ts">
+import ImageEvo from '@/components/image-evo.vue'
+import { unix } from 'dayjs'
+
+const props = withDefaults(
+  defineProps<{
+    id: string | number
+    url: string
+    cover: string
+  }>(),
+  {},
+)
+const emits = defineEmits<{ play: [id: string | number]; ended: [id: string | number] }>()
+const instance = getCurrentInstance()
+const playing = ref(false)
+const duration = ref(0)
+const durationText = computed(() => unix(duration.value).format('mm:ss'))
+const videoContext = ref<UniNamespace.VideoContext>()
+const handlePlay = async () => {
+  videoContext.value?.play()
+  playing.value = true
+  emits('play', props.id)
+}
+const handleLoadedMetaData = ({ detail }) => {
+  duration.value = detail.duration
+}
+const handleEnded = () => {
+  playing.value = false
+  videoContext.value?.pause()
+  emits('ended', props.id)
+}
+onMounted(async () => {
+  videoContext.value = uni.createVideoContext(`video-${props.id}`, instance)
+})
+defineExpose({
+  videoContext,
+})
+</script>
+<template>
+  <div class="w-full h-full relative">
+    <div class="w-full h-full box-border pb-6">
+      <video
+        class="w-full h-full"
+        :id="`video-${id}`"
+        :src="url"
+        :controls="'contimg'"
+        :show-center-play-btn="false"
+        :enable-progress-gesture="false"
+        :loop="false"
+        @ended="handleEnded"
+        @loadedmetadata="handleLoadedMetaData"
+      ></video>
+    </div>
+    <div v-if="!playing" class="absolute left-0 top-0 w-full h-full bg-black">
+      <ImageEvo :src="cover"></ImageEvo>
+    </div>
+    <div
+      v-if="!playing"
+      class="w-[375px] h-[90px] bg-gradient-to-t from-black to-black/0 absolute left-0 bottom-0 w-full flex items-center"
+    >
+      <view class="mx-7">
+        <wd-button
+          plain
+          custom-class="bg-transparent! text-white! w-20.5! min-w-20! h-8.25! border! border-solid! border-white!"
+          @click="handlePlay()"
+        >
+          <div class="flex items-center">
+            <wd-icon name="play" size="22px"></wd-icon>
+            <div class="text-white text-[13px] font-['Gotham'] leading-[10.18px]">
+              {{ durationText }}
+            </div>
+          </div>
+        </wd-button>
+      </view>
+    </div>
+  </div>
+</template>

+ 0 - 0
packages/app/src/pages/home/components/info-card.vue → packages/app/src/pages-sub/home/components/info-card.vue


+ 62 - 0
packages/app/src/pages-sub/home/components/menus.vue

@@ -0,0 +1,62 @@
+<script lang="ts" setup>
+import Card from '@/components/card.vue'
+
+const items = [
+  {
+    id: 1,
+    title: '设计游学',
+    desc: '游学项目',
+    path: '/pages-sub/home/study-tour/index',
+    icon: '/static/svgs/iconly-glass-edit.svg',
+  },
+  {
+    id: 2,
+    title: '线下活动',
+    desc: '成长关爱',
+    path: '/pages-sub/home/offline-activity/index',
+    icon: '/static/svgs/iconly-glass-star.svg',
+  },
+  {
+    id: 3,
+    title: '设计传播',
+    desc: '运营推广',
+    path: '/pages-sub/home/spread/index',
+    icon: '/static/svgs/iconly-glass-play.svg',
+  },
+  {
+    id: 4,
+    title: '品质商城',
+    desc: '所需周边',
+    path: '/pages-sub/home/mall/index',
+    icon: '/static/svgs/message.svg',
+  },
+]
+const handleClick = (path: string) => {
+  uni.navigateTo({ url: path })
+}
+</script>
+<template>
+  <view class="w-full px-3.5 box-border grid grid-cols-2 grid-gap-4 my-6">
+    <template v-for="it of items" :key="it.id">
+      <view class="" @click="handleClick(it.path)">
+        <Card>
+          <view class="flex justify-between">
+            <view class="text-[rgba(0,0,0,0.85)] text-4 font-400 line-height-2.5">
+              <div class="text-black/90 text-base font-bold font-['PingFang_SC'] leading-[10.18px]">
+                {{ it.title }}
+              </div>
+              <view class="text-[rgba(0,0,0,0.45)] text-3.5 my-2.5">{{ it.desc }}</view>
+            </view>
+            <view class="">
+              <wd-img
+                custom-class="w-10.5 h-10.5 mt-3.5 vertical-bottom"
+                :src="it.icon"
+                mode="scaleToFill"
+              ></wd-img>
+            </view>
+          </view>
+        </Card>
+      </view>
+    </template>
+  </view>
+</template>

+ 0 - 0
packages/app/src/pages/home/components/moment-video.vue → packages/app/src/pages-sub/home/components/moment-video.vue


+ 1 - 1
packages/app/src/pages/home/components/offline-activity-item.vue → packages/app/src/pages-sub/home/components/offline-activity-item.vue

@@ -19,7 +19,7 @@ defineProps({
 const router = useRouter()
 </script>
 <template>
-  <div @click="router.push(`/pages/home/classmates-detail/index?id=${options.id}`)">
+  <div @click="router.push(`/pages-sub/home/classmates-detail/index?id=${options.id}`)">
     <card :custom-class="[customClass, 'p-0!']">
       <view class="relative aspect-[1.72/1]">
         <wd-img

+ 1 - 1
packages/app/src/pages/home/components/register-card.vue → packages/app/src/pages-sub/home/components/register-card.vue

@@ -26,7 +26,7 @@ onMounted(async () => {
 })
 </script>
 <template>
-  <div @click="router.push(`/pages/home/activity/detail/index?id=${options?.id}&type=activity`)">
+  <div @click="router.push(`/pages-sub/home/activity/detail/index?id=${options?.id}&type=activity`)">
     <Card custom-class="w-full p-0! relative aspect-[0.75/1]">
       <div class="absolute left-0 top-0 right-0 bottom-0">
         <wd-img

+ 124 - 0
packages/app/src/pages-sub/home/components/schedule-card.vue

@@ -0,0 +1,124 @@
+<script setup lang="ts">
+import SectionHeading from '@/components/section-heading.vue'
+import { scheduleCardBg } from '../../../core/libs/pngs'
+import { group } from 'radash'
+import dayjs from 'dayjs'
+import ImageEvo from '@/components/image-evo.vue'
+import { useRouter } from '../../../core/utils/router'
+
+const props = withDefaults(
+  defineProps<{
+    customClass?: string
+    items?: {
+      createTime: any
+      updateTime: any
+      creator: any
+      updater: any
+      deleted: any
+      id: any
+      studyId: number
+      travelDate: any
+      travelTime: number
+      title: string
+      travelDesc: string
+      clockExplainDesc: string
+      clockExplainUrl: string
+    }[]
+  }>(),
+  {
+    items: () => [],
+  },
+)
+const router = useRouter()
+const data = ref()
+const imgDisplayed = ref(false)
+const schedules = computed(() =>
+  group(props.items, (it) => dayjs(it?.travelTime).format('YYYY-MM-DD')),
+)
+const currentSchedule = computed(() => schedules.value[dayjs().format('YYYY-MM-DD')])
+const pull = () => {
+  data.value = currentSchedule.value.slice(0, 3)
+}
+const push = () => {
+  data.value = currentSchedule.value.slice(0, 2)
+}
+const handleClick = async () => {
+  router.push('/pages-sub/home/schedule/index')
+}
+const handleImgDisplayed = () => {
+  setTimeout(() => (imgDisplayed.value = true), 300)
+}
+onMounted(() => {
+  push()
+})
+</script>
+<template>
+  <view class="flex flex-col items-center aspect-[1.28/1]" :class="[customClass]">
+    <div class="px-3.5 w-full box-border">
+      <SectionHeading title="我的游学日程" custom-class="w-full"></SectionHeading>
+      <div
+        class="w-full my-3.5 text-[#acacac] text-sm font-normal font-['PingFang_SC'] leading-normal"
+      >
+        <!-- 6月26日 第二天 -->
+        {{ dayjs().format('M月D日') }}
+        第{{ Object.keys(schedules).findIndex((it) => it === dayjs().format('YYYY-MM-DD')) + 1 }}天
+      </div>
+    </div>
+    <div
+      class="w-80 bg-gradient-to-r from-[#141414] to-[#4b4949] rounded-tl-2xl rounded-tr-2xl p-6 box-border"
+    >
+      <template v-for="(it, index) in data" :key="index">
+        <view class="relative mb-4">
+          <view class="flex items-center">
+            <div class="w-2 h-2 left-0 top-0 rounded-full border-2 border-solid border-white"></div>
+
+            <div
+              class="w-12 ml-3.5 text-white text-base font-normal font-['PingFang_SC'] leading-normal"
+            >
+              <!-- 9:00 -->
+              {{ dayjs(it?.travelTime).format('HH:mm') }}
+            </div>
+            <div class="text-white text-base font-normal font-['PingFang_SC'] leading-normal">
+              <!-- 早稻田大学课程 -->
+              {{ it?.title }}
+            </div>
+          </view>
+          <div
+            v-if="!(data?.length === 2 && index === data?.length - 1)"
+            class="ml-6.5 text-white/40 text-sm font-normal font-['PingFang_SC'] leading-normal line-clamp-2 text-ellipsis overflow-hidden"
+          >
+            <!-- 学习灯光设计师课程 -->
+            {{ it?.travelDesc }}
+          </div>
+          <div
+            v-if="index !== data?.length - 1"
+            class="absolute left-1.25 top-6 bottom--4 border border-dashed border-gray bg-gray-500"
+          ></div>
+        </view>
+      </template>
+    </div>
+    <view class="w-full relative bottom-7 mb--9">
+      <div class="aspect-[2.55/1]">
+        <ImageEvo :src="scheduleCardBg" @displayed="handleImgDisplayed"></ImageEvo>
+      </div>
+      <view
+        class="absolute bottom-0 left-0 right-0 px-3.5 py-7 flex flex-col items-center"
+        v-show="imgDisplayed"
+      >
+        <div class="p-4 relative" @click="data?.length > 2 ? push() : pull()">
+          <wd-icon
+            custom-class=""
+            :name="data?.length > 2 ? 'arrow-up' : 'arrow-down'"
+            size="22px"
+            color="#4f4f4f"
+          ></wd-icon>
+        </div>
+        <view class="w-full">
+          <wd-button block size="large" custom-class="rd!" @click="handleClick">
+            查看全部行程
+          </wd-button>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>

+ 0 - 0
packages/app/src/pages/home/components/test.vue → packages/app/src/pages-sub/home/components/test.vue


+ 0 - 0
packages/app/src/pages/home/content/index.vue → packages/app/src/pages-sub/home/content/index.vue


+ 1 - 1
packages/app/src/pages/home/mall/components/product.vue → packages/app/src/pages-sub/home/mall/components/product.vue

@@ -40,7 +40,7 @@ const handleAddToCart = async () => {
 <template>
   <div
     class="w-full flex flex-col gap-2.5"
-    @click="router.push(`/pages/home/mall/detail/index?id=${options.productId}`)"
+    @click="router.push(`/pages-sub/home/mall/detail/index?id=${options.productId}`)"
   >
     <div class="bg-[#f6f6f6] rounded-2xl w-full aspect-square overflow-hidden">
       <wd-img

+ 2 - 2
packages/app/src/pages/home/mall/confirm-order/index.vue → packages/app/src/pages-sub/home/mall/confirm-order/index.vue

@@ -18,7 +18,7 @@ import { storeToRefs } from 'pinia'
 import { useRouter } from '../../../../core/utils/router'
 import { Coupon } from '../../../../core/libs/models'
 import { sort } from 'radash'
-import CouponsSelector from '@/pages/common/components/coupons-selector.vue'
+import CouponsSelector from '@/pages-sub/common/components/coupons-selector.vue'
 import { right } from '../../../../core/libs/svgs'
 import ButtonEvo from '@/components/button-evo.vue'
 import { handleClickInstruction } from '../../../../core/libs/actions'
@@ -86,7 +86,7 @@ const handlePay = async () => {
     { success: true, successTitle: '兑换成功' },
   )
   if (code === 0) {
-    await router.replace('/pages/home/mall/purchased/success/index')
+    await router.replace('/pages-sub/home/mall/purchased/success/index')
   }
 }
 const handleQ = async () => {

+ 0 - 0
packages/app/src/pages/home/mall/confirm-order/test.java → packages/app/src/pages-sub/home/mall/confirm-order/test.java


+ 242 - 0
packages/app/src/pages-sub/home/mall/detail/index.vue

@@ -0,0 +1,242 @@
+<route lang="json5">
+{
+style: {
+navigationBarTitleText: '品质商城',
+navigationBarBackgroundColor: '#fff',
+},
+}
+</route>
+
+<script setup lang="ts">
+import {useRouter} from '../../../../core/utils/router'
+import {createProductItemBuy, getProduct, productPlacing} from '../../../../core/libs/requests'
+import {requestToast} from '../../../../core/utils/common'
+import {useUserStore} from '../../../../store'
+import {storeToRefs} from 'pinia'
+import BottomAppBar from '@/components/bottom-app-bar.vue'
+import ButtonEvo from '@/components/button-evo.vue'
+import {usePermissions} from '../../../../composables/permissions'
+import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html.vue'
+import {useToast} from 'wot-design-uni'
+
+const toast = useToast()
+const {clickByPermission} = usePermissions()
+const userStore = useUserStore()
+const router = useRouter()
+const {userInfo} = storeToRefs(userStore)
+const id = ref()
+const show = ref(false)
+const nums = ref(1)
+const type = ref<'add2Cart' | 'orderNow'>()
+const {data, run: setData} = useRequest(() => getProduct(id.value))
+
+const handleConfirm = async () => {
+  // 积分
+  const points = data.value?.showFavourable ? data.value?.favourablePoints : data.value?.points
+  if (type.value === 'orderNow') {
+    const body = {
+      isShoppingCart: 0,
+      userId: userInfo.value.userId,
+      item: 3,
+      list: [
+        {
+          productId: id.value,
+          points,
+          nums: nums.value,
+          productName: data.value.prodcutName,
+          orderImgUrl: data.value.productCoverImgUrl,
+          vendorId: data.value.vendorId,
+        },
+      ],
+      couponList: [],
+    }
+    const {data: res, code} = await requestToast(() => productPlacing(body))
+    if (code !== 0) return
+    await router.push(`/pages-sub/home/mall/confirm-order/index?data=${JSON.stringify(body)}`)
+  }
+  if (type.value === 'add2Cart') {
+    await requestToast(
+      () =>
+        createProductItemBuy({
+          doList: [
+            {
+              userId: userInfo.value.userId,
+              productId: data.value?.productId || '',
+              points,
+              nums: nums.value,
+            },
+          ],
+        }),
+      {success: true, successTitle: '加入购物车成功'},
+    )
+    show.value = false
+  }
+}
+
+const handleClick = (product) => {
+  if (product?.isRestrict === 1 && product?.productRepertory === 0) {
+    toast.show("库存不足")
+    return null
+  }
+  let levelIds = product.memberLevelIds.split(",");
+  if (!levelIds.includes(String(userInfo.value.level.level))) {
+    toast.show("您当前会员等级不符合兑换条件")
+    return null
+  }
+  // 否则,执行原来的点击逻辑
+  clickByPermission('mallExchange', () => {
+    show.value = true;
+    type.value = 'orderNow';
+  });
+}
+onLoad(async (query: { id: string }) => {
+  id.value = query.id
+  await setData()
+})
+onShareAppMessage(() => ({
+  title: data.value?.prodcutName,
+}))
+onShareTimeline(() => ({
+  title: data.value?.prodcutName,
+}))
+</script>
+
+<template>
+  <view class="flex-grow flex flex-col">
+    <div class="aspect-[1.34/1] relative">
+      <div class="absolute aspect-[1.26/1] top-0 w-full">
+        <swiper>
+          <wd-swiper
+            custom-class="rounded-1xl overflow-hidden aspect-[1.29/1]"
+            width="100%"
+            height="100%"
+            :list="data?.productDetailsImgUrl?.split(',')"
+            autoplay
+            v-model:current="current"
+            :indicator="{ type: 'dots-bar' } as any"
+            @click="handleClick"
+          ></wd-swiper>
+        </swiper>
+      </div>
+    </div>
+    <div class="relative flex-1 bg-white p-4 flex flex-col gap-4 rounded-tl-2xl rounded-tr-2xl">
+      <div class="flex items-end gap-1">
+        <div class="text-[#ef4343] text-[26px] font-normal font-['D-DIN_Exp'] leading-[20px]">
+          <!-- 1000 -->
+          {{ data?.showFavourable ? data?.favourablePoints : data?.points }}
+        </div>
+        <template v-if="String(data?.needPoints) === '0'">
+          <div class="text-black/60 text-base font-normal font-['PingFang_SC'] leading-4">积分</div>
+        </template>
+        <template v-if="String(data?.needPoints) === '1'">
+          <div class="text-black/60 text-base font-normal font-['PingFang_SC'] leading-4">
+            折(积分结算)
+          </div>
+        </template>
+        <div
+          v-if="Number(data?.productPrice)"
+          class="w-[66px] text-black/30 text-xs font-normal font-['PingFang_SC'] leading-3"
+        >
+          <!-- ¥60 -->
+          <span style="text-decoration: line-through;">¥{{ data?.productPrice }}</span>
+        </div>
+        <div class="flex-1"></div>
+        <template v-if="String(data?.needPoints) !== '1'">
+          <div class="text-[#999999] text-xs font-normal font-['PingFang_SC']">
+            {{ data?.isRestrict === 0 ? '不限库存' : `库存:${data?.productRepertory || 0}` }}
+          </div>
+        </template>
+      </div>
+      <div class="text-black text-xl font-normal font-['PingFang_SC']">
+        <!-- 阿芙佳朵 -->
+        {{ data?.prodcutName }}
+      </div>
+      <div class="h-0.25 bg-[#f6f6f6]"></div>
+      <div class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-normal">
+        积分兑换说明:
+      </div>
+      <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-[23px]">
+        {{ data?.exchangeDesc }}
+        <!--        · 不限制兑换个数-->
+        <!--        <br />-->
+        <!--        · 兑换后不支持退换货,如有问题可联系官方客户-->
+        <!--        <br />-->
+        <!--        · 规格:件-->
+        <!--        <br />-->
+        <!--        · 配送方式:到店自取-->
+      </div>
+      <div class="mx--4 h-2.5 bg-neutral-100"></div>
+      <wd-divider>
+        <div
+          class="text-center text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal"
+        >
+          商品详情
+        </div>
+      </wd-divider>
+      <mpHtml :content="data?.contentDesc"></mpHtml>
+    </div>
+    <template v-if="String(data?.needPoints) === '0'">
+      <BottomAppBar fixed placeholder>
+        <div class="h-[63px] bg-white backdrop-blur-[20px] flex items-center justify-between gap-2">
+          <div class="flex-1">
+            <ButtonEvo
+              block
+              color="white"
+              location="right"
+              @click="((show = true), (type = 'add2Cart'))"
+            >
+              <span class="text-black/80">加入购物车</span>
+            </ButtonEvo>
+          </div>
+          <div class="flex-1">
+            <ButtonEvo
+              block
+              size="lg"
+              :disabled="(data?.isRestrict === 1 && data?.productRepertory == 0) || (!data?.memberLevelIds.split(',').includes(String(userInfo.level.level))) ? 'isDisabled': null"
+              @click="handleClick(data)"
+            >
+              立即兑换
+            </ButtonEvo>
+          </div>
+        </div>
+      </BottomAppBar>
+    </template>
+    <wd-action-sheet v-model="show">
+      <view class="px-7 py-11">
+        <div class="flex gap-3 mb-13.5">
+          <div class="w-[110px] h-[110px] bg-[#f6f6f6] rounded-2xl">
+            <wd-img width="100%" height="100%" :src="data?.productCoverImgUrl"></wd-img>
+          </div>
+          <div class="flex flex-col justify-between flex-1">
+            <div class="text-black/40 text-base font-normal font-['PingFang_SC'] leading-normal">
+              {{ data?.prodcutName }}
+            </div>
+            <div class="flex items-end gap-1">
+              <div class="text-[#ef4343] text-[22px] font-normal font-['D-DIN_Exp'] leading-4">
+                <!--                {{ data?.points }}-->
+                {{ data?.showFavourable ? data?.favourablePoints : data?.points }}
+              </div>
+              <div class="text-black/40 text-sm font-normal font-['PingFang_SC'] leading-3">
+                积分
+              </div>
+              <div class="flex-1"></div>
+              <wd-input-number
+                v-model="nums"
+                :max="data?.isRestrict === 1 && data?.purchaseLimit
+    ? Math.min(data?.purchaseQuantity, data?.productRepertory)
+    : data?.isRestrict === 1 && !data?.purchaseLimit
+    ? data?.productRepertory
+    : data?.isRestrict === 2 && data?.purchaseLimit
+    ? data?.purchaseQuantity
+    : 100"
+              />
+            </div>
+          </div>
+        </div>
+        <wd-button block :round="false" @click="handleConfirm">确认</wd-button>
+      </view>
+    </wd-action-sheet>
+  </view>
+</template>
+
+<style scoped lang="scss"></style>

+ 10 - 9
packages/app/src/pages/home/mall/index.vue → packages/app/src/pages-sub/home/mall/index.vue

@@ -145,13 +145,10 @@ onShareTimeline(() => ({
           </div>
         </div>
       </div>
-      <div class="absolute top-11 left-0 right-0 bottom-0 bg-white rounded-2xl shadow">
+      <div class="absolute top-11 left-0 right-0 bottom-0 bg-white rounded-2xl shadow swiper">
         <SwiperEvo v-model="current" :items="favourableProducts">
           <template #default="{ item: it }">
-            <div
-              class="w-full h-full px-4 flex items-center gap-3 box-border"
-              @click="router.push(`/pages/home/mall/detail/index?id=${it.productId}`)"
-            >
+            <div class="w-full h-full px-4 flex items-center gap-3 box-border" @click="router.push(`/pages-sub/home/mall/detail/index?id=${it.productId}`)">
               <wd-img
                 width="114"
                 height="114"
@@ -209,7 +206,7 @@ onShareTimeline(() => ({
                   </div>
                   <div class="flex-1"></div>
                   <div
-                    @click.stop="router.push(`/pages/home/mall/detail/index?id=${it.productId}`)"
+                    @click.stop="router.push(`/pages-sub/home/mall/detail/index?id=${it.productId}`)"
                   >
                     <wd-img width="106" height="40" :src="grabNow"></wd-img>
                   </div>
@@ -275,12 +272,12 @@ onShareTimeline(() => ({
             width="32"
             height="32"
             :src="shoppingBag"
-            @click="router.push('/pages/home/mall/shopping-cart/index')"
+            @click="router.push('/pages-sub/home/mall/shopping-cart/index')"
           ></wd-img>
         </wd-badge>
         <!-- </wd-button> -->
         <!-- </div> -->
-        <div @click="router.push('/pages/home/mall/shopping-cart/index')">
+        <div @click="router.push('/pages-sub/home/mall/shopping-cart/index')">
           <ButtonEvo>
             <span
               class="h-[22px] text-white text-base font-normal font-['PingFang_SC'] leading-tight"
@@ -297,4 +294,8 @@ onShareTimeline(() => ({
   </view>
 </template>
 
-<style scoped lang="scss"></style>
+<style lang="scss">
+	:deep(.swiper .swiper-item.h-full>view){
+		height:100%;
+	}
+</style>

+ 2 - 2
packages/app/src/pages/home/mall/purchased/success/index.vue → packages/app/src/pages-sub/home/mall/purchased/success/index.vue

@@ -14,7 +14,7 @@ import { useRouter } from '../../../../../core/utils/router'
 const userStore = useUserStore()
 const router = useRouter()
 const handle2Orders = () => {
-  router.replace('/pages/mine/orders/index')
+  router.replace('/pages-sub/mine/orders/index')
 }
 const handle2Mall = () => {
   const pages = getCurrentPages()
@@ -23,7 +23,7 @@ const handle2Mall = () => {
     console.log(pages.length - mallIndex - 1)
     router.back(pages.length - mallIndex - 1)
   } else {
-    router.replace('/pages/home/mall/index')
+    router.replace('/pages-sub/home/mall/index')
   }
 }
 onLoad(() => {})

+ 1 - 1
packages/app/src/pages/home/mall/shopping-cart/index.vue → packages/app/src/pages-sub/home/mall/shopping-cart/index.vue

@@ -136,7 +136,7 @@ const handlePlaceOrder = async () => {
   const {code, data: res} = await requestToast(() => productPlacing(body))
   if (code === 0) {
     await pageHelperRef.value?.reload()
-    await router.push(`/pages/home/mall/confirm-order/index?data=${JSON.stringify(body)}`)
+    await router.push(`/pages-sub/home/mall/confirm-order/index?data=${JSON.stringify(body)}`)
   }
 }
 </script>

+ 3 - 4
packages/app/src/pages/home/moment/index.vue → packages/app/src/pages-sub/home/moment/index.vue

@@ -34,7 +34,7 @@ import { getRect, addUnit } from 'wot-design-uni/components/common/util'
 import Card from '@/components/card.vue'
 import { get } from 'radash'
 import { DictType } from '../../../core/libs/models'
-import MomentVideo from '@/pages/home/components/moment-video.vue'
+import MomentVideo from '@/pages-sub/home/components/moment-video.vue'
 import { ComponentExposed } from 'vue-component-type-helpers'
 import { useShare } from '@/composables/share'
 
@@ -151,14 +151,13 @@ const handleDelete = async (index?: number) => {
 const handleUpvote = async (index?: number) => {
   if (index !== undefined) {
     await commentItemRef.value.at(index).refresh()
-  } else {
-    await run()
   }
+  await runGetReviews()
 }
 const toDesignerHomepage = () => {
   if (['1', '2'].includes(String(data.value?.circleType))) {
     router.push(
-      `/pages/mine/homepage/index?id=${data.value?.stylistId}${isShared.value ? '&isShared=true' : ''}`,
+      `/pages-sub/mine/homepage/index?id=${data.value?.stylistId}${isShared.value ? '&isShared=true' : ''}`,
     )
   }
 }

+ 0 - 0
packages/app/src/pages/home/offline-activity/cycling-rankings/index.vue → packages/app/src/pages-sub/home/offline-activity/cycling-rankings/index.vue


+ 13 - 11
packages/app/src/pages/home/offline-activity/index.vue → packages/app/src/pages-sub/home/offline-activity/index.vue

@@ -71,18 +71,20 @@ onMounted(async () => {
     <section-heading
       custom-class=""
       title="线下活动"
-      path="/pages/home/offline-activity/list/index"
+      path="/pages-sub/home/offline-activity/list/index"
       end-text="查看全部"
     ></section-heading>
-    <template v-if="activities.list?.length">
-      <swiper class="aspect-[0.75/1] rounded-[20px] overflow-hidden">
-        <template v-for="(it, i) in activities.list" :key="i">
-          <swiper-item>
-            <RegisterCard :options="{ ...it, levelsByMemberLevel }"></RegisterCard>
-          </swiper-item>
-        </template>
-      </swiper>
-    </template>
+    <view class="relative">
+		<template v-if="activities.list?.length">
+		  <swiper class="aspect-[0.75/1] rounded-[20px] overflow-hidden">
+		    <template v-for="(it, i) in activities.list" :key="i">
+		      <swiper-item>
+		        <RegisterCard :options="{ ...it, levelsByMemberLevel }"></RegisterCard>
+		      </swiper-item>
+		    </template>
+		  </swiper>
+		</template>
+	</view>
     <card custom-class="">
       <div class="my-7.5 text-black text-xl font-normal font-['PingFang_SC'] leading-[10.18px]">
         筑巢荟-活动营
@@ -111,7 +113,7 @@ onMounted(async () => {
           <section-heading
             title="筑巢荟骑行俱乐部"
             size="sm"
-            path="/pages/home/offline-activity/cycling-rankings/index"
+            path="/pages-sub/home/offline-activity/cycling-rankings/index"
           ></section-heading>
         </div>
       </div>

+ 147 - 0
packages/app/src/pages-sub/home/offline-activity/list/index.vue

@@ -0,0 +1,147 @@
+<route lang="json">
+{ "style": { "navigationBarTitleText": "线下活动", "navigationBarBackgroundColor": "#fff" } }
+</route>
+<script setup lang="ts">
+import { getActivities, getByDictType } from '../../../../core/libs/requests'
+import Card from '@/components/card.vue'
+import PageHelper from '@/components/page-helper.vue'
+import TiltedButton from '@/components/tilted-button.vue'
+import { useRouter } from '../../../../core/utils/router'
+import dayjs from 'dayjs'
+import ActivityCountDown from '../../components/activity-count-down.vue'
+import { getActivityStatus, getActivityStatusButtonText } from '../../../../core/utils/common'
+import { DictType } from '../../../../core/libs/models'
+
+const tab = ref<number>(0)
+const router = useRouter()
+const { data: tabs, run: setTabs } = useRequest(() => getByDictType(DictType.MemberActivityType), {
+  initialData: [],
+})
+onMounted(async () => {
+  await setTabs()
+})
+onShareAppMessage(() => ({
+  title: '线下活动',
+}))
+onShareTimeline(() => ({
+  title: '线下活动',
+}))
+</script>
+<template>
+  <div class="flex-grow flex flex-col gap-6 mx-3.5">
+    <div class="mx--3.5">
+      <wd-tabs v-model="tab" custom-class="" :slidable-num="4">
+        <block v-for="(it, item) in tabs" :key="item">
+          <wd-tab :title="it.label"></wd-tab>
+        </block>
+      </wd-tabs>
+    </div>
+    <PageHelper
+      v-if="tabs.length"
+      :request="getActivities"
+      :query="{ activityType: tabs[tab].value, showStatus: 1 }"
+      class="flex flex-col flex-grow"
+    >
+      <template #default="{ source }">
+        <div class="flex flex-col gap-6">
+          <template v-for="(it, index) in source.list" :key="index">
+            <!-- <offline-activity-item class="" :options="it"></offline-activity-item> -->
+            <div
+              @click="router.push(`/pages-sub/home/activity/detail/index?id=${it.id}&type=activity`)"
+            >
+              <Card>
+                <div class="flex flex-col gap-5">
+                  <div class="flex gap-4 mb-2">
+                    <wd-img
+                      width="110px"
+                      height="88px"
+                      class="rounded-[10px]"
+                      :src="it.thumbnailUrl"
+                    ></wd-img>
+                    <div class="flex flex-col justify-between">
+                      <div
+                        class="w-[168px] text-black text-base font-normal font-['PingFang_SC'] leading-relaxed"
+                      >
+                        {{ it.name }}
+                      </div>
+                      <div class="flex">
+                        <div
+                          class="w-[70px] text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px]"
+                        >
+                          活动时间:
+                        </div>
+                        <div
+                          class="text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px] flex items-center"
+                        >
+                          {{ dayjs(it.activityStartTime).format('MM.DD') }}
+                          <wd-icon name="play" size="22px"></wd-icon>
+                          {{ dayjs(it.activityEndTime).format('MM.DD') }}
+                        </div>
+                      </div>
+                      <div class="flex items-end">
+                        <div
+                          class="text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px]"
+                        >
+                          兑换积分:
+                        </div>
+                        <div
+                          class="text-[#ef4343] text-xl font-normal font-['D-DIN_Exp'] leading-[34px]"
+                        >
+                          {{ it.needPointsCount }}
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                  <view class="flex items-center justify-between mb-1.5">
+                    <view
+                      class="flex items-center text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px]"
+                    >
+                      <!-- <wd-count-down
+                        :time="dayjs(it.applyStartTime).diff(new Date(), 'millisecond')"
+                      >
+                        <template #default="{ current }">
+                          <div class="flex items-center gap-1.25 text-black/40 text-sm">
+                            <div>距结束还剩</div>
+                            <div
+                              class="w-4 h-4 bg-black/90 rounded text-white text-2.5 flex items-center justify-center"
+                            >
+                              {{ current.days }}
+                            </div>
+                            <span class="custom-count-down-colon">天</span>
+                            <div
+                              class="w-4 h-4 bg-black/90 rounded text-white text-2.5 flex items-center justify-center"
+                            >
+                              {{ current.hours }}
+                            </div>
+                            <span class="custom-count-down-colon">时</span>
+                            <div
+                              class="w-4 h-4 bg-black/90 rounded text-white text-2.5 flex items-center justify-center"
+                            >
+                              {{ current.minutes }}
+                            </div>
+                            <span class="custom-count-down-colon">分</span>
+                          </div>
+                        </template>
+                      </wd-count-down> -->
+                      <ActivityCountDown
+                        :start-at="it.applyStartTime"
+                        :end-at="it.applyEndTime"
+                      ></ActivityCountDown>
+                    </view>
+                    <tilted-button>
+                      {{
+                        it.ifSingnUp
+                          ? '已报名'
+                          : getActivityStatusButtonText(it.applyStartTime, it.applyEndTime)
+                      }}
+                    </tilted-button>
+                  </view>
+                </div>
+              </Card>
+            </div>
+          </template>
+        </div>
+      </template>
+    </PageHelper>
+  </div>
+</template>

+ 1 - 1
packages/app/src/pages/home/schedule/index.vue → packages/app/src/pages-sub/home/schedule/index.vue

@@ -153,7 +153,7 @@ onMounted(async () => {
         </div> -->
         <view class="flex-1"></view>
         <view>
-          <ButtonEvo size="lg" @click="router.push('/pages/publish/moment/index?circleType=1')">
+          <ButtonEvo size="lg" @click="router.push('/pages-sub/publish/moment/index?circleType=1')">
             发圈子
           </ButtonEvo>
         </view>

+ 1 - 1
packages/app/src/pages/home/spread/case-shooting/index.vue → packages/app/src/pages-sub/home/spread/case-shooting/index.vue

@@ -28,7 +28,7 @@ onShareTimeline(() => ({
               class="flex flex-col gap-4"
               @click="
                 router.push(
-                  `/pages/home/spread/product-detail/index?id=${it.productId}&title=案例拍摄&item=4`,
+                  `/pages-sub/home/spread/product-detail/index?id=${it.productId}&title=案例拍摄&item=4`,
                 )
               "
             >

+ 0 - 0
packages/app/src/pages/home/spread/case-shooting/photographer/index.vue → packages/app/src/pages-sub/home/spread/case-shooting/photographer/index.vue


+ 0 - 0
packages/app/src/pages/home/spread/design-awards/index.vue → packages/app/src/pages-sub/home/spread/design-awards/index.vue


+ 3 - 3
packages/app/src/pages/home/spread/index.vue → packages/app/src/pages-sub/home/spread/index.vue

@@ -36,19 +36,19 @@ const menus = ref([
     title: '微信代运营',
     icon: wechat,
     class: 'col-start-1 row-start-1 row-end-3 items-start!',
-    path: '/pages/home/spread/wx-agent-operation/index',
+    path: '/pages-sub/home/spread/wx-agent-operation/index',
   },
   {
     title: '设计奖项',
     icon: award,
     class: 'col-start-2 row-start-1',
-    path: '/pages/home/spread/design-awards/index',
+    path: '/pages-sub/home/spread/design-awards/index',
   },
   {
     title: '案例拍摄',
     icon: camera,
     class: 'col-start-2 row-start-2',
-    path: '/pages/home/spread/case-shooting/index',
+    path: '/pages-sub/home/spread/case-shooting/index',
   },
 ])
 onMounted(async () => {

+ 218 - 0
packages/app/src/pages-sub/home/spread/product-detail/index.vue

@@ -0,0 +1,218 @@
+<route lang="json5">
+{
+  style: {
+    navigationBarTitleText: '',
+    navigationBarBackgroundColor: '#fff',
+  },
+}
+</route>
+
+<script setup lang="ts">
+import TiltedButton from '@/components/tilted-button.vue'
+import Product from '../components/product.vue'
+import { useRouter } from '../../../../core/utils/router'
+import { getProduct, productPlacing } from '../../../../core/libs/requests'
+import { requestToast } from '../../../../core/utils/common'
+import { useUserStore } from '../../../../store'
+import { storeToRefs } from 'pinia'
+import BottomAppBar from '@/components/bottom-app-bar.vue'
+import { usePermissions } from '../../../../composables/permissions'
+import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html.vue'
+
+const userStore = useUserStore()
+const router = useRouter()
+
+const { userInfo } = storeToRefs(userStore)
+const { clickByPermission } = usePermissions()
+const id = ref()
+const show = ref(false)
+const a = ref(1)
+const item = ref()
+const type = ref<'add2Cart' | 'orderNow'>()
+const { data, run: setData } = useRequest(() => getProduct(id.value))
+
+const handleConfirm = async () => {
+  if (type.value === 'orderNow') {
+    const body = {
+      isShoppingCart: 0,
+      userId: userInfo.value.userId,
+      item: item.value,
+      list: [
+        {
+          productId: id.value,
+          points: data.value.showFavourable ? data.value.favourablePoints : data.value.points,
+          nums: 1,
+          productName: data.value.prodcutName,
+          orderImgUrl: data.value.productCoverImgUrl,
+          vendorId: data.value.vendorId,
+        },
+      ],
+      couponList: [],
+    }
+    const { data: res, code, msg } = await requestToast(() => productPlacing(body))
+    if (code !== 0) {
+      await uni.showToast({
+        title: msg,
+        icon: 'none',
+      })
+    } else {
+      await router.push(`/pages-sub/home/mall/confirm-order/index?data=${JSON.stringify(body)}`)
+    }
+    // router.push(`/pages-sub/home/mall/confirm-order/index?data=${JSON.stringify(res)}`)
+  }
+}
+onLoad(async (query: { id: string; title: string; item: string }) => {
+  id.value = query.id
+  item.value = query.item
+  uni.setNavigationBarTitle({ title: query.title })
+  await setData()
+})
+onShareAppMessage(() => ({
+  title: data.value?.prodcutName,
+}))
+onShareTimeline(() => ({
+  title: data.value?.prodcutName,
+}))
+</script>
+
+<template>
+  <!-- <view class="flex-grow flex flex-col">
+    <div class="aspect-[1.34/1] relative">
+      <div class="absolute aspect-[1.26/1] top-0 w-full">
+        <wd-img width="100%" height="100%" :src="data?.productCoverImgUrl" />
+      </div>
+    </div>
+    <div class="relative flex-1 bg-white p-4 flex flex-col gap-4 rounded-tl-2xl rounded-tr-2xl">
+      <div class="flex items-center gap-1">
+        <div class="text-[#ef4343] text-[26px] font-normal font-['D-DIN_Exp'] leading-normal">
+          {{ data?.points }}
+        </div>
+        <div class="text-black/60 text-base font-normal font-['PingFang_SC'] leading-[34px]">
+          积分
+        </div>
+        <div
+          class="w-[66px] text-black/30 text-xs font-normal font-['PingFang_SC'] line-through leading-normal"
+        >
+          ¥{{ data?.productPrice }}
+        </div>
+        <div class="flex-1"></div>
+        <div class="text-[#999999] text-xs font-normal font-['PingFang_SC'] leading-[10.18px]">
+          已售{{ data?.exchangeCount || 0 }}件
+        </div>
+      </div>
+      <div class="h-4 text-black text-xl font-normal font-['PingFang_SC'] leading-[10.18px]">
+        {{ data?.prodcutName }}
+      </div>
+      <div class="h-0.25 bg-[#f6f6f6]"></div>
+      <div class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-normal">
+        积分兑换说明:
+      </div>
+      <div
+        class="w-[346px] h-[95px] text-black/40 text-xs font-normal font-['PingFang_SC'] leading-[23px]"
+      >
+        · 不限制兑换个数
+        <br />
+        · 兑换后不支持退换货,如有问题可联系官方客户
+        <br />
+        · 规格:件
+        <br />
+        · 配送方式:到店自取
+      </div>
+      <div class="mx--4 h-2.5 bg-neutral-100"></div>
+      <wd-divider>
+        <div
+          class="text-center text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal"
+        >
+          商品详情
+        </div>
+      </wd-divider>
+      <wd-img width="100%" mode="widthFix" :src="data?.productDetailsImgUrl"></wd-img>
+    </div>
+  </view> -->
+  <div class="flex-grow flex flex-col">
+    <div class="aspect-[1.34/1] relative">
+      <div class="absolute aspect-[1.26/1] top-0 w-full">
+        <!--        <wd-img width="100%" height="100%" :src="data?.productDetailsImgUrl" />-->
+        <swiper>
+          <template v-for="(it, index) in data?.productDetailsImgUrl?.split(',')" :key="index">
+            <swiper-item>
+              <wd-img width="100%" height="100%" mode="aspectFill" :src="it" />
+            </swiper-item>
+          </template>
+        </swiper>
+      </div>
+    </div>
+    <div class="relative flex-1 bg-white p-7 flex flex-col gap-6 rounded-tl-2xl rounded-tr-2xl">
+      <div
+        v-if="String(data?.needPoints) === '1'"
+        class="text-black text-xl font-normal font-['PingFang_SC'] leading-[10.18px] mr-1"
+      >
+        {{ data?.points }}折
+      </div>
+      <div class="flex">
+        <div class="text-black text-xl font-normal font-['PingFang_SC'] leading-[10.18px]">
+          {{ data?.prodcutName }}
+        </div>
+      </div>
+      <div class="text-black/60 text-sm font-normal font-['PingFang_SC']">
+        {{ data?.exchangeDesc }}
+      </div>
+      <!--      <div-->
+      <!--        class="text-justify text-black/40 text-base font-normal font-['PingFang_SC'] leading-relaxed"-->
+      <!--        v-html="data?.contentDesc"-->
+      <!--      ></div>-->
+      <mpHtml :content="data?.contentDesc"></mpHtml>
+    </div>
+
+    <BottomAppBar fixed placeholder v-if="String(data?.needPoints) !== '1'">
+      <div
+        class="bg-white/90 backdrop-blur-[20px] flex px-10 py-2.5 border-t-1 border-t-solid border-t-[#ececec]"
+      >
+        <div class="text-[#ef4343] text-2xl font-normal font-['D-DIN_Exp'] leading-normal">
+          <!--          {{ data?.points }}-->
+          {{ data?.showFavourable ? data?.favourablePoints : data?.points }}
+        </div>
+        <div class="text-black/40 text-base font-normal font-['PingFang_SC'] leading-[34px]">
+          积分
+        </div>
+        <div class="flex-1"></div>
+        <div
+          @click="
+            clickByPermission('mallExchange', () => {
+              show = true
+              type = 'orderNow'
+            })
+          "
+        >
+          <TiltedButton size="large">立即兑换</TiltedButton>
+        </div>
+      </div>
+    </BottomAppBar>
+    <wd-action-sheet v-model="show">
+      <view class="px-7 py-11">
+        <div class="flex gap-3 mb-13.5">
+          <div class="w-[110px] h-[110px] bg-[#f6f6f6] rounded-2xl">
+            <wd-img width="100%" height="100%" :src="data?.productCoverImgUrl"></wd-img>
+          </div>
+          <div class="flex flex-col justify-between flex-1">
+            <div class="text-black/40 text-base font-normal font-['PingFang_SC'] leading-normal">
+              {{ data?.prodcutName }}
+            </div>
+            <div class="flex items-center">
+              <div class="text-[#ef4343] text-[22px] font-normal font-['D-DIN_Exp'] leading-normal">
+                {{ data?.showFavourable ? data?.favourablePoints : data?.points }}
+              </div>
+              <div class="text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px]">
+                积分
+              </div>
+              <div class="flex-1"></div>
+            </div>
+          </div>
+        </div>
+        <wd-button block :round="false" @click="handleConfirm">确认</wd-button>
+      </view>
+    </wd-action-sheet>
+  </div>
+</template>
+
+<style scoped lang="scss"></style>

+ 1 - 1
packages/app/src/pages/home/spread/wx-agent-operation/index.vue → packages/app/src/pages-sub/home/spread/wx-agent-operation/index.vue

@@ -27,7 +27,7 @@ onShareTimeline(() => ({
             class="flex flex-col gap-4"
             @click="
               router.push(
-                `/pages/home/spread/product-detail/index?id=${it.productId}&title=微信代运营&item=5`,
+                `/pages-sub/home/spread/product-detail/index?id=${it.productId}&title=微信代运营&item=5`,
               )
             "
           >

+ 1 - 1
packages/app/src/pages/home/study-tour/components/register-card.vue → packages/app/src/pages-sub/home/study-tour/components/register-card.vue

@@ -26,7 +26,7 @@ onMounted(async () => {
 })
 </script>
 <template>
-  <div @click="router.push(`/pages/home/activity/detail/index?id=${options?.id}&type=studyTour`)">
+  <div @click="router.push(`/pages-sub/home/activity/detail/index?id=${options?.id}&type=studyTour`)">
     <Card custom-class="w-full p-0! relative aspect-[0.75/1]">
       <div class="absolute left-0 top-0 right-0 bottom-0">
         <wd-img

+ 1 - 1
packages/app/src/pages/home/study-tour/components/study-tour-card.vue → packages/app/src/pages-sub/home/study-tour/components/study-tour-card.vue

@@ -20,7 +20,7 @@ const activityOptions = ref(omit(props.options, ['levelsByMemberLevel', 'index']
 const { listItemButtonText, statusText, status, difference, startAt, endAt, refresh } =
   useActivity(activityOptions)
 const toDetail = () => {
-  router.push(`/pages/home/activity/detail/index?id=${props.options?.id}&type=studyTour`)
+  router.push(`/pages-sub/home/activity/detail/index?id=${props.options?.id}&type=studyTour`)
 }
 </script>
 <template>

+ 1 - 1
packages/app/src/pages/home/study-tour/components/time-line.vue → packages/app/src/pages-sub/home/study-tour/components/time-line.vue

@@ -11,7 +11,7 @@ const current = ref(0)
       title="游学时间表"
       end-text="查看全部"
       end-class="text-white!"
-      path="/pages/home/study-tour/list"
+      path="/pages-sub/home/study-tour/list"
     >
       <template #append>
         <div class="flex items-center">

+ 0 - 0
packages/app/src/pages/home/study-tour/detail.vue → packages/app/src/pages-sub/home/study-tour/detail.vue


+ 13 - 11
packages/app/src/pages/home/study-tour/index.vue → packages/app/src/pages-sub/home/study-tour/index.vue

@@ -62,7 +62,7 @@ onMounted(async () => {
             :src="banners[0].bannerImgUrl"
             @click="
               router.push(
-                `/pages/home/study-tour/list?designStudyAbroadYear=${banners[0].designStudyAbroadYear}&designDesc=${banners[0].designDesc}`,
+                `/pages-sub/home/study-tour/list?designStudyAbroadYear=${banners[0].designStudyAbroadYear}&designDesc=${banners[0].designDesc}`,
               )
             "
           ></wd-img>
@@ -70,15 +70,17 @@ onMounted(async () => {
       </template>
     </div>
 
-    <template v-if="studyTours?.list.length">
-      <swiper class="aspect-[0.75/1] rounded-[20px] overflow-hidden">
-        <template v-for="(it, i) in studyTours?.list" :key="i">
-          <swiper-item>
-            <RegisterCard :options="{ ...it, levelsByMemberLevel }"></RegisterCard>
-          </swiper-item>
-        </template>
-      </swiper>
-    </template>
+    <div class="relative">
+		<template v-if="studyTours?.list.length">
+		  <swiper class="aspect-[0.75/1] rounded-[20px] overflow-hidden">
+		    <template v-for="(it, i) in studyTours?.list" :key="i">
+		      <swiper-item>
+		        <RegisterCard :options="{ ...it, levelsByMemberLevel }"></RegisterCard>
+		      </swiper-item>
+		    </template>
+		  </swiper>
+		</template>
+	</div>
     <!-- </template>
     </PageHelper> -->
     <!-- <card custom-class="p-0!">
@@ -155,7 +157,7 @@ onMounted(async () => {
     <section-heading
       custom-class=""
       title="同学荟"
-      path="/pages/home/classmates/index"
+      path="/pages-sub/home/classmates/index"
     ></section-heading>
     <template v-for="(it, i) in classmates.list" :key="i">
       <ClassItem :options="it"></ClassItem>

+ 0 - 0
packages/app/src/pages/home/study-tour/list.vue → packages/app/src/pages-sub/home/study-tour/list.vue


+ 0 - 0
packages/app/src/pages/login/index.vue → packages/app/src/pages-sub/login/index.vue


+ 1 - 1
packages/app/src/pages/mine/agents/index.vue → packages/app/src/pages-sub/mine/agents/index.vue

@@ -9,7 +9,7 @@ import { handleCall } from '../../../core/utils/common'
 
 const { data: agents, run: setAgents } = useRequest(() => getAgents())
 const handleClick = () => {
-  uni.navigateTo({ url: '/pages/mine/orders/detail/index' })
+  uni.navigateTo({ url: '/pages-sub/mine/orders/detail/index' })
 }
 onMounted(async () => {
   await setAgents()

+ 2 - 2
packages/app/src/pages/mine/authentication/index.vue → packages/app/src/pages-sub/mine/authentication/index.vue

@@ -164,7 +164,7 @@ const handleSubmit = async () => {
       spatialExpertiseType: formData.value.spatialExpertiseType?.join(','),
     })
     if (code === 0) {
-      await router.replace(`/pages/mine/authentication/submit/success/index`)
+      await router.replace(`/pages-sub/mine/authentication/submit/success/index`)
     } else {
       error(msg)
     }
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
     }
     const { code } = await requestToast(() => updateUserAuthInfo({ ...toBeUpdate, auditStatus: 1 }))
     if (code === 0) {
-      await router.replace(`/pages/mine/authentication/submit/success/index`)
+      await router.replace(`/pages-sub/mine/authentication/submit/success/index`)
     }
   }
 }

+ 0 - 0
packages/app/src/pages/mine/authentication/submit/success/index.vue → packages/app/src/pages-sub/mine/authentication/submit/success/index.vue


+ 88 - 0
packages/app/src/pages-sub/mine/components/coupon-card.vue

@@ -0,0 +1,88 @@
+<script setup lang="ts">
+import Card from '@/components/card.vue'
+import { Coupon, CouponStatus } from '../../../core/libs/models'
+import dayjs from 'dayjs'
+import used from '@designer-hub/assets/src/libs/assets/used'
+import expired from '@designer-hub/assets/src/libs/assets/expired'
+import invalid from '@designer-hub/assets/src/libs/assets/invalid'
+
+const props = withDefaults(
+  defineProps<{ options?: Coupon; canSelect?: boolean; selected?: boolean }>(),
+  {
+    canSelect: false,
+    selected: false,
+  },
+)
+const emits = defineEmits<{ select: [coupon: Coupon]; clickInstruction: [coupon: Coupon] }>()
+</script>
+<template>
+  <Card custom-class="mx-3.5">
+    <div class="relative" @click="canSelect && emits('select', options)">
+      <div class="flex gap-3">
+        <div class="w-[94px] h-[94px] bg-[#f6f6f6] rounded-2.5 overflow-hidden">
+          <template v-if="options.couponType === 1">
+            <div class="bg-[#fff8f8] w-full h-full flex flex-col items-center justify-center">
+              <div class="text-[#ff7878] text-[26px] font-normal font-['PingFang_SC']">
+                {{ options.brandPoints }}
+              </div>
+              <div class="text-[#ff7878] text-base font-normal font-['PingFang_SC']">积分</div>
+            </div>
+          </template>
+          <template v-else>
+            <wd-img width="100%" height="100%" :src="options.couponImgUrl"></wd-img>
+          </template>
+        </div>
+        <div class="flex-1 flex flex-col justify-around">
+          <div class="flex items-center gap-1">
+            <div
+              class="px-[3px] rounded border border-solid border-[#ff3636] justify-center items-center gap-2.5 inline-flex"
+            >
+              <div
+                class="text-[#ff3e3e] text-[10px] font-normal font-['PingFang_SC'] leading-normal"
+              >
+                {{ options.materialName }}
+              </div>
+            </div>
+            <div class="text-black text-sm font-normal font-['PingFang_SC'] leading-normal">
+              <!-- GELATO咖啡兑换券 -->
+              {{ options.couponName }}
+            </div>
+          </div>
+          <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal">
+            有效期:
+            <!-- 2024/04/01-2024/05/30 -->
+            {{ dayjs(options.validityStartDate).format('YYYY/MM/DD') }}-{{
+              dayjs(options.validityEndDate).format('YYYY/MM/DD')
+            }}
+          </div>
+          <div
+            class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal flex items-center"
+            @click.stop="emits('clickInstruction', options)"
+          >
+            使用说明
+            <wd-icon name="arrow-right" size="14"></wd-icon>
+          </div>
+        </div>
+        <div class="flex items-center" v-if="canSelect">
+          <div
+            class="w-4 h-4 rounded-full border border-black/60 border-solid"
+            :class="`${selected ? 'bg-black' : ''}`"
+          ></div>
+        </div>
+      </div>
+      <div v-if="options.couponStatus !== CouponStatus.NOT_USE" class="absolute top--4 right--4">
+        <wd-img
+          width="58"
+          height="58"
+          :src="
+            {
+              [CouponStatus.HAVE_USE]: used,
+              [CouponStatus.EXPIRED]: expired,
+              [CouponStatus.BECAME_INVALID]: invalid,
+            }[options.couponStatus]
+          "
+        ></wd-img>
+      </div>
+    </div>
+  </Card>
+</template>

+ 90 - 0
packages/app/src/pages-sub/mine/components/coupon-record.vue

@@ -0,0 +1,90 @@
+<script setup lang="ts">
+import Card from '@/components/card.vue'
+import dayjs from 'dayjs'
+import used from '@designer-hub/assets/src/libs/assets/used'
+import expired from '@designer-hub/assets/src/libs/assets/expired'
+import invalid from '@designer-hub/assets/src/libs/assets/invalid'
+import { CouponStatus } from '@/core/libs/models'
+
+const props = withDefaults(
+  defineProps<{
+    option?: {
+      materialId: number
+      couponImgUrl: any
+      materialsName: string
+      validityStartDate: number
+      validityEndDate: number
+      brandPoints: number
+    }
+    canSelect?: boolean
+    selected?: boolean
+  }>(),
+  {
+    canSelect: false,
+    selected: false,
+  },
+)
+</script>
+<template>
+  <div
+    class="mx-3.5 p-4 bg-[rgba(255,255,255,0.7)] rounded-2xl shadow-[0px_5px_8px_0px_rgba(21,3,3,0.03)]"
+  >
+    <div class="relative">
+      <div class="flex gap-3">
+        <div class="w-[68px] h-[68px] bg-[#f6f6f6] rounded-2.5 overflow-hidden">
+          <!--          <template v-if="option.couponType === 1">-->
+          <!--            <div class="bg-[#fff8f8] w-full h-full flex flex-col items-center justify-center">-->
+          <!--              <div class="text-[#ff7878] text-[26px] font-normal font-['PingFang_SC']">-->
+          <!--                {{ options.brandPoints }}-->
+          <!--              </div>-->
+          <!--              <div class="text-[#ff7878] text-base font-normal font-['PingFang_SC']">积分</div>-->
+          <!--            </div>-->
+          <!--          </template>-->
+          <!--          <template v-else>-->
+          <wd-img width="100%" height="100%" :src="option.couponImgUrl"></wd-img>
+          <!--          </template>-->
+        </div>
+        <div class="flex-1 flex flex-col justify-around">
+          <div class="flex items-center gap-1">
+            <div
+              class="px-[3px] rounded border border-solid border-[#ff3636] justify-center items-center gap-2.5 inline-flex"
+            >
+              <div
+                class="text-[#ff3e3e] text-[10px] font-normal font-['PingFang_SC'] leading-normal"
+              >
+                {{ option.materialsName }}
+              </div>
+            </div>
+            <div class="text-black text-sm font-normal font-['PingFang_SC'] leading-normal">
+              <!-- GELATO咖啡兑换券 -->
+              {{ option.couponName }}
+            </div>
+          </div>
+          <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal">
+            <!--            有效期:-->
+            <!-- 2024/04/01-2024/05/30 -->
+            {{ dayjs(option.validityStartDate).format('YYYY/MM/DD') }}-{{
+              dayjs(option.validityEndDate).format('YYYY/MM/DD')
+            }}
+          </div>
+          <!--          <div-->
+          <!--            class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal flex items-center"-->
+          <!--            @click.stop="emits('clickInstruction', options)"-->
+          <!--          >-->
+          <!--            使用说明-->
+          <!--            <wd-icon name="arrow-right" size="14"></wd-icon>-->
+          <!--          </div>-->
+        </div>
+        <div class="flex items-center" v-if="canSelect">
+          <div
+            class="w-4 h-4 rounded-full border border-black/60 border-solid"
+            :class="`${selected ? 'bg-black' : ''}`"
+          ></div>
+        </div>
+      </div>
+      <div class="absolute top--4 right--4">
+        <wd-img width="58" height="58" :src="used"></wd-img>
+      </div>
+    </div>
+  </div>
+</template>

+ 106 - 0
packages/app/src/pages-sub/mine/components/coupons-selector.vue

@@ -0,0 +1,106 @@
+<script setup lang="ts">
+import { getPointsCoupons, getProductCoupons } from '../../../core/libs/requests'
+import { Coupon } from '../../../core/libs/models'
+import { useUserStore } from '../../../store'
+import { storeToRefs } from 'pinia'
+import CouponCard from './coupon-card.vue'
+import { useMessage } from 'wot-design-uni'
+
+const props = withDefaults(
+  defineProps<{
+    type: 'points' | 'product'
+    products?: any[]
+    businessId?: number
+    show?: boolean
+  }>(),
+  { show: false },
+)
+const modelValue = defineModel({ default: () => [], type: Array as PropType<Coupon[]> })
+const emits = defineEmits<{ close: []; clickInstruction: [coupon: Coupon] }>()
+const userStore = useUserStore()
+const { userInfo } = storeToRefs(userStore)
+const { alert } = useMessage()
+// const show = ref(false)
+const tab = ref(0)
+const query = ref<{ userId: number; available?: boolean }>({
+  userId: userInfo.value.userId,
+  available: true,
+})
+const request = computed(() =>
+  props.type === 'points'
+    ? () =>
+        getPointsCoupons({
+          userId: userInfo.value.userId,
+          //   productIds: props.products.map((it) => it.productId).join(','),
+          businessId: props.businessId,
+          // isUse: 0,
+          ...query.value,
+        })
+    : () =>
+        getProductCoupons({
+          userId: userInfo.value.userId,
+          productIds: props.products.map((it) => it.productId).join(','),
+          isUse: 0,
+          ...query.value,
+        }),
+)
+const { data: coupons, run: setCoupons } = useRequest(() => request.value(), { initialData: [] })
+const handleSelect = (coupon: Coupon) => {
+  // if (modelValue.value.map(({ id }) => id).includes(coupon.id)) {
+  //   modelValue.value = modelValue.value.filter(({ id }) => id !== coupon.id)
+  // } else {
+  //   modelValue.value = [...modelValue.value, coupon]
+  if (modelValue.value.length) {
+    if (modelValue.value.map(({ id }) => id).includes(coupon.id)) {
+      modelValue.value = modelValue.value.filter(({ id }) => id !== coupon.id)
+    } else {
+      modelValue.value.splice(0, 1, coupon)
+    }
+  } else {
+    modelValue.value.push(coupon)
+  }
+  emits('close')
+}
+const handleTabsChange = async ({ index, name }) => {
+  console.log(index)
+  query.value = { ...query.value, available: index === 0 }
+  await setCoupons()
+}
+watch(
+  () => props.show,
+  async (val) => {
+    if (val) {
+      await setCoupons()
+    }
+  },
+)
+onMounted(async () => {})
+</script>
+<template>
+  <wd-action-sheet
+    :title="{ points: '销售积分券', product: '商品优惠券' }[type]"
+    :modelValue="show"
+    @close="emits('close')"
+  >
+    <view class="">
+      <wd-tabs v-model="tab" @change="handleTabsChange">
+        <wd-tab :title="`可用${{ points: '积分券', product: '商品券' }[type]}`"></wd-tab>
+        <wd-tab :title="`不可用${{ points: '积分券', product: '商品券' }[type]}`"></wd-tab>
+      </wd-tabs>
+      <div class="h-100 overflow-y-scroll">
+        <div class="bg-[#f6f6f6] py-3.5 flex flex-col gap-4 min-h-full">
+          <template v-for="(it, i) in coupons" :key="i">
+            <CouponCard
+              :options="{ couponType: 2, ...it }"
+              :canSelect="tab === 0"
+              :selected="modelValue?.map(({ id }) => id).includes(it.id)"
+              @select="handleSelect"
+              @click-instruction="(e) => emits('clickInstruction', e)"
+            ></CouponCard>
+          </template>
+        </div>
+      </div>
+      <!-- <wd-button block :round="false">确认</wd-button> -->
+    </view>
+  </wd-action-sheet>
+</template>

+ 261 - 0
packages/app/src/pages-sub/mine/components/message-card.vue

@@ -0,0 +1,261 @@
+<script setup lang="ts">
+import { Coupon, Message } from '../../../core/libs/models'
+import Card from '@/components/card.vue'
+import { integral, interact, message, system } from '../../../core/libs/svgs'
+import { beforeNow } from '../../../utils/date-util'
+import dayjs from 'dayjs'
+import { MessageType, PointStatus } from '../../../core/libs/enums'
+import {fuckYou, getPointsCoupons, updateReadByMessageType} from '../../../core/libs/requests'
+import { getMessageType } from '../../../core/libs/message-types'
+import { useRouter } from '../../../core/utils/router'
+import ButtonEvo from '@/components/button-evo.vue'
+import { messages } from '../../../core/libs/messages'
+import { stringify } from 'qs'
+
+const props = withDefaults(
+  defineProps<{ options?: Message & { selectedCoupons?: Coupon[] } }>(),
+  {},
+)
+const emits = defineEmits<{
+  submit: [message: Message, coupons: Coupon[]]
+  cancel: [message: Message]
+  selectCoupon: [message: Message, coupons: any[]]
+}>()
+const router = useRouter()
+const { data: coupons, run: setCoupons } = useRequest(
+  () =>
+    getPointsCoupons({
+      userId: props.options.designerId,
+      businessId: props.options.businessId,
+      available: true,
+    }),
+  { initialData: [] },
+)
+const couponSelectText = computed(() => {
+  const selectedCoupons = props.options.selectedCoupons || []
+  const availableCoupons = coupons.value || []
+
+  if (selectedCoupons.length > 0) {
+    return `${selectedCoupons[0].brandPoints ?? 0}积分`
+  }
+  if (availableCoupons.length > 0) {
+    return `${availableCoupons.length}张可用`
+  }
+  return '无可用'
+})
+const hasLine = computed(() => getMessageType(props.options.messageSubType)?.path)
+const init = async () => {
+  if (
+    props.options.messageType === MessageType.Integral &&
+    props.options.messageSubType === 31 &&
+    props.options.isRead !== '1'
+  ) {
+    await setCoupons()
+  }
+}
+const handleJump = () => {
+  fuckYou({id:props.options.id})
+  if ((props.options.linkUrl ?? '') !== '') {
+    return router.push(props.options.linkUrl)
+  }
+  const query: Record<string, string> = {}
+  switch (props.options.messageSubType) {
+    case 5:
+      query.id = props.options.id
+      query.title = props.options.title
+      query.contentDetail = props.options.detailBody
+      query.createTime = String(props.options.createTime)
+      query.viewsCount = props.options.viewCount
+      break
+    default:
+      break
+  }
+  console.log(stringify(query))
+  router.push(getMessageType(props.options.messageSubType)?.path + '?' + stringify(query))
+
+}
+watch(
+  () => props.options,
+  async (value, oldValue, onCleanup) => {
+    // console.log('====>', value)
+    await init()
+  },
+)
+onMounted(async () => {
+  await init()
+})
+
+</script>
+<template>
+  <Card>
+    <div class="grid items-center grid-cols-[38px_auto_100px]">
+
+      <div class="row-start-1 col-start-1">
+        <div
+          class="w-[30px] h-[30px] bg-neutral-100 rounded-full mr-2 flex items-center justify-center"
+        >
+
+          <wd-img
+            width="18"
+            height="18"
+            :src="
+              {
+                [MessageType.Integral]: integral,
+                [MessageType.System]: system,
+                [MessageType.Interact]: interact,
+              }[options.messageType]
+            "
+          ></wd-img>
+
+        </div>
+      </div>
+
+      <div class="row-start-1 col-start-2 text-start relative">
+        <div class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-[30px]">
+<!--          {{-->
+<!--            String(options.messageSubType) === '5'-->
+<!--              ? getMessageType(options.messageSubType)?.desc-->
+<!--              : options.title-->
+<!--          }}-->
+          {{options.title}}
+        </div>
+      </div>
+
+      <div class="row-start-1 col-start-3 text-end" style="white-space: nowrap">
+        <div class="text-black/30 text-sm font-normal font-['PingFang_SC'] leading-[8.18px] ">
+          <template v-if="String(options.isRead) === '0'">
+             <wd-img width="16" height="16" src="/static/svgs/red.svg"></wd-img>
+          </template>
+          {{ beforeNow(dayjs(options.createTime).toDate()) }}
+<!--          <div class="absolute top-[2px] right-[50px] z-10">-->
+<!--            <wd-img width="16" height="20" src="/static/svgs/red.svg"></wd-img>-->
+<!--          </div>-->
+<!--          <wd-img width="16" height="10" src="/static/svgs/red.svg"></wd-img>-->
+        </div>
+      </div>
+      <div class="row-start-2 col-start-2 col-end-4">
+        <div class="my-3 text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[25px]">
+          <!-- {{ options.detailBody }} -->
+          <div
+            v-if="
+              [MessageType.Integral, MessageType.System].includes(options.messageType) &&
+              String(options.messageSubType) !== '5'
+            "
+            v-html="options.detailBody"
+          ></div>
+          <div class="grid grid-cols-[auto_1fr] gap-x-1 gap-y-4.5">
+            <template
+              v-if="
+                options.messageSubType === 31 &&
+                options.pointsDetail?.pointsStauts === PointStatus.PendingConfirmation
+              "
+            >
+              <div
+                class="text-black/40 text-sm font-normal font-['PingFang_SC'] h-5.5 flex items-center"
+              >
+                销售积分券:
+              </div>
+              <div
+                class="flex items-center h-full overflow-hidden"
+                @click="emits('selectCoupon', options, coupons)"
+              >
+                <div
+                  class="text-sm font-normal font-['PingFang_SC']"
+                  :class="`${coupons.length > 0 ? 'text-[#ef4343]' : 'text-black/60'}`"
+                >
+                  <!--                  {{ `${coupons.length > 0 ? `${coupons.length}张可用` : '无可用'}` }}-->
+                  {{ couponSelectText }}
+                </div>
+                <div class="h-5.5 flex items-center overflow-hidden">
+                  <wd-icon
+                    name="chevron-right"
+                    :custom-class="`${coupons.length > 0 ? 'text-[#ef4343]' : 'text-black/60'}`"
+                    size="16"
+                  ></wd-icon>
+                </div>
+              </div>
+            </template>
+          </div>
+        </div>
+      </div>
+      <div
+        v-if="options.coverUrl"
+        class="row-start-3 col-start-2 col-end-4 aspect-[1.7/1] rounded-md overflow-hidden"
+      >
+        <wd-img width="100%" height="100%" mode="aspectFill" :src="options.coverUrl"  @click="handleJump"/>
+      </div>
+      <div v-if="hasLine" class="row-start-4 col-start-1 col-end-4 my-2">
+        <div class="bg-[#dadada] w-full h-[1px]"></div>
+      </div>
+      <div class="row-start-5 col-start-2 col-end-4">
+        <div class="text-black/40 text-xs font-normal font-['PingFang_SC']">
+          <template
+            v-if="
+              [MessageType.Integral].includes(Number(options.messageType)) &&
+              options.messageSubType === 31 &&
+              options.pointsDetail?.pointsStauts === PointStatus.PendingConfirmation
+            "
+          >
+            <span class="text-black/40">
+              {{ messages.messages.pointNotice }}
+            </span>
+          </template>
+          <template
+            v-else-if="
+              [MessageType.Integral].includes(Number(options.messageType)) &&
+              options.messageSubType === 31
+            "
+          >
+            <template v-if="options.pointsDetail?.pointsStauts === PointStatus.Rejected">
+              <span class="text-[#EF4343]">
+                <!-- 确认积分后,即刻到账,如有问题请驳回,联系材料商修改积分后再次确认 -->
+                已驳回,驳回原因:{{ options.pointsDetail?.cancelReason }}
+              </span>
+            </template>
+          </template>
+          <template
+            v-else-if="
+              [MessageType.Integral].includes(Number(options.messageType)) &&
+              [21, 22].includes(options.messageSubType)
+            "
+          >
+            如有问题请您联系官方客服!
+          </template>
+          <template v-if="getMessageType(options.messageSubType)?.path">
+            <div
+              @click="handleJump"
+              class="flex items-center text-[rgba(0,0,0,0.85)] text-xs font-normal font-['PingFang_SC'] leading-[25px]"
+            >
+              查看详情
+              <wd-icon name="arrow-right" size="12" color="rgba(0,0,0,0.85)"></wd-icon>
+            </div>
+          </template>
+        </div>
+      </div>
+      <div
+        class="row-start-6 col-start-1 col-end-4 my-1"
+        v-if="
+          [MessageType.Integral].includes(Number(options.messageType)) &&
+          options.messageSubType === 31 &&
+          options.pointsDetail?.pointsStauts === PointStatus.PendingConfirmation
+        "
+      >
+        <div class="flex gap-4 mt-4">
+          <div class="flex-1">
+            <!-- <wd-button block :round="false" plain @click="emits('cancel', options)">驳回</wd-button> -->
+            <ButtonEvo block color="white" location="right" @click="emits('cancel', options)">
+              <span class="text-black/80">驳回</span>
+            </ButtonEvo>
+          </div>
+          <!-- <div class="flex-1">
+            <wd-button block :round="false" @click="handleQ(it)">积分券</wd-button>
+          </div> -->
+          <div class="flex-1">
+            <!-- <wd-button block :round="false" @click="emits('submit', options)">确认</wd-button> -->
+            <ButtonEvo block @click="emits('submit', options, coupons)">确认</ButtonEvo>
+          </div>
+        </div>
+      </div>
+    </div>
+  </Card>
+</template>

+ 151 - 0
packages/app/src/pages-sub/mine/components/tasks-card.vue

@@ -0,0 +1,151 @@
+<script setup lang="ts">
+import { Task } from '../../../core/libs/models'
+import { taskCenterBg } from '../../../core/libs/pngs'
+import { useRouter } from '../../../core/utils/router'
+import { usePermissions } from '@/composables/permissions'
+
+const { clickByPermission } = usePermissions()
+const router = useRouter()
+defineProps({
+  customClass: {
+    type: String,
+    default: '',
+  },
+  items: {
+    type: Array as PropType<(Task & { btnProps: any })[]>,
+    default: () => [],
+  },
+})
+const styles = ref({
+  header: {
+    width: '100%',
+    height: '60px',
+    background: `url(${taskCenterBg}) -9px -9px`,
+  },
+  content: {
+    background: `url(${taskCenterBg}) -9px -69px no-repeat`,
+  },
+  main: {
+    background: `url(${taskCenterBg}) -9px -9px`,
+  },
+})
+const taskExtends = ref([
+  {
+    id: 1,
+    action: () => router.push('/pages-sub/publish/moment/index?circleType=1'),
+    completed: false,
+  },
+])
+const taskExtendsById = computed(() =>
+  taskExtends.value.reduce((acc, item) => {
+    acc[item.id] = item
+    return acc
+  }, {}),
+)
+onMounted(async () => {})
+</script>
+<template>
+  <view class="relative w-full box-border">
+    <view class="relative h-full mx--2.5 mb--6 mt--1 box-border">
+      <wd-img :width="'100%'" :height="'100%'" :src="taskCenterBg" mode="widthFix"></wd-img>
+    </view>
+    <view class="absolute left-0 right-0 top-1 bottom-6 z-1 p-3.5">
+      <view class="w-full h-full flex flex-col justify-between">
+        <div class="text-start text-black text-lg font-normal font-['PingFang_SC'] leading-normal">
+          任务中心
+        </div>
+        <div class="flex-grow mt-4 overflow-auto">
+          <template v-for="({ taskKey, taskValue, status, id, btnProps }, i) in items" :key="i">
+            <div class="flex items-center my-6">
+              <div class="text-black/90 text-sm font-normal font-['PingFang_SC'] leading-normal">
+                {{ taskKey }}
+              </div>
+              <div
+                v-if="Number(taskValue) !== 0"
+                class="ml-1 text-[#dc753a] text-xs font-normal font-['PingFang_SC'] leading-normal"
+              >
+                +{{ taskValue }}积分
+              </div>
+              <div class="flex-1"></div>
+              <wd-button
+                type="info"
+                plain
+                size="small"
+                :disabled="btnProps?.disabled"
+                @click="clickByPermission('task', () => btnProps?.onClick())"
+              >
+                {{ btnProps?.content }}
+                <!-- {{ taskExtendsById[id]?.completed ? '已完成' : '去完成' }} -->
+              </wd-button>
+            </div>
+          </template>
+        </div>
+      </view>
+    </view>
+  </view>
+  <!-- <div>
+    <div :style="styles.header">1</div>
+    <div :style="styles.content" class="p-3.5">
+      <template v-for="({ title, score }, i) in items" :key="i">
+        <div class="flex items-center my-6">
+          <div class="text-black/90 text-sm font-normal font-['PingFang_SC'] leading-normal">
+            {{ title }}
+          </div>
+          <div class="ml-1 text-[#dc753a] text-xs font-normal font-['PingFang_SC'] leading-normal">
+            +{{ score }}积分
+          </div>
+          <div class="flex-1"></div>
+          <wd-button type="info" plain size="small">去完成</wd-button>
+        </div>
+      </template>
+    </div>
+    <div></div>
+  </div> -->
+  <!-- <div class="card" :style="styles.main">
+    <div class="card-content">
+      <h2>任务中心</h2>
+      <ul>
+        <li>每日发布圈子获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+        <li>到店打卡获取积分</li>
+      </ul>
+    </div>
+  </div> -->
+</template>
+
+<style scoped>
+.card {
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  width: 100%;
+  min-height: 200px;
+  padding: 20px;
+  /* background-image: url('your-image-path'); */
+  /* 背景图片路径 */
+  background-repeat: no-repeat;
+  background-position: top center; /* 背景图片头部固定 */
+  background-size: auto; /* 固定背景图片的宽度,不拉伸 */
+  border-radius: 10px;
+}
+
+.card-content {
+  flex-grow: 1;
+  padding: 20px;
+  background-color: rgba(255, 255, 255, 0.8); /* 半透明背景 */
+  border-radius: 10px;
+}
+</style>

+ 0 - 0
packages/app/src/pages/mine/convention/index.vue → packages/app/src/pages-sub/mine/convention/index.vue


+ 1 - 1
packages/app/src/pages/mine/coupons/index.vue → packages/app/src/pages-sub/mine/coupons/index.vue

@@ -6,7 +6,7 @@ import Card from '@/components/card.vue'
 import { getCoupons } from '../../../core/libs/requests'
 import PageHelper from '@/components/page-helper.vue'
 import dayjs from 'dayjs'
-import CouponCard from '@/pages/common/components/coupon-card.vue'
+import CouponCard from '../components/coupon-card.vue'
 import { Coupon } from '../../../core/libs/models'
 import { useMessage } from 'wot-design-uni'
 import { handleClickInstruction } from '../../../core/libs/actions'

+ 0 - 0
packages/app/src/pages/mine/homepage/channels/index.vue → packages/app/src/pages-sub/mine/homepage/channels/index.vue


+ 1 - 1
packages/app/src/pages/mine/homepage/consult/index.vue → packages/app/src/pages-sub/mine/homepage/consult/index.vue

@@ -74,7 +74,7 @@ const handleSubmit = async () => {
   )
   if (code === 0) {
     form.value = { appointmentName: '', appointmentPhone: '' }
-    await router.replace(`/pages/mine/homepage/consult/success/index?name=${''}`)
+    await router.replace(`/pages-sub/mine/homepage/consult/success/index?name=${''}`)
   }
 }
 onShareAppMessage(() => ({ title: `${userInfo.value.nickname}` }))

+ 0 - 0
packages/app/src/pages/mine/homepage/consult/success/index.vue → packages/app/src/pages-sub/mine/homepage/consult/success/index.vue


+ 0 - 0
packages/app/src/pages/mine/homepage/edit/index.vue → packages/app/src/pages-sub/mine/homepage/edit/index.vue


+ 6 - 6
packages/app/src/pages/mine/homepage/index.vue → packages/app/src/pages-sub/mine/homepage/index.vue

@@ -196,7 +196,7 @@ defineExpose({
                 <div
                   v-if="isOwn && features.personalCode"
                   class="flex items-center"
-                  @click="router.push(`/pages/mine/homepage/qr-code/index`)"
+                  @click="router.push(`/pages-sub/mine/homepage/qr-code/index`)"
                 >
                   <wd-img width="22" height="22" :src="qrCode"></wd-img>
                   <wd-icon name="chevron-right" color="white" size="16"></wd-icon>
@@ -274,7 +274,7 @@ defineExpose({
         <div
           class="w-[76px] h-[30px] px-3 right-0 top-1.5 absolute bg-black/90 rounded-tl-[30px] rounded-bl-[30px] justify-center items-center gap-2.5 inline-flex"
           @click="
-            router.push(`/pages/mine/honors/index?id=${id}${isShared ? '&isShared=true' : ''}`)
+            router.push(`/pages-sub/mine/honors/index?id=${id}${isShared ? '&isShared=true' : ''}`)
           "
         >
           <div class="text-center text-white text-xs font-normal font-['PingFang_SC']">
@@ -326,7 +326,7 @@ defineExpose({
           <div
             v-else
             class="h-7 px-4 py-0.5 bg-[#fa9d3b] rounded-[20px] justify-center items-center gap-2.5 inline-flex"
-            @click.stop="router.push('/pages/mine/homepage/channels/index')"
+            @click.stop="router.push('/pages-sub/mine/homepage/channels/index')"
           >
             <div
               class="text-center text-white text-xs font-normal font-['PingFang_SC'] leading-normal"
@@ -370,7 +370,7 @@ defineExpose({
     <BottomAppBar fixed placeholder>
       <div class="flex gap-7.5">
         <div class="flex-1" v-if="isOwn && !isShared">
-          <wd-button block :round="false" @click="router.push(`/pages/mine/homepage/edit/index`)">
+          <wd-button block :round="false" @click="router.push(`/pages-sub/mine/homepage/edit/index`)">
             编辑
           </wd-button>
         </div>
@@ -385,7 +385,7 @@ defineExpose({
             :data-share-content="{
               title: `${userInfo.nickname}: “${designerInfo.designDesc}”`,
               imageUrl: designerInfo.sharePageUrl,
-              path: `/pages/mine/homepage/index?id=${id}&isShared=true`,
+              path: `/pages-sub/mine/homepage/index?id=${id}&isShared=true`,
             }"
             :data-options="{
               homepageId: id,
@@ -405,7 +405,7 @@ defineExpose({
           <wd-button
             block
             :round="false"
-            @click="router.push(`/pages/mine/homepage/consult/index?id=${id}`)"
+            @click="router.push(`/pages-sub/mine/homepage/consult/index?id=${id}`)"
           >
             预约咨询
           </wd-button>

+ 5 - 5
packages/app/src/pages/mine/homepage/qr-code/index.vue → packages/app/src/pages-sub/mine/homepage/qr-code/index.vue

@@ -26,7 +26,7 @@ const a = async (canvasContext: UniApp.CanvasContext) => {
   //   })
   //   qr.data = '12324'
   qr.data = toQrCodeString(QrCodeBusinessType.PagePath, {
-    path: `/pages/mine/homepage/index?id=${userInfo.value?.userId}`,
+    path: `/pages-sub/mine/homepage/index?id=${userInfo.value?.userId}`,
   })
   // 设置二维码大小,必须与canvas设置的宽高一致
   qr.size = 200
@@ -87,15 +87,15 @@ const handleClickScan = async () => {
   // console.log(qrCodeString2Object(toQrCodeString('到店', { a: 1, orderId: 2222 })))
   const { type, options } = qrCodeString2Object(result)
   // if (type === QrCodeBusinessType.InStoreClockIn) {
-  //   if (!features.value.checkInAtStoreTask) return router.push('/pages/mine/authentication/index')
+  //   if (!features.value.checkInAtStoreTask) return router.push('/pages-sub/mine/authentication/index')
   //   try {
   //     await storeAndPunchIn({ id: options.id })
   //     // await storeAndPunchIn({ id: 24 })
-  //     router.push(`/pages/mine/scan/result/index?result=${result}`)
+  //     router.push(`/pages-sub/mine/scan/result/index?result=${result}`)
   //   } catch (e) {
   //     if (e.code === 1000) {
   //       router.push(
-  //         `/pages/mine/scan/result/index?result=${toQrCodeString(type, { name: options.name, desc: e.msg })}`,
+  //         `/pages-sub/mine/scan/result/index?result=${toQrCodeString(type, { name: options.name, desc: e.msg })}`,
   //       )
   //     } else {
   //       uni.showToast({ title: e.msg, icon: 'none' })
@@ -107,7 +107,7 @@ const handleClickScan = async () => {
     await router.push(options.path)
     return
   }
-  await router.push(`/pages/mine/scan/result/index?result=${result}`)
+  await router.push(`/pages-sub/mine/scan/result/index?result=${result}`)
 }
 const saveQrcode = async () => {
   try {

+ 203 - 0
packages/app/src/pages-sub/mine/homepage/statistics/index.vue

@@ -0,0 +1,203 @@
+<route lang="json">
+{ "style": { "navigationBarTitleText": "主页数据", "navigationBarBackgroundColor": "#fff" } }
+</route>
+<script setup lang="ts">
+import SectionHeading from '@/components/section-heading.vue'
+import {
+  getDesignerInfo,
+  getBrowseHistories,
+  getReserveHistory,
+  countThisYear,
+} from '../../../../core/libs/requests'
+import { useUserStore } from '../../../../store'
+import { storeToRefs } from 'pinia'
+import Card from '@/components/card.vue'
+import PageHelper from '@/components/page-helper.vue'
+import dayjs from 'dayjs'
+import PageHelperEvo from '@/components/page-helper-evo.vue'
+
+const userStore = useUserStore()
+const { userInfo } = storeToRefs(userStore)
+const current = ref('累计')
+const request =
+  ref<
+    () => Promise<IResData<{ shareCount: number; viewCount: number; winCustomerCount: number }>>
+  >()
+const data = ref()
+const info = computed(() => [
+  { label: '分享', value: data.value?.shareCount || 0, unit: '次' },
+  { label: '浏览', value: data.value?.viewCount || 0, unit: '次' },
+  { label: '获客', value: data.value?.winCustomerCount || 0, unit: '人' },
+])
+const tab = ref('分享')
+const tabs = ref([
+  { label: '分享明细', value: '分享' },
+  { label: '浏览明细', value: '浏览' },
+  { label: '获客明细', value: '获客' },
+])
+const query = computed(() => ({}))
+const setData = async ({ value }) => {
+  console.log(1111)
+  console.log(value)
+
+  request.value = {
+    累计: () =>
+      getDesignerInfo(userInfo.value.userId).then((res) => ({
+        code: res.code,
+        msg: res.msg,
+        data: {
+          shareCount: res.data.shareCount,
+          viewCount: res.data.viewCount,
+          winCustomerCount: res.data.winCustomerCount,
+        },
+      })),
+    本年: () =>
+      countThisYear({ userId: userInfo.value.userId, year: new Date().getFullYear() }).then(
+        (res) => ({
+          code: res.code,
+          msg: res.msg,
+          data: {
+            shareCount: res.data.find((it) => String(it.bizType) === '1')?.quantity || 0,
+            viewCount: res.data.find((it) => String(it.bizType) === '3')?.quantity || 0,
+            winCustomerCount: res.data.find((it) => String(it.bizType) === '2')?.quantity || 0,
+          },
+        }),
+      ),
+  }[value]
+  const { data: resData } = await request.value()
+  data.value = resData
+  console.log(data.value)
+}
+onMounted(async () => {
+  console.log(1111)
+
+  await setData({ value: current.value })
+  console.log(data.value)
+  // await countThisYear({ userId: userInfo.value.userId, year: new Date().getFullYear() })
+})
+</script>
+<template>
+  <div class="flex-grow flex flex-col gap-5 px-3.5 py-6">
+    <Card>
+      <SectionHeading title="主页数据">
+        <template #append>
+          <div>
+            <wd-segmented
+              v-model:value="current"
+              :options="['累计', '本年']"
+              @change="setData"
+            ></wd-segmented>
+          </div>
+        </template>
+      </SectionHeading>
+      <div class="flex mt-7">
+        <template v-for="(it, i) in info" :key="i">
+          <div class="flex-1 flex flex-col items-center gap-2">
+            <div class="flex items-end gap-0.5">
+              <div class="text-black text-2xl font-medium font-['D-DIN-PRO'] leading-6">
+                {{ it.value }}
+              </div>
+              <div class="text-[#333333] text-sm font-normal font-['PingFang_SC']">
+                {{ it.unit }}
+              </div>
+            </div>
+            <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal">
+              {{ it.label }}
+            </div>
+          </div>
+        </template>
+      </div>
+    </Card>
+    <Card>
+      <wd-tabs v-model="tab">
+        <template v-for="(it, i) in tabs" :key="i">
+          <wd-tab :title="it.label" :name="it.value"></wd-tab>
+        </template>
+      </wd-tabs>
+      <template v-if="tab === '分享'">
+        <PageHelper :request="getBrowseHistories" :query="{ bizType: 1 }">
+          <template #default="{ source }">
+            <template v-for="(it, i) in source.list" :key="i">
+              <div class="py-4">
+                <div class="flex">
+                  <div
+                    class="flex-1 text-black text-sm font-normal font-['PingFang_SC'] leading-normal"
+                  >
+                    <!-- 银色飞行船 -->
+                    {{ it.creatorName }}
+                  </div>
+                  <div
+                    class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal"
+                  >
+                    <!-- 浏览时长:{{ (Number(it.duration) / 60).toFixed(2) }}分钟 -->
+                  </div>
+                </div>
+                <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal">
+                  分享时间:
+                  <!-- 2024/04/01 14:52 -->
+                  {{ dayjs(it.createTime).format('YYYY/MM/DD HH:mm') }}
+                </div>
+              </div>
+              <div v-if="i < source.list.length - 1" class="bg-[#f6f6f6] h-.25"></div>
+            </template>
+          </template>
+        </PageHelper>
+      </template>
+      <template v-if="tab === '浏览'">
+        <PageHelper :request="getBrowseHistories" :query="query">
+          <template #default="{ source }">
+            <template v-for="(it, i) in source.list" :key="i">
+              <div class="py-4">
+                <div class="flex">
+                  <div
+                    class="flex-1 text-black text-sm font-normal font-['PingFang_SC'] leading-normal"
+                  >
+                    <!-- 银色飞行船 -->
+                    {{ it.creatorName }}
+                  </div>
+                  <div
+                    class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal"
+                  >
+                    浏览时长:{{ (Number(it.duration) / 60).toFixed(2) }}分钟
+                  </div>
+                </div>
+                <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal">
+                  查看时间:
+                  <!-- 2024/04/01 14:52 -->
+                  {{ dayjs(it.createTime).format('YYYY/MM/DD HH:mm') }}
+                </div>
+              </div>
+              <div v-if="i < source.list.length - 1" class="bg-[#f6f6f6] h-.25"></div>
+            </template>
+          </template>
+        </PageHelper>
+      </template>
+      <template v-if="tab === '获客'">
+        <PageHelperEvo :request="getReserveHistory" :query="query">
+          <template #default="{ source }">
+            <template v-for="(it, i) in source.list" :key="i">
+              <div class="py-4">
+                <div class="flex gap-3">
+                  <div class="text-black text-sm font-normal font-['PingFang_SC'] leading-normal">
+                    <!-- 银色飞行船 -->
+                    {{ it.appointmentName }}
+                  </div>
+                  <div class="text-black text-sm font-normal font-['PingFang_SC'] leading-normal">
+                    <!-- 浏览时长:{{ (Number(it.duration) / 60).toFixed(2) }}分钟 -->
+                    {{ it.appointmentPhone }}
+                  </div>
+                </div>
+                <div class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-normal">
+                  获客时间:
+                  <!-- 2024/04/01 14:52 -->
+                  {{ dayjs(it.createTime).format('YYYY/MM/DD HH:mm') }}
+                </div>
+              </div>
+              <div v-if="i < source.list.length - 1" class="bg-[#f6f6f6] h-.25"></div>
+            </template>
+          </template>
+        </PageHelperEvo>
+      </template>
+    </Card>
+  </div>
+</template>

+ 0 - 0
packages/app/src/pages/mine/honors/detail/collection.vue → packages/app/src/pages-sub/mine/honors/detail/collection.vue


+ 1 - 1
packages/app/src/pages/mine/honors/detail/index.vue → packages/app/src/pages-sub/mine/honors/detail/index.vue

@@ -126,7 +126,7 @@ const subTitle = computed(() =>
 const setBadgesPath = (type: string) => {
   if (type === '活动徽章') {
     uni.redirectTo({
-      url: `/pages/home/offline-activity/index`,
+      url: `/pages-sub/home/offline-activity/index`,
     })
   } else {
     uni.switchTab({

+ 3 - 3
packages/app/src/pages/mine/honors/index.vue → packages/app/src/pages-sub/mine/honors/index.vue

@@ -85,13 +85,13 @@ const handleSwiperChange = (e: any) => {
 
 const handleGetCondition = (badge: any) => {
   uni.navigateTo({
-    url: `/pages/mine/honors/detail/collection?id=${badge}`,
+    url: `/pages-sub/mine/honors/detail/collection?id=${badge}`,
   })
 }
 
 const handleGetBadge = (badge: any) => {
   uni.navigateTo({
-    url: `/pages/mine/honors/leaderboard/index?id=${badge}`,
+    url: `/pages-sub/mine/honors/leaderboard/index?id=${badge}`,
   })
 }
 const currentCertificate = ref<Certificate | undefined>()
@@ -279,7 +279,7 @@ onLoad(async (query?: Record<string | 'active' | 'id' | 'isShared', string>) =>
                 class="w-full px-4 box-border"
                 @click="
                   router.push(
-                    `/pages/mine/honors/detail/index?type=badge&data=${JSON.stringify(item)}`,
+                    `/pages-sub/mine/honors/detail/index?type=badge&data=${JSON.stringify(item)}`,
                   )
                 "
               >

+ 0 - 0
packages/app/src/pages/mine/honors/leaderboard/index.vue → packages/app/src/pages-sub/mine/honors/leaderboard/index.vue


Vissa filer visades inte eftersom för många filer har ändrats