Prechádzať zdrojové kódy

做题字体修改和练习前的温馨提示

zhangyujun 3 rokov pred
rodič
commit
2cab8543cd
100 zmenil súbory, kde vykonal 4282 pridanie a 347 odobranie
  1. 1 0
      src/api/modules/user.js
  2. 40 0
      src/components/m-classify-tip/m-classify-tip.vue
  3. 3 0
      src/otherPages/classifyArea/index.vue
  4. 13 1
      src/otherPages/classifyChoose/index.vue
  5. 3 0
      src/otherPages/classifyKind/index.vue
  6. 16 12
      src/otherPages/classifyOrder/index.vue
  7. 73 11
      src/otherPages/exercise/index.vue
  8. 2 0
      src/otherPages/mockExam/index.vue
  9. 52 20
      src/pages.json
  10. 373 302
      src/pages/cinema/schedulelist.vue
  11. 1 1
      src/pages/mockExam/components/correctAnswerMask.vue
  12. 1 0
      src/ttcomponents/vant/action-sheet/index.d.ts
  13. 62 0
      src/ttcomponents/vant/action-sheet/index.js
  14. 8 0
      src/ttcomponents/vant/action-sheet/index.json
  15. 101 0
      src/ttcomponents/vant/action-sheet/index.vue
  16. 69 0
      src/ttcomponents/vant/action-sheet/index.wxml
  17. 0 0
      src/ttcomponents/vant/action-sheet/index.wxss
  18. 1 0
      src/ttcomponents/vant/area/index.d.ts
  19. 232 0
      src/ttcomponents/vant/area/index.js
  20. 6 0
      src/ttcomponents/vant/area/index.json
  21. 246 0
      src/ttcomponents/vant/area/index.vue
  22. 20 0
      src/ttcomponents/vant/area/index.wxml
  23. 8 0
      src/ttcomponents/vant/area/index.wxs
  24. 1 0
      src/ttcomponents/vant/area/index.wxss
  25. 1 0
      src/ttcomponents/vant/button/index.d.ts
  26. 58 0
      src/ttcomponents/vant/button/index.js
  27. 7 0
      src/ttcomponents/vant/button/index.json
  28. 84 0
      src/ttcomponents/vant/button/index.vue
  29. 53 0
      src/ttcomponents/vant/button/index.wxml
  30. 39 0
      src/ttcomponents/vant/button/index.wxs
  31. 0 0
      src/ttcomponents/vant/button/index.wxss
  32. 37 0
      src/ttcomponents/vant/calendar/calendar.vue
  33. 65 0
      src/ttcomponents/vant/calendar/calendar.wxml
  34. 1 0
      src/ttcomponents/vant/calendar/components/header/index.d.ts
  35. 16 0
      src/ttcomponents/vant/calendar/components/header/index.js
  36. 3 0
      src/ttcomponents/vant/calendar/components/header/index.json
  37. 43 0
      src/ttcomponents/vant/calendar/components/header/index.vue
  38. 16 0
      src/ttcomponents/vant/calendar/components/header/index.wxml
  39. 1 0
      src/ttcomponents/vant/calendar/components/header/index.wxss
  40. 1 0
      src/ttcomponents/vant/calendar/components/month/index.d.ts
  41. 157 0
      src/ttcomponents/vant/calendar/components/month/index.js
  42. 3 0
      src/ttcomponents/vant/calendar/components/month/index.json
  43. 195 0
      src/ttcomponents/vant/calendar/components/month/index.vue
  44. 39 0
      src/ttcomponents/vant/calendar/components/month/index.wxml
  45. 67 0
      src/ttcomponents/vant/calendar/components/month/index.wxs
  46. 0 0
      src/ttcomponents/vant/calendar/components/month/index.wxss
  47. 1 0
      src/ttcomponents/vant/calendar/index.d.ts
  48. 297 0
      src/ttcomponents/vant/calendar/index.js
  49. 10 0
      src/ttcomponents/vant/calendar/index.json
  50. 325 0
      src/ttcomponents/vant/calendar/index.vue
  51. 25 0
      src/ttcomponents/vant/calendar/index.wxml
  52. 37 0
      src/ttcomponents/vant/calendar/index.wxs
  53. 1 0
      src/ttcomponents/vant/calendar/index.wxss
  54. 17 0
      src/ttcomponents/vant/calendar/utils.d.ts
  55. 78 0
      src/ttcomponents/vant/calendar/utils.js
  56. 25 0
      src/ttcomponents/vant/calendar/utils.wxs
  57. 1 0
      src/ttcomponents/vant/card/index.d.ts
  58. 49 0
      src/ttcomponents/vant/card/index.js
  59. 6 0
      src/ttcomponents/vant/card/index.json
  60. 103 0
      src/ttcomponents/vant/card/index.vue
  61. 56 0
      src/ttcomponents/vant/card/index.wxml
  62. 0 0
      src/ttcomponents/vant/card/index.wxss
  63. 1 0
      src/ttcomponents/vant/cell-group/index.d.ts
  64. 10 0
      src/ttcomponents/vant/cell-group/index.js
  65. 3 0
      src/ttcomponents/vant/cell-group/index.json
  66. 27 0
      src/ttcomponents/vant/cell-group/index.vue
  67. 9 0
      src/ttcomponents/vant/cell-group/index.wxml
  68. 1 0
      src/ttcomponents/vant/cell-group/index.wxss
  69. 1 0
      src/ttcomponents/vant/cell/index.d.ts
  70. 38 0
      src/ttcomponents/vant/cell/index.js
  71. 6 0
      src/ttcomponents/vant/cell/index.json
  72. 73 0
      src/ttcomponents/vant/cell/index.vue
  73. 46 0
      src/ttcomponents/vant/cell/index.wxml
  74. 17 0
      src/ttcomponents/vant/cell/index.wxs
  75. 0 0
      src/ttcomponents/vant/cell/index.wxss
  76. 1 0
      src/ttcomponents/vant/checkbox-group/index.d.ts
  77. 31 0
      src/ttcomponents/vant/checkbox-group/index.js
  78. 3 0
      src/ttcomponents/vant/checkbox-group/index.json
  79. 43 0
      src/ttcomponents/vant/checkbox-group/index.vue
  80. 1 0
      src/ttcomponents/vant/checkbox-group/index.wxml
  81. 1 0
      src/ttcomponents/vant/checkbox-group/index.wxss
  82. 1 0
      src/ttcomponents/vant/checkbox/index.d.ts
  83. 74 0
      src/ttcomponents/vant/checkbox/index.js
  84. 6 0
      src/ttcomponents/vant/checkbox/index.json
  85. 99 0
      src/ttcomponents/vant/checkbox/index.vue
  86. 31 0
      src/ttcomponents/vant/checkbox/index.wxml
  87. 20 0
      src/ttcomponents/vant/checkbox/index.wxs
  88. 1 0
      src/ttcomponents/vant/checkbox/index.wxss
  89. 6 0
      src/ttcomponents/vant/circle/canvas.d.ts
  90. 43 0
      src/ttcomponents/vant/circle/canvas.js
  91. 1 0
      src/ttcomponents/vant/circle/index.d.ts
  92. 186 0
      src/ttcomponents/vant/circle/index.js
  93. 3 0
      src/ttcomponents/vant/circle/index.json
  94. 204 0
      src/ttcomponents/vant/circle/index.vue
  95. 9 0
      src/ttcomponents/vant/circle/index.wxml
  96. 1 0
      src/ttcomponents/vant/circle/index.wxss
  97. 1 0
      src/ttcomponents/vant/col/index.d.ts
  98. 9 0
      src/ttcomponents/vant/col/index.js
  99. 3 0
      src/ttcomponents/vant/col/index.json
  100. 23 0
      src/ttcomponents/vant/col/index.vue

+ 1 - 0
src/api/modules/user.js

@@ -7,6 +7,7 @@ const user = {
 	 */
 	async login() {
 		let res = await wx.login()
+		console.log(res)
 		return request({
 			url: `${process.env.NODE_ENV==='development'?'https://jpcj-admin1.zzxcx.net/twzd-admin':'https://jpcj-admin.zzxcx.net/twzd-admin'}/login/jscode`,
 			method: 'post',

+ 40 - 0
src/components/m-classify-tip/m-classify-tip.vue

@@ -0,0 +1,40 @@
+<template>
+  <div>
+    <div class="box">
+      <div class="line1">温馨提示:</div>
+      <div v-for="(item, index) in content" :key="index">
+        {{ index + 1 }}.{{ item }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  props: {
+    content: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  padding: 0 15rpx;
+  width: 750rpx;
+  font-size: 28rpx;
+
+  .line1 {
+    color: rgba(165, 0, 0, 0.61);
+    font-size: 28rpx;
+    line-height: 38rpx;
+  }
+}
+</style>

+ 3 - 0
src/otherPages/classifyArea/index.vue

@@ -25,6 +25,8 @@
         <div class="icon">{{ index + 1 }}</div>
       </template>
     </van-cell>
+    <div style="height:40rpx;width: 750rpx;"></div>
+    <m-classify-tip :content="classifyTip"></m-classify-tip>
   </div>
 </template>
 
@@ -34,6 +36,7 @@ import utils from "@/utils/index";
 export default {
   data() {
     return {
+      classifyTip:['地方题库,如有个别地区增加【地方题库】,请选择该区域的【地方题库】+【必学题】学习,如果没有无需学习地方题库'],
       classData: [],
       query: {},
     };

+ 13 - 1
src/otherPages/classifyChoose/index.vue

@@ -52,7 +52,7 @@
         </template>
       </van-cell> -->
     </div>
-    <div class="cell-box">
+    <div style="padding-right:0rpx" class="cell-box">
       <van-cell
         class="cell"
         :title="
@@ -61,6 +61,13 @@
           item.excellIssueName ||
           item.sequeIssueName
         "
+        @click="
+          () => {
+            goExercise({
+              excellIssueName: item.excellIssueName,
+            });
+          }
+        "
         is-link
         center
         v-for="(item, index) in classDataRight"
@@ -72,6 +79,8 @@
         </template>
       </van-cell>
     </div>
+     <div style="height:40rpx;width: 750rpx;"></div>
+    <m-classify-tip :content="classifyTip"></m-classify-tip>
   </div>
 </template>
 
@@ -81,6 +90,8 @@ import utils from "@/utils/index";
 export default {
   data() {
     return {
+      classifyTip:['软件题库已同步更新至车管所最新,左边的红色必学题,每套题必须学完.',
+      '模拟考试能连续5次以上达到96分左右,即可参加考试','如果模拟考试达不到要求,请把右边的选学题也学习一遍'],
       classDataRight: [],
       classDataLeft: [],
       query: {},
@@ -181,6 +192,7 @@ export default {
 .cell-container {
   display: flex;
   flex-direction: row;
+  flex-wrap: wrap;
 }
 .cell-box {
   display: flex;

+ 3 - 0
src/otherPages/classifyKind/index.vue

@@ -22,6 +22,8 @@
         <div class="icon">{{ index + 1 }}</div>
       </template>
     </van-cell>
+     <div style="height:40rpx;width: 750rpx;"></div>
+       <m-classify-tip :content="classifyTip"></m-classify-tip>
   </div>
 </template>
 
@@ -31,6 +33,7 @@ import utils from "@/utils/index";
 export default {
   data() {
     return {
+      classifyTip:['分类练习,学员可重点学习自己不懂的题目.','建议新学员直接看软件必考题技巧,快速学习'],
       classData: [],
       query: {},
     };

+ 16 - 12
src/otherPages/classifyOrder/index.vue

@@ -46,6 +46,10 @@
         </van-cell>
       </view>
     </div>
+    <!-- <div style="height: 40rpx; width: 750rpx"></div>
+    <div style="padding:0rpx 15rpx">
+         <m-classify-tip :content="classifyTip"></m-classify-tip>
+    </div> -->
   </view>
 </template>
 
@@ -56,6 +60,7 @@ export default {
   data() {
     return {
       classData: [],
+      classifyTip:['软件题库已同步更新至车管所最新'],
       query: {
         title: "",
         vehicle: "",
@@ -71,7 +76,6 @@ export default {
           ...extraQuery,
         };
       } else {
-       
       }
 
       uni.navigateTo({
@@ -127,33 +131,33 @@ export default {
     flex: 1.2;
 
     .select-item0 {
-      padding: 0 12px;
+      padding: 0 18rpx;
       background: #498ef5;
-      margin-right: 10px;
-      border-radius: 8px;
-      font-size: 12px;
+      margin-right: 20rpx;
+      border-radius: 8rpx;
+      font-size: 24rpx;
     }
 
     .select-item1 {
-      padding: 0 12px;
+      padding: 0 18rpx;
       background: #06bd5e;
-      font-size: 12px;
-      border-radius: 8px;
+      font-size: 24rpx;
+      border-radius: 16rpx;
     }
   }
   .icon {
-    width: 20px;
-    height: 20px;
+    width: 40rpx;
+    height: 40rpx;
     background: #498ef5;
     border-radius: 50%;
     font-weight: 500;
     font-family: PingFang SC;
-    font-size: 13px;
+    font-size: 26rpx;
     display: flex;
     justify-content: center;
     align-items: center;
     color: #ffffff;
-    margin-right: 5px;
+    margin-right: 10rpx;
   }
 }
 </style>

+ 73 - 11
src/otherPages/exercise/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <view class="box">
+  <view @touchstart="touchStart" @touchend="touchEnd" class="box">
     <nav-bar :title="navTitle"> </nav-bar>
     <!-- <view style="text-align:center;">
       <van-count-down :time="time"></van-count-down>
@@ -10,7 +10,9 @@
         problemList[problemListIndex].questionType | questionType
       }}</span>
       <!-- <text>{{ problemListIndex + 1 }}、</text> -->
-      <text class="">{{ problemList[problemListIndex].issue }}</text>
+      <text class="problem-issue">{{
+        problemList[problemListIndex].issue
+      }}</text>
       <view v-if="problemList[problemListIndex].image" class="problem-img">
         <image
           mode="widthFix"
@@ -200,9 +202,16 @@
         <view>答案是:{{ problemList[problemListIndex].answer }}</view>
       </view>
     </view>
-    <explainJs @close="()=>{
-      explainJsVisible=false
-      }" :explainJs="problemList[problemListIndex].explainJs" :explainjsmp3="problemList[problemListIndex].explainjsmp3" :show="explainJsVisible"></explainJs>
+    <explainJs
+      @close="
+        () => {
+          explainJsVisible = false;
+        }
+      "
+      :explainJs="problemList[problemListIndex].explainJs"
+      :explainjsmp3="problemList[problemListIndex].explainjsmp3"
+      :show="explainJsVisible"
+    ></explainJs>
 
     <van-tabbar>
       <van-tabbar-item @click="goBeforeTopics"
@@ -233,9 +242,11 @@
         }}/{{ problemListTotal }}
       </van-tabbar-item>
       <van-tabbar-item
-      @click="()=>{
-        explainJsVisible=true
-      }"
+        @click="
+          () => {
+            explainJsVisible = true;
+          }
+        "
         ><icon slot="icon" type="warn" size="18px" />解释
       </van-tabbar-item>
       <van-tabbar-item @click="goNextTopics"
@@ -254,7 +265,7 @@
 import navBar from "./components/navBar.vue";
 import api from "@/api/index";
 import utils from "@/utils/index";
-import explainJs from './components/explainJs.vue'
+import explainJs from "./components/explainJs.vue";
 export default {
   data() {
     return {
@@ -274,9 +285,11 @@ export default {
         },
         {},
       ],
-      explainJsVisible:false,
+      explainJsVisible: false,
       time: 45 * 60 * 1000,
       problemListTotal: 1,
+      touchx: 0,
+      touchy: 0,
       problemList: [
         {
           answer: "×",
@@ -355,6 +368,50 @@ export default {
     },
   },
   methods: {
+    touchStart(e) {
+      var that = this;
+
+      (this.touchx = e.changedTouches[0].clientX),
+        (this.touchy = e.changedTouches[0].clientY);
+    },
+    touchEnd(e) {
+      console.log(e);
+      var that = this;
+      let x = e.changedTouches[0].clientX;
+      let y = e.changedTouches[0].clientY;
+      let turn = "";
+      if (x - that.touchx > 50 && Math.abs(y - that.touchy) < 50) {
+        //右滑
+        turn = "right";
+        this.problemListIndex <= 0
+          ? uni.showToast({
+              title: "到底了",
+              icon: "none",
+            })
+          : this.problemListIndex--;
+      } else if (x - that.touchx < -50 && Math.abs(y - that.touchy) < 50) {
+        //左滑
+        turn = "left";
+        this.problemListIndex >= this.problemList.length - 1
+          ? uni.showToast({
+              title: "到底了",
+              icon: "none",
+            })
+          : this.problemListIndex++;
+      }
+      if (y - that.touchy > 50 && Math.abs(x - that.touchx) < 50) {
+        //下滑
+        turn = "down";
+      } else if (y - that.touchy < -50 && Math.abs(x - that.touchx) < 50) {
+        //上滑
+        turn = "up";
+      }
+      //根据方向进行操作
+      if (turn == "down") {
+        //下滑触发操作
+      }
+      console.log(turn);
+    },
     isRightAnswer(item) {
       if (
         typeof item.userAnswer == "object" &&
@@ -552,7 +609,7 @@ export default {
 
   components: {
     navBar,
-    explainJs
+    explainJs,
   },
 };
 </script>
@@ -631,6 +688,11 @@ export default {
       border-radius: 16rpx 16rpx 0 16rpx;
       background: #498ef5;
       margin-right: 10rpx;
+      color: #fff;
+      font-size: 32rpx;
+    }
+    .problem-issue {
+      font-size: 42rpx;
     }
     .problem-ops {
       margin-top: 30rpx;

+ 2 - 0
src/otherPages/mockExam/index.vue

@@ -480,6 +480,8 @@ export default {
       border-radius: 16rpx 16rpx 0 16rpx;
       background: #498ef5;
       margin-right: 10rpx;
+      color: #fff;
+      font-size: 32rpx;
     }
     .problem-ops {
       margin-top: 30rpx;

+ 52 - 20
src/pages.json

@@ -85,7 +85,6 @@
         "enablePullDownRefresh": false
       }
     },
-
     {
       "path": "pages/fulu/index",
       "style": {
@@ -138,10 +137,8 @@
       "path": "pages/user/index",
       "style": {
         "navigationBarTitleText": "用户信息"
-        
       }
     },
-
     {
       "path": "pages/carVideo/shortVideoPaly",
       "style": {
@@ -195,18 +192,17 @@
           "style": {
             "navigationBarTitleText": "模拟考试分数",
             "enablePullDownRefresh": false
-
           }
         },
         {
-          "path":"beforeMockExam/index",
+          "path": "beforeMockExam/index",
           "styles": {
             "navigationBarTitleText": "模拟考试",
             "enablePullDownRefresh": false
           }
         },
         {
-          "path":"collection/index",
+          "path": "collection/index",
           "styles": {}
         },
         {
@@ -217,31 +213,25 @@
           }
         },
         {
-          "path":"mockExam/index",
+          "path": "mockExam/index",
           "style": {
             "navigationBarTitleText": "模拟考试",
             "enablePullDownRefresh": false
-        
           }
-
         },
         {
-          "path":"mockExamEnd/index",
+          "path": "mockExamEnd/index",
           "style": {
             "navigationBarTitleText": "模拟考试结果",
             "enablePullDownRefresh": false
-        
           }
-
         },
         {
-          "path":"exercise/index",
+          "path": "exercise/index",
           "style": {
             "navigationBarTitleText": "练习",
             "enablePullDownRefresh": false
-        
           }
-
         }
       ]
     }
@@ -277,6 +267,7 @@
     "navigationBarTitleText": "",
     "navigationBarBackgroundColor": "#F8F8F8",
     "backgroundColor": "#F8F8F8",
+    // #ifdef MP-WEIXIN
     "usingComponents": {
       "van-overlay": "./wxcomponents/vant/overlay/index",
       "van-tabbar": "./wxcomponents/vant/tabbar/index",
@@ -313,8 +304,50 @@
       "van-sidebar-item": "wxcomponents/vant/sidebar-item/index",
       "van-grid": "wxcomponents/vant/grid/index",
       "van-grid-item": "wxcomponents/vant/grid-item/index",
-      "van-nav-bar":"wxcomponents/vant/nav-bar/index"
+      "van-nav-bar": "wxcomponents/vant/nav-bar/index"
+    },
+    "a":""
+    // #endif
+    // #ifdef MP-TOUTIAO
+    "usingComponents": {
+      "van-overlay": "/ttcomponents/vant/overlay/index",
+      "van-tabbar": "/ttcomponents/vant/tabbar/index",
+      "van-tabbar-item": "/ttcomponents/vant/tabbar-item/index",
+      "van-search": "/ttcomponents/vant/search/index",
+      "van-icon": "/ttcomponents/vant/icon/index",
+      "van-row": "/ttcomponents/vant/row/index",
+      "van-col": "/ttcomponents/vant/col/index",
+      "van-transition": "/ttcomponents/vant/transition/index",
+      "van-image": "/ttcomponents/vant/image/index",
+      "van-checkbox": "/ttcomponents/vant/checkbox/index",
+      "van-checkbox-group": "/ttcomponents/vant/checkbox-group/index",
+      "van-radio": "/ttcomponents/vant/radio/index",
+      "van-radio-group": "/ttcomponents/vant/radio-group/index",
+      "van-cell": "/ttcomponents/vant/cell/index",
+      "van-cell-group": "/ttcomponents/vant/cell-group/index",
+      "van-switch": "/ttcomponents/vant/switch/index",
+      "van-popup": "/ttcomponents/vant/popup/index",
+      "van-skeleton": "/ttcomponents/vant/skeleton/index",
+      "van-field": "/ttcomponents/vant/field/index",
+      "van-area": "/ttcomponents/vant/area/index",
+      "van-button": "/ttcomponents/vant/button/index",
+      "van-divider": "/ttcomponents/vant/divider/index",
+      "van-count-down": "/ttcomponents/vant/count-down/index",
+      "van-dialog": "/ttcomponents/vant/dialog/index",
+      "van-tab": "/ttcomponents/vant/tab/index",
+      "van-tabs": "/ttcomponents/vant/tabs/index",
+      "van-picker": "/ttcomponents/vant/picker/index",
+      "van-share-sheet": "/ttcomponents/vant/share-sheet/index",
+      "van-index-bar": "/ttcomponents/vant/index-bar/index",
+      "van-index-anchor": "/ttcomponents/vant/index-anchor/index",
+      "van-stepper": "/ttcomponents/vant/stepper/index",
+      "van-sidebar": "/ttcomponents/vant/sidebar/index",
+      "van-sidebar-item": "/ttcomponents/vant/sidebar-item/index",
+      "van-grid": "/ttcomponents/vant/grid/index",
+      "van-grid-item": "/ttcomponents/vant/grid-item/index",
+      "van-nav-bar": "/ttcomponents/vant/nav-bar/index"
     }
+    // #endif
   },
   "condition": {
     //模式配置,仅开发期间生效
@@ -345,19 +378,18 @@
       {
         "name": "模拟考试仿真题目",
         "path": "otherPages/mockExam/index",
-        "query":"liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=模拟考试&sort=3"
+        "query": "liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=模拟考试&sort=3"
       },
       {
         "name": "模拟考试结果",
         "path": "otherPages/mockExamEnd/index",
-        "query":"liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=模拟考试&sort=3"
+        "query": "liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=模拟考试&sort=3"
       },
       {
         "name": "练习",
         "path": "otherPages/exercise/index",
-        "query":"liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=4&title=顺序练习&sort=3&excellIssueName=新增题库"
+        "query": "liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=4&title=顺序练习&sort=3&excellIssueName=新增题库"
       }
-      
     ]
   }
 }

+ 373 - 302
src/pages/cinema/schedulelist.vue

@@ -1,335 +1,406 @@
 <template>
-	<page-meta>
-		<navigation-bar :title="filmList[filmId].name" background-color="#FFFFFF" front-color="#000000" />
-	</page-meta>
-	<view class="schedulelist">
-		<loadSke :loading='listLoading'>
-			<view class="des-box">
-				<view class="address">
-					{{cinemaName}}
-				</view>
-				<swiper class="swiper-box" :current="current" previous-margin='200rpx' next-margin='200rpx' @change='swiperChange'>
-					<swiper-item v-for="(item,index) in scheduleListKey" :key='index' class="swiper-item">
-						<image class="image" :class="{imgBig:current==index}" :src="filmList[item].pic" mode="heightFix" :draggable="false" />
-					</swiper-item>
-				</swiper>
-				<view class="film-name">
-					{{filmList[filmId].name}}
-				</view>
-				<view class="film-des">
-					{{filmList[filmId].duration}}分钟 | {{filmList[filmId].filmTypes}} | {{filmList[filmId].cast}}
-				</view>
-			</view>
+  <page-meta>
+    <navigation-bar
+      :title="filmList[filmId].name"
+      background-color="#FFFFFF"
+      front-color="#000000"
+    />
+  </page-meta>
+  <view class="schedulelist">
+    <loadSke :loading="listLoading">
+      <view class="des-box">
+        <view class="address">
+          {{ cinemaName }}
+        </view>
+        <swiper
+          class="swiper-box"
+          :current="current"
+          previous-margin="200rpx"
+          next-margin="200rpx"
+          @change="swiperChange"
+        >
+          <swiper-item
+            v-for="(item, index) in scheduleListKey"
+            :key="index"
+            class="swiper-item"
+          >
+            <image
+              class="image"
+              :class="{ imgBig: current == index }"
+              :src="filmList[item].pic"
+              mode="heightFix"
+              :draggable="false"
+            />
+          </swiper-item>
+        </swiper>
+        <view class="film-name">
+          {{ filmList[filmId].name }}
+        </view>
+        <view class="film-des">
+          {{ filmList[filmId].duration }}分钟 |
+          {{ filmList[filmId].filmTypes }} | {{ filmList[filmId].cast }}
+        </view>
+      </view>
 
-
-			<view class="schedule-box">
-				<van-tabs :active='tabActive' :swipe-threshold='3' animated swipeable id="tabs" @change='tabsChange'>
-					<van-tab class='schedule-tab' :title="$utils.getDay(index)+' '+index.slice(5)" v-for='(item,index) in scheduleItem'
-					 :key='index'>
-						<view v-for="(sonItem,sonIndex) in item" :key='sonItem.showId' class="schedule-des" @click="clickBuy(sonItem)">
-							<view class="left-box">
-								<view class="item-box">
-									<text>{{sonItem.showTime.slice(11,16)}}</text>
-									<text class="bottom-text">{{sonItem.duration}}分钟</text>
-								</view>
-								<view class="type-box">
-									<text>{{sonItem.planType}}</text>
-									<text class="bottom-text">{{sonItem.hallName}}</text>
-								</view>
-							</view>
-							<view class="right-box">
-								<view class="price-box">
-									<text>{{(sonItem.netPrice/100*(sonItem.netPrice>3900?discountRule.upDiscountRate:discountRule.downDiscountRate)*filmDiscount).toFixed(2)}}元</text>
-									<text class="bottom-text old-price">{{sonItem.netPrice/100}}元</text>
-								</view>
-								<button v-if='discontinued(sonItem.stopSellTime)'>购 票</button>
-								<button v-else type="default" style="background: linear-gradient(90deg, #c0c0c0, #c0c0c0, #c0c0c0);">停 售</button>
-							</view>
-						</view>
-					</van-tab>
-				</van-tabs>
-			</view>
-		</loadSke>
-	</view>
+      <view class="schedule-box">
+        <van-tabs
+          :active="tabActive"
+          :swipe-threshold="3"
+          animated
+          swipeable
+          id="tabs"
+          @change="tabsChange"
+        >
+          <van-tab
+            class="schedule-tab"
+            :title="$utils.getDay(index) + ' ' + index.slice(5)"
+            v-for="(item, index) in scheduleItem"
+            :key="index"
+          >
+            <view
+              v-for="(sonItem, sonIndex) in item"
+              :key="sonItem.showId"
+              class="schedule-des"
+              @click="clickBuy(sonItem)"
+            >
+              <view class="left-box">
+                <view class="item-box">
+                  <text>{{ sonItem.showTime.slice(11, 16) }}</text>
+                  <text class="bottom-text">{{ sonItem.duration }}分钟</text>
+                </view>
+                <view class="type-box">
+                  <text>{{ sonItem.planType }}</text>
+                  <text class="bottom-text">{{ sonItem.hallName }}</text>
+                </view>
+              </view>
+              <view class="right-box">
+                <view class="price-box">
+                  <text
+                    >{{
+                      (
+                        (sonItem.netPrice / 100) *
+                        (sonItem.netPrice > 3900
+                          ? discountRule.upDiscountRate
+                          : discountRule.downDiscountRate) *
+                        filmDiscount
+                      ).toFixed(2)
+                    }}元</text
+                  >
+                  <text class="bottom-text old-price"
+                    >{{ sonItem.netPrice / 100 }}元</text
+                  >
+                </view>
+                <button v-if="discontinued(sonItem.stopSellTime)">购 票</button>
+                <button
+                  v-else
+                  type="default"
+                  style="
+                    background: linear-gradient(
+                      90deg,
+                      #c0c0c0,
+                      #c0c0c0,
+                      #c0c0c0
+                    );
+                  "
+                >
+                  停 售
+                </button>
+              </view>
+            </view>
+          </van-tab>
+        </van-tabs>
+      </view>
+    </loadSke>
+  </view>
 </template>
 
 <script>
-	export default {
-		data: () => ({
-			listLoading: true,
-			tabActive: 0,
-			current: 0,
-			cinemaId: null,
-			filmId: null,
-			cinemaName: '',
-			scheduleList: {},
-			scheduleListKey: null,
-			discountRule: {},
-			scheduleItem: {}
-		}),
-		computed: {
-			filmList() {
-				let list = {}
-				this.$store.state.cinema.filmList.map((val) => {
-					list[val.filmId] = val
-				})
-				return list;
-			},
-			filmDiscount() {
-				return this.$store.state.cinema.filmDiscount;
-			}
-		},
-		onLoad: function(option) {
-			this.cinemaId = option.cinemaId;
-			this.filmId = option.filmId;
-		},
-		mounted() {
-			this.init()
-		},
-		methods: {
-			clickBuy(item) {
-				let flag = this.discontinued(item.stopSellTime)
-				if (flag) {
-					this.$utils.goPage(`/pages/cinema/selectseat`, null, {
-						showItem: item
-					})
-				}
-				return
-			},
-			init() {
-				this.listLoading = true
-				this.$api.cinema.getScheduleList({
-					cinemaId: this.cinemaId
-				}).then(res => {
-					this.scheduleList = {}
-					this.discountRule = res.data.data.discountRule
-					this.$store.commit('SET_DISCOUNTRULE', res.data.data.discountRule)
-					this.cinemaName = res.data.data.list[0].cinemaName
-					res.data.data.list.sort((a, b) => {
-						return this.$utils.dayjs(a.showTime).isAfter(b.showTime) ? 1 : -1
-					})
-					res.data.data.list.forEach((val) => {
-						this.scheduleList[val.filmId] || (this.scheduleList[val.filmId] = {})
-						this.scheduleList[val.filmId][val.showDate] || (this.scheduleList[val.filmId][val.showDate] = [])
-						this.scheduleList[val.filmId][val.showDate].push(val)
-					})
-					this.scheduleListKey = Object.keys(this.scheduleList);
-					//定位影片位置
-					(this.filmId == 'undefined') && (this.filmId = this.scheduleListKey[0])
-					this.scheduleItem = this.scheduleList[this.filmId]
-					this.current = this.scheduleListKey.indexOf(this.filmId)
-					this.listLoading = false
-					setTimeout(() => {
-						this.selectComponent('#tabs').resize();
-					}, 500)
-				})
-			},
-			discontinued(date) {
-				let flag = (new Date(date.replace(/-/g, "/")).getTime() - new Date().getTime() - 1000 * 60 * 60) > 0
-				return flag
-			},
-			swiperChange(e) {
-				this.current = e.detail.current
-				this.filmId = this.scheduleListKey[this.current]
-				this.scheduleItem = {}
-				this.$nextTick(() => {
-					this.scheduleItem = this.scheduleList[this.filmId]
-					this.$nextTick(() => {
-						this.tabActive = 0
-						this.selectComponent('#tabs').resize();
-					})
-				})
-			},
-			tabsChange(e) {
-				this.tabActive = e.detail.index
-			}
-		}
-	}
+export default {
+  data: () => ({
+    listLoading: true,
+    tabActive: 0,
+    current: 0,
+    cinemaId: null,
+    filmId: null,
+    cinemaName: "",
+    scheduleList: {},
+    scheduleListKey: null,
+    discountRule: {},
+    scheduleItem: {},
+  }),
+  computed: {
+    filmList() {
+      let list = {};
+      this.$store.state.cinema.filmList.map((val) => {
+        list[val.filmId] = val;
+      });
+      return list;
+    },
+    filmDiscount() {
+      return this.$store.state.cinema.filmDiscount;
+    },
+  },
+  onLoad: function (option) {
+    this.cinemaId = option.cinemaId;
+    this.filmId = option.filmId;
+  },
+  mounted() {
+    this.init();
+  },
+  methods: {
+    clickBuy(item) {
+      let flag = this.discontinued(item.stopSellTime);
+      if (flag) {
+        this.$utils.goPage(`/pages/cinema/selectseat`, null, {
+          showItem: item,
+        });
+      }
+      return;
+    },
+    init() {
+      this.listLoading = true;
+      this.$api.cinema
+        .getScheduleList({
+          cinemaId: this.cinemaId,
+        })
+        .then((res) => {
+          this.scheduleList = {};
+          this.discountRule = res.data.data.discountRule;
+          this.$store.commit("SET_DISCOUNTRULE", res.data.data.discountRule);
+          this.cinemaName = res.data.data.list[0].cinemaName;
+          res.data.data.list.sort((a, b) => {
+            return this.$utils.dayjs(a.showTime).isAfter(b.showTime) ? 1 : -1;
+          });
+          res.data.data.list.forEach((val) => {
+            this.scheduleList[val.filmId] ||
+              (this.scheduleList[val.filmId] = {});
+            this.scheduleList[val.filmId][val.showDate] ||
+              (this.scheduleList[val.filmId][val.showDate] = []);
+            this.scheduleList[val.filmId][val.showDate].push(val);
+          });
+          this.scheduleListKey = Object.keys(this.scheduleList);
+          //定位影片位置
+          this.filmId == "undefined" && (this.filmId = this.scheduleListKey[0]);
+          this.scheduleItem = this.scheduleList[this.filmId];
+          this.current = this.scheduleListKey.indexOf(this.filmId);
+          this.listLoading = false;
+          setTimeout(() => {
+            this.selectComponent("#tabs").resize();
+          }, 500);
+        });
+    },
+    discontinued(date) {
+      let flag =
+        new Date(date.replace(/-/g, "/")).getTime() -
+          new Date().getTime() -
+          1000 * 60 * 60 >
+        0;
+      return flag;
+    },
+    swiperChange(e) {
+      this.current = e.detail.current;
+      this.filmId = this.scheduleListKey[this.current];
+      this.scheduleItem = {};
+      this.$nextTick(() => {
+        this.scheduleItem = this.scheduleList[this.filmId];
+        this.$nextTick(() => {
+          this.tabActive = 0;
+          this.selectComponent("#tabs").resize();
+        });
+      });
+    },
+    tabsChange(e) {
+      this.tabActive = e.detail.index;
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	.button-box {
-		width: 100%;
-		height: 100rpx;
-		display: flex;
-		justify-content: space-around;
-		align-items: stretch;
-		background-color: #ffffff;
+.button-box {
+  width: 100%;
+  height: 100rpx;
+  display: flex;
+  justify-content: space-around;
+  align-items: stretch;
+  background-color: #ffffff;
 
-		.problem-type {
-			display: flex;
-			justify-content: center;
-			align-items: center;
-		}
+  .problem-type {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
 
-		.active {
-			border-bottom: 2px solid red;
-		}
-	}
+  .active {
+    border-bottom: 2px solid red;
+  }
+}
 
-	.des-box {
-		background-image: url(https://t1-1305573081.cos.ap-shanghai.myqcloud.com/wxapp/static/imgs/filmBg.png);
-		padding: 35rpx 30rpx;
-		box-sizing: border-box;
-		width: 100%;
-		height: 690rpx;
+.des-box {
+  background-image: url(https://t1-1305573081.cos.ap-shanghai.myqcloud.com/wxapp/static/imgs/filmBg.png);
+  padding: 35rpx 30rpx;
+  box-sizing: border-box;
+  width: 100%;
+  height: 690rpx;
 
-		.address {
-			font-size: 30rpx;
-			font-weight: bold;
-			color: #FFFFFF;
-		}
+  .address {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #ffffff;
+  }
 
-		.swiper-box {
-			margin: auto;
-			margin-top: 60rpx;
-			padding: 0 45rpx;
-			box-sizing: border-box;
-			width: 100%;
-			height: 270rpx;
+  .swiper-box {
+    margin: auto;
+    margin-top: 60rpx;
+    padding: 0 45rpx;
+    box-sizing: border-box;
+    width: 100%;
+    height: 270rpx;
 
-			.swiper-item {
-				display: flex;
-				justify-content: center;
-				align-items: center;
-			}
+    .swiper-item {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
 
-			.image {
-				height: 86%;
-			}
+    .image {
+      height: 86%;
+    }
 
-			.imgBig {
-				height: 100% !important;
-			}
-		}
+    .imgBig {
+      height: 100% !important;
+    }
+  }
 
-		.film-name {
-			margin-top: 53rpx;
-			text-align: center;
-			font-size: 30rpx;
-			font-weight: bold;
-			color: #FFFFFF;
-		}
+  .film-name {
+    margin-top: 53rpx;
+    text-align: center;
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #ffffff;
+  }
 
-		.film-des {
-			margin-top: 19rpx;
-			text-align: center;
-			font-size: 22rpx;
-			font-weight: 400;
-			color: #FFFFFF;
-			width: 100%;
-			overflow: hidden;
-			white-space: nowrap;
-			text-overflow: ellipsis;
-		}
-	}
+  .film-des {
+    margin-top: 19rpx;
+    text-align: center;
+    font-size: 22rpx;
+    font-weight: 400;
+    color: #ffffff;
+    width: 100%;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+}
 
-	.schedule-box {
-		width: 100vw;
-		min-height: calc(100vh - 690rpx + 122rpx - 10px - env(safe-area-inset-bottom)/2);
-		padding-bottom: calc(10px + env(safe-area-inset-bottom)/2);
-		background-color: #FFFFFF;
-		border-radius: 50rpx 50rpx 0px 0px;
-		margin-top: -122rpx;
-		overflow: hidden;
+.schedule-box {
+  width: 100vw;
+  min-height: calc(
+    100vh - 690rpx + 122rpx - 10px - env(safe-area-inset-bottom) / 2
+  );
+  padding-bottom: calc(10px + env(safe-area-inset-bottom) / 2);
+  background-color: #ffffff;
+  border-radius: 50rpx 50rpx 0px 0px;
+  margin-top: -122rpx;
+  overflow: hidden;
 
-		.schedule-tab {
-			overflow-y: auto;
-		}
+  .schedule-tab {
+    overflow-y: auto;
+  }
 
-		.schedule-des {
-			display: flex;
-			justify-content: space-between;
-			align-items: center;
-			padding: 0 30rpx;
-			margin-top: 50rpx;
+  .schedule-des {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 30rpx;
+    margin-top: 50rpx;
 
-			.bottom-text {
-				font-size: 22rpx;
-				font-weight: 400;
-				color: #999999;
-				width: 100rpx;
-				text-align: center;
-				white-space: nowrap;
-				overflow: hidden;
-				text-overflow: ellipsis;
-			}
+    .bottom-text {
+      font-size: 22rpx;
+      font-weight: 400;
+      color: #999999;
+      width: 100rpx;
+      text-align: center;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
 
-			.left-box {
-				width: 50%;
-				display: flex;
-				justify-content: space-around;
-				align-items: stretch;
+    .left-box {
+      width: 50%;
+      display: flex;
+      justify-content: space-around;
+      align-items: stretch;
 
-				.item-box {
-					display: flex;
-					flex-direction: column;
-					justify-content: space-between;
-					align-items: center;
+      .item-box {
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
 
-					&:first-child {
-						font-size: 40rpx;
-						font-weight: 400;
-						color: #0F0404;
-					}
-				}
+        &:first-child {
+          font-size: 40rpx;
+          font-weight: 400;
+          color: #0f0404;
+        }
+      }
 
-				.type-box {
-					display: flex;
-					flex-direction: column;
-					justify-content: space-between;
-					align-items: center;
+      .type-box {
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
 
-					&:first-child {
-						font-size: 26rpx;
-						font-weight: 400;
-						color: #0F0404;
-					}
+        &:first-child {
+          font-size: 26rpx;
+          font-weight: 400;
+          color: #0f0404;
+        }
 
-					:last-child {
-						width: 220rpx !important;
-					}
-				}
-			}
+        :last-child {
+          width: 220rpx !important;
+        }
+      }
+    }
 
-			.right-box {
-				width: 45%;
-				display: flex;
-				justify-content: space-around;
-				align-items: center;
+    .right-box {
+      width: 45%;
+      display: flex;
+      justify-content: space-around;
+      align-items: center;
 
-				.price-box {
-					display: flex;
-					flex-direction: column;
-					justify-content: space-between;
-					align-items: center;
+      .price-box {
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
 
-					&:first-child {
-						font-size: 36rpx;
-						font-weight: 400;
-						color: #E31919;
-					}
+        &:first-child {
+          font-size: 36rpx;
+          font-weight: 400;
+          color: #e31919;
+        }
 
-					.old-price {
-						text-decoration: line-through;
-					}
-				}
+        .old-price {
+          text-decoration: line-through;
+        }
+      }
 
-				button {
-					margin: 0;
-					width: 126rpx;
-					height: 60rpx;
-					background: linear-gradient(90deg, #E31818, #ED3E24, #ED4F24);
-					border-radius: 30rpx;
-					font-size: 26rpx;
-					font-weight: 400;
-					color: #FFFFFF;
-					white-space: nowrap;
-					display: flex;
-					justify-content: center;
-					align-items: center;
-				}
-			}
-		}
-	}
-</style>
+      button {
+        margin: 0;
+        width: 126rpx;
+        height: 60rpx;
+        background: linear-gradient(90deg, #e31818, #ed3e24, #ed4f24);
+        border-radius: 30rpx;
+        font-size: 26rpx;
+        font-weight: 400;
+        color: #ffffff;
+        white-space: nowrap;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+  }
+}
+</style>

+ 1 - 1
src/pages/mockExam/components/correctAnswerMask.vue

@@ -21,7 +21,7 @@
           <!-- <div class="mid-line3" v-if="correctScore >= 90">再接再励</div> -->
           <!-- <div class="mid-line3">技巧:{{ explainJq }}</div> -->
         </div>
-        <div v-if="image" class="image">
+        <div v-if="question.image" class="image">
           <image
             mode="heightFix"
             class="answer-image"

+ 1 - 0
src/ttcomponents/vant/action-sheet/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 62 - 0
src/ttcomponents/vant/action-sheet/index.js

@@ -0,0 +1,62 @@
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+import { openType } from '../mixins/open-type';
+VantComponent({
+  mixins: [button, openType],
+  props: {
+    show: Boolean,
+    title: String,
+    cancelText: String,
+    description: String,
+    round: {
+      type: Boolean,
+      value: true,
+    },
+    zIndex: {
+      type: Number,
+      value: 100,
+    },
+    actions: {
+      type: Array,
+      value: [],
+    },
+    overlay: {
+      type: Boolean,
+      value: true,
+    },
+    closeOnClickOverlay: {
+      type: Boolean,
+      value: true,
+    },
+    closeOnClickAction: {
+      type: Boolean,
+      value: true,
+    },
+    safeAreaInsetBottom: {
+      type: Boolean,
+      value: true,
+    },
+  },
+  methods: {
+    onSelect(event) {
+      const { index } = event.currentTarget.dataset;
+      const item = this.data.actions[index];
+      if (item && !item.disabled && !item.loading) {
+        this.$emit('select', item);
+        if (this.data.closeOnClickAction) {
+          this.onClose();
+        }
+      }
+    },
+    onCancel() {
+      this.$emit('cancel');
+    },
+    onClose() {
+      this.$emit('close');
+    },
+    onClickOverlay() {
+      this.$emit('click-overlay');
+      this.onClose();
+    },
+  },
+});

+ 8 - 0
src/ttcomponents/vant/action-sheet/index.json

@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index",
+    "van-popup": "../popup/index",
+    "van-loading": "../loading/index"
+  }
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 101 - 0
src/ttcomponents/vant/action-sheet/index.vue


+ 69 - 0
src/ttcomponents/vant/action-sheet/index.wxml

@@ -0,0 +1,69 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<van-popup
+  show="{{ show }}"
+  position="bottom"
+  round="{{ round }}"
+  z-index="{{ zIndex }}"
+  overlay="{{ overlay }}"
+  custom-class="van-action-sheet"
+  safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
+  close-on-click-overlay="{{ closeOnClickOverlay }}"
+  bind:close="onClickOverlay"
+>
+  <view wx:if="{{ title }}" class="van-action-sheet__header">
+    {{ title }}
+    <van-icon
+      name="cross"
+      custom-class="van-action-sheet__close"
+      bind:click="onClose"
+    />
+  </view>
+  <view wx:if="{{ description }}" class="van-action-sheet__description van-hairline--bottom">
+    {{ description }}
+  </view>
+  <view wx:if="{{ actions && actions.length }}">
+    <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
+    <button
+      wx:for="{{ actions }}"
+      wx:key="index"
+      open-type="{{ item.openType }}"
+      style="{{ item.color ? 'color: ' + item.color : '' }}"
+      class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} {{ item.className || '' }}"
+      hover-class="van-action-sheet__item--hover"
+      data-index="{{ index }}"
+      bind:tap="onSelect"
+      bindgetuserinfo="bindGetUserInfo"
+      bindcontact="bindContact"
+      bindgetphonenumber="bindGetPhoneNumber"
+      binderror="bindError"
+      bindlaunchapp="bindLaunchApp"
+      bindopensetting="bindOpenSetting"
+      lang="{{ lang }}"
+      session-from="{{ sessionFrom }}"
+      send-message-title="{{ sendMessageTitle }}"
+      send-message-path="{{ sendMessagePath }}"
+      send-message-img="{{ sendMessageImg }}"
+      show-message-card="{{ showMessageCard }}"
+      app-parameter="{{ appParameter }}"
+    >
+      <block wx:if="{{ !item.loading }}">
+        {{ item.name }}
+        <view wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</view>
+      </block>
+      <van-loading wx:else custom-class="van-action-sheet__loading" size="22px" />
+    </button>
+  </view>
+  <slot />
+  <block wx:if="{{ cancelText }}">
+    <view class="van-action-sheet__gap" />
+    <view
+      class="van-action-sheet__cancel"
+      hover-class="van-action-sheet__cancel--hover"
+      hover-stay-time="70"
+      bind:tap="onCancel"
+    >
+      {{ cancelText }}
+    </view>
+  </block>
+</van-popup>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
src/ttcomponents/vant/action-sheet/index.wxss


+ 1 - 0
src/ttcomponents/vant/area/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 232 - 0
src/ttcomponents/vant/area/index.js

@@ -0,0 +1,232 @@
+import { VantComponent } from '../common/component';
+import { pickerProps } from '../picker/shared';
+import { requestAnimationFrame } from '../common/utils';
+const EMPTY_CODE = '000000';
+VantComponent({
+  classes: ['active-class', 'toolbar-class', 'column-class'],
+  props: Object.assign(Object.assign({}, pickerProps), {
+    value: {
+      type: String,
+      observer(value) {
+        this.code = value;
+        this.setValues();
+      },
+    },
+    areaList: {
+      type: Object,
+      value: {},
+      observer: 'setValues',
+    },
+    columnsNum: {
+      type: null,
+      value: 3,
+    },
+    columnsPlaceholder: {
+      type: Array,
+      observer(val) {
+        this.setData({
+          typeToColumnsPlaceholder: {
+            province: val[0] || '',
+            city: val[1] || '',
+            county: val[2] || '',
+          },
+        });
+      },
+    },
+  }),
+  data: {
+    columns: [{ values: [] }, { values: [] }, { values: [] }],
+    typeToColumnsPlaceholder: {},
+  },
+  mounted() {
+    requestAnimationFrame(() => {
+      this.setValues();
+    });
+  },
+  methods: {
+    getPicker() {
+      if (this.picker == null) {
+        this.picker = this.selectComponent('.van-area__picker');
+      }
+      return this.picker;
+    },
+    onCancel(event) {
+      this.emit('cancel', event.detail);
+    },
+    onConfirm(event) {
+      const { index } = event.detail;
+      let { value } = event.detail;
+      value = this.parseValues(value);
+      this.emit('confirm', { value, index });
+    },
+    emit(type, detail) {
+      detail.values = detail.value;
+      delete detail.value;
+      this.$emit(type, detail);
+    },
+    parseValues(values) {
+      const { columnsPlaceholder } = this.data;
+      return values.map((value, index) => {
+        if (
+          value &&
+          (!value.code || value.name === columnsPlaceholder[index])
+        ) {
+          return Object.assign(Object.assign({}, value), {
+            code: '',
+            name: '',
+          });
+        }
+        return value;
+      });
+    },
+    onChange(event) {
+      const { index, picker, value } = event.detail;
+      this.code = value[index].code;
+      this.setValues().then(() => {
+        this.$emit('change', {
+          picker,
+          values: this.parseValues(picker.getValues()),
+          index,
+        });
+      });
+    },
+    getConfig(type) {
+      const { areaList } = this.data;
+      return (areaList && areaList[`${type}_list`]) || {};
+    },
+    getList(type, code) {
+      if (type !== 'province' && !code) {
+        return [];
+      }
+      const { typeToColumnsPlaceholder } = this.data;
+      const list = this.getConfig(type);
+      let result = Object.keys(list).map((code) => ({
+        code,
+        name: list[code],
+      }));
+      if (code != null) {
+        // oversea code
+        if (code[0] === '9' && type === 'city') {
+          code = '9';
+        }
+        result = result.filter((item) => item.code.indexOf(code) === 0);
+      }
+      if (typeToColumnsPlaceholder[type] && result.length) {
+        // set columns placeholder
+        const codeFill =
+          type === 'province'
+            ? ''
+            : type === 'city'
+            ? EMPTY_CODE.slice(2, 4)
+            : EMPTY_CODE.slice(4, 6);
+        result.unshift({
+          code: `${code}${codeFill}`,
+          name: typeToColumnsPlaceholder[type],
+        });
+      }
+      return result;
+    },
+    getIndex(type, code) {
+      let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
+      const list = this.getList(type, code.slice(0, compareNum - 2));
+      // oversea code
+      if (code[0] === '9' && type === 'province') {
+        compareNum = 1;
+      }
+      code = code.slice(0, compareNum);
+      for (let i = 0; i < list.length; i++) {
+        if (list[i].code.slice(0, compareNum) === code) {
+          return i;
+        }
+      }
+      return 0;
+    },
+    setValues() {
+      const picker = this.getPicker();
+      if (!picker) {
+        return;
+      }
+      let code = this.code || this.getDefaultCode();
+      const provinceList = this.getList('province');
+      const cityList = this.getList('city', code.slice(0, 2));
+      const stack = [];
+      const indexes = [];
+      const { columnsNum } = this.data;
+      if (columnsNum >= 1) {
+        stack.push(picker.setColumnValues(0, provinceList, false));
+        indexes.push(this.getIndex('province', code));
+      }
+      if (columnsNum >= 2) {
+        stack.push(picker.setColumnValues(1, cityList, false));
+        indexes.push(this.getIndex('city', code));
+        if (cityList.length && code.slice(2, 4) === '00') {
+          [{ code }] = cityList;
+        }
+      }
+      if (columnsNum === 3) {
+        stack.push(
+          picker.setColumnValues(
+            2,
+            this.getList('county', code.slice(0, 4)),
+            false
+          )
+        );
+        indexes.push(this.getIndex('county', code));
+      }
+      return Promise.all(stack)
+        .catch(() => {})
+        .then(() => picker.setIndexes(indexes))
+        .catch(() => {});
+    },
+    getDefaultCode() {
+      const { columnsPlaceholder } = this.data;
+      if (columnsPlaceholder.length) {
+        return EMPTY_CODE;
+      }
+      const countyCodes = Object.keys(this.getConfig('county'));
+      if (countyCodes[0]) {
+        return countyCodes[0];
+      }
+      const cityCodes = Object.keys(this.getConfig('city'));
+      if (cityCodes[0]) {
+        return cityCodes[0];
+      }
+      return '';
+    },
+    getValues() {
+      const picker = this.getPicker();
+      if (!picker) {
+        return [];
+      }
+      return this.parseValues(picker.getValues().filter((value) => !!value));
+    },
+    getDetail() {
+      const values = this.getValues();
+      const area = {
+        code: '',
+        country: '',
+        province: '',
+        city: '',
+        county: '',
+      };
+      if (!values.length) {
+        return area;
+      }
+      const names = values.map((item) => item.name);
+      area.code = values[values.length - 1].code;
+      if (area.code[0] === '9') {
+        area.country = names[1] || '';
+        area.province = names[2] || '';
+      } else {
+        area.province = names[0] || '';
+        area.city = names[1] || '';
+        area.county = names[2] || '';
+      }
+      return area;
+    },
+    reset(code) {
+      this.code = code || '';
+      return this.setValues();
+    },
+  },
+});

+ 6 - 0
src/ttcomponents/vant/area/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-picker": "../picker/index"
+  }
+}

+ 246 - 0
src/ttcomponents/vant/area/index.vue

@@ -0,0 +1,246 @@
+<template>
+<uni-shadow-root class="vant-area-index"><van-picker class="van-area__picker" active-class="active-class" toolbar-class="toolbar-class" column-class="column-class" show-toolbar value-key="name" :title="title" :loading="loading" :columns="computed.displayColumns(columns, columnsNum)" :item-height="itemHeight" :visible-item-count="visibleItemCount" :cancel-button-text="cancelButtonText" :confirm-button-text="confirmButtonText" @change="onChange" @confirm="onConfirm" @cancel="onCancel"></van-picker></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanPicker from '../picker/index.vue'
+global['__wxVueOptions'] = {components:{'van-picker': VanPicker}}
+
+global['__wxRoute'] = 'vant/area/index'
+import { VantComponent } from '../common/component';
+import { pickerProps } from '../picker/shared';
+import { requestAnimationFrame } from '../common/utils';
+const EMPTY_CODE = '000000';
+VantComponent({
+  classes: ['active-class', 'toolbar-class', 'column-class'],
+  props: Object.assign(Object.assign({}, pickerProps), {
+    value: {
+      type: String,
+      observer(value) {
+        this.code = value;
+        this.setValues();
+      },
+    },
+    areaList: {
+      type: Object,
+      value: {},
+      observer: 'setValues',
+    },
+    columnsNum: {
+      type: null,
+      value: 3,
+    },
+    columnsPlaceholder: {
+      type: Array,
+      observer(val) {
+        this.setData({
+          typeToColumnsPlaceholder: {
+            province: val[0] || '',
+            city: val[1] || '',
+            county: val[2] || '',
+          },
+        });
+      },
+    },
+  }),
+  data: {
+    columns: [{ values: [] }, { values: [] }, { values: [] }],
+    typeToColumnsPlaceholder: {},
+  },
+  mounted() {
+    requestAnimationFrame(() => {
+      this.setValues();
+    });
+  },
+  methods: {
+    getPicker() {
+      if (this.picker == null) {
+        this.picker = this.selectComponent('.van-area__picker');
+      }
+      return this.picker;
+    },
+    onCancel(event) {
+      this.emit('cancel', event.detail);
+    },
+    onConfirm(event) {
+      const { index } = event.detail;
+      let { value } = event.detail;
+      value = this.parseValues(value);
+      this.emit('confirm', { value, index });
+    },
+    emit(type, detail) {
+      detail.values = detail.value;
+      delete detail.value;
+      this.$emit(type, detail);
+    },
+    parseValues(values) {
+      const { columnsPlaceholder } = this.data;
+      return values.map((value, index) => {
+        if (
+          value &&
+          (!value.code || value.name === columnsPlaceholder[index])
+        ) {
+          return Object.assign(Object.assign({}, value), {
+            code: '',
+            name: '',
+          });
+        }
+        return value;
+      });
+    },
+    onChange(event) {
+      const { index, picker, value } = event.detail;
+      this.code = value[index].code;
+      this.setValues().then(() => {
+        this.$emit('change', {
+          picker,
+          values: this.parseValues(picker.getValues()),
+          index,
+        });
+      });
+    },
+    getConfig(type) {
+      const { areaList } = this.data;
+      return (areaList && areaList[`${type}_list`]) || {};
+    },
+    getList(type, code) {
+      if (type !== 'province' && !code) {
+        return [];
+      }
+      const { typeToColumnsPlaceholder } = this.data;
+      const list = this.getConfig(type);
+      let result = Object.keys(list).map((code) => ({
+        code,
+        name: list[code],
+      }));
+      if (code != null) {
+        // oversea code
+        if (code[0] === '9' && type === 'city') {
+          code = '9';
+        }
+        result = result.filter((item) => item.code.indexOf(code) === 0);
+      }
+      if (typeToColumnsPlaceholder[type] && result.length) {
+        // set columns placeholder
+        const codeFill =
+          type === 'province'
+            ? ''
+            : type === 'city'
+            ? EMPTY_CODE.slice(2, 4)
+            : EMPTY_CODE.slice(4, 6);
+        result.unshift({
+          code: `${code}${codeFill}`,
+          name: typeToColumnsPlaceholder[type],
+        });
+      }
+      return result;
+    },
+    getIndex(type, code) {
+      let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
+      const list = this.getList(type, code.slice(0, compareNum - 2));
+      // oversea code
+      if (code[0] === '9' && type === 'province') {
+        compareNum = 1;
+      }
+      code = code.slice(0, compareNum);
+      for (let i = 0; i < list.length; i++) {
+        if (list[i].code.slice(0, compareNum) === code) {
+          return i;
+        }
+      }
+      return 0;
+    },
+    setValues() {
+      const picker = this.getPicker();
+      if (!picker) {
+        return;
+      }
+      let code = this.code || this.getDefaultCode();
+      const provinceList = this.getList('province');
+      const cityList = this.getList('city', code.slice(0, 2));
+      const stack = [];
+      const indexes = [];
+      const { columnsNum } = this.data;
+      if (columnsNum >= 1) {
+        stack.push(picker.setColumnValues(0, provinceList, false));
+        indexes.push(this.getIndex('province', code));
+      }
+      if (columnsNum >= 2) {
+        stack.push(picker.setColumnValues(1, cityList, false));
+        indexes.push(this.getIndex('city', code));
+        if (cityList.length && code.slice(2, 4) === '00') {
+          [{ code }] = cityList;
+        }
+      }
+      if (columnsNum === 3) {
+        stack.push(
+          picker.setColumnValues(
+            2,
+            this.getList('county', code.slice(0, 4)),
+            false
+          )
+        );
+        indexes.push(this.getIndex('county', code));
+      }
+      return Promise.all(stack)
+        .catch(() => {})
+        .then(() => picker.setIndexes(indexes))
+        .catch(() => {});
+    },
+    getDefaultCode() {
+      const { columnsPlaceholder } = this.data;
+      if (columnsPlaceholder.length) {
+        return EMPTY_CODE;
+      }
+      const countyCodes = Object.keys(this.getConfig('county'));
+      if (countyCodes[0]) {
+        return countyCodes[0];
+      }
+      const cityCodes = Object.keys(this.getConfig('city'));
+      if (cityCodes[0]) {
+        return cityCodes[0];
+      }
+      return '';
+    },
+    getValues() {
+      const picker = this.getPicker();
+      if (!picker) {
+        return [];
+      }
+      return this.parseValues(picker.getValues().filter((value) => !!value));
+    },
+    getDetail() {
+      const values = this.getValues();
+      const area = {
+        code: '',
+        country: '',
+        province: '',
+        city: '',
+        county: '',
+      };
+      if (!values.length) {
+        return area;
+      }
+      const names = values.map((item) => item.name);
+      area.code = values[values.length - 1].code;
+      if (area.code[0] === '9') {
+        area.country = names[1] || '';
+        area.province = names[2] || '';
+      } else {
+        area.province = names[0] || '';
+        area.city = names[1] || '';
+        area.county = names[2] || '';
+      }
+      return area;
+    },
+    reset(code) {
+      this.code = code || '';
+      return this.setValues();
+    },
+  },
+});
+export default global['__wxComponents']['vant/area/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';
+</style>

+ 20 - 0
src/ttcomponents/vant/area/index.wxml

@@ -0,0 +1,20 @@
+<wxs src="./index.wxs" module="computed" />
+
+<van-picker
+  class="van-area__picker"
+  active-class="active-class"
+  toolbar-class="toolbar-class"
+  column-class="column-class"
+  show-toolbar
+  value-key="name"
+  title="{{ title }}"
+  loading="{{ loading }}"
+  columns="{{ computed.displayColumns(columns, columnsNum) }}"
+  item-height="{{ itemHeight }}"
+  visible-item-count="{{ visibleItemCount }}"
+  cancel-button-text="{{ cancelButtonText }}"
+  confirm-button-text="{{ confirmButtonText }}"
+  bind:change="onChange"
+  bind:confirm="onConfirm"
+  bind:cancel="onCancel"
+/>

+ 8 - 0
src/ttcomponents/vant/area/index.wxs

@@ -0,0 +1,8 @@
+/* eslint-disable */
+function displayColumns(columns, columnsNum) {
+  return columns.slice(0, +columnsNum);
+}
+
+module.exports = {
+  displayColumns: displayColumns,
+};

+ 1 - 0
src/ttcomponents/vant/area/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';

+ 1 - 0
src/ttcomponents/vant/button/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 58 - 0
src/ttcomponents/vant/button/index.js

@@ -0,0 +1,58 @@
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+import { openType } from '../mixins/open-type';
+import { canIUseFormFieldButton } from '../common/version';
+const mixins = [button, openType];
+if (canIUseFormFieldButton()) {
+  mixins.push('wx://form-field-button');
+}
+VantComponent({
+  mixins,
+  classes: ['hover-class', 'loading-class'],
+  data: {
+    baseStyle: '',
+  },
+  props: {
+    formType: String,
+    icon: String,
+    classPrefix: {
+      type: String,
+      value: 'van-icon',
+    },
+    plain: Boolean,
+    block: Boolean,
+    round: Boolean,
+    square: Boolean,
+    loading: Boolean,
+    hairline: Boolean,
+    disabled: Boolean,
+    loadingText: String,
+    customStyle: String,
+    loadingType: {
+      type: String,
+      value: 'circular',
+    },
+    type: {
+      type: String,
+      value: 'default',
+    },
+    dataset: null,
+    size: {
+      type: String,
+      value: 'normal',
+    },
+    loadingSize: {
+      type: String,
+      value: '20px',
+    },
+    color: String,
+  },
+  methods: {
+    onClick() {
+      if (!this.data.loading) {
+        this.$emit('click');
+      }
+    },
+    noop() {},
+  },
+});

+ 7 - 0
src/ttcomponents/vant/button/index.json

@@ -0,0 +1,7 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index",
+    "van-loading": "../loading/index"
+  }
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 84 - 0
src/ttcomponents/vant/button/index.vue


+ 53 - 0
src/ttcomponents/vant/button/index.wxml

@@ -0,0 +1,53 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
+
+<button
+  id="{{ id }}"
+  data-detail="{{ dataset }}"
+  class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
+  hover-class="van-button--active hover-class"
+  lang="{{ lang }}"
+  form-type="{{ formType }}"
+  style="{{ computed.rootStyle({ plain, color, customStyle }) }}"
+  open-type="{{ disabled ? '' : openType }}"
+  business-id="{{ businessId }}"
+  session-from="{{ sessionFrom }}"
+  send-message-title="{{ sendMessageTitle }}"
+  send-message-path="{{ sendMessagePath }}"
+  send-message-img="{{ sendMessageImg }}"
+  show-message-card="{{ showMessageCard }}"
+  app-parameter="{{ appParameter }}"
+  aria-label="{{ ariaLabel }}"
+  bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
+  bindgetuserinfo="bindGetUserInfo"
+  bindcontact="bindContact"
+  bindgetphonenumber="bindGetPhoneNumber"
+  binderror="bindError"
+  bindlaunchapp="bindLaunchApp"
+  bindopensetting="bindOpenSetting"
+>
+  <block wx:if="{{ loading }}">
+    <van-loading
+      custom-class="loading-class"
+      size="{{ loadingSize }}"
+      type="{{ loadingType }}"
+      color="{{ computed.loadingColor({ type, color, plain }) }}"
+    />
+    <view wx:if="{{ loadingText }}" class="van-button__loading-text">
+      {{ loadingText }}
+    </view>
+  </block>
+  <block wx:else>
+    <van-icon
+      wx:if="{{ icon }}"
+      size="1.2em"
+      name="{{ icon }}"
+      class-prefix="{{ classPrefix }}"
+      class="van-button__icon"
+      custom-style="line-height: inherit;"
+    />
+    <view class="van-button__text">
+      <slot />
+    </view>
+  </block>
+</button>

+ 39 - 0
src/ttcomponents/vant/button/index.wxs

@@ -0,0 +1,39 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+
+function rootStyle(data) {
+  if (!data.color) {
+    return data.customStyle;
+  }
+
+  var properties = {
+    color: data.plain ? data.color : '#fff',
+    background: data.plain ? null : data.color,
+  };
+
+  // hide border when color is linear-gradient
+  if (data.color.indexOf('gradient') !== -1) {
+    properties.border = 0;
+  } else {
+    properties['border-color'] = data.color;
+  }
+
+  return style([properties, data.customStyle]);
+}
+
+function loadingColor(data) {
+  if (data.plain) {
+    return data.color ? data.color : '#c9c9c9';
+  }
+
+  if (data.type === 'default') {
+    return '#c9c9c9';
+  }
+
+  return '#fff';
+}
+
+module.exports = {
+  rootStyle: rootStyle,
+  loadingColor: loadingColor,
+};

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
src/ttcomponents/vant/button/index.wxss


+ 37 - 0
src/ttcomponents/vant/calendar/calendar.vue

@@ -0,0 +1,37 @@
+<template>
+<uni-shadow-root class="vant-calendar-calendar"><view class="van-calendar">
+  <header :title="title" :showTitle="showTitle" :subtitle="subtitle" :showSubtitle="showSubtitle">
+    <slot name="title" slot="title"></slot>
+  </header>
+
+  <scroll-view class="van-calendar__body" scroll-y :scroll-into-view="scrollIntoView">
+    <month v-for="(item,index) in (computed.getMonths(minDate, maxDate))" :key="item.index" :id="'month'+(index)" class="month" :data-date="item" :date="item" :type="type" :color="color" :minDate="minDate" :maxDate="maxDate" :showMark="showMark" :formatter="formatter" :rowHeight="rowHeight" :currentDate="currentDate" :showSubtitle="showSubtitle" :allowSameDay="allowSameDay" :showMonthTitle="index !== 0 || !showSubtitle" @click="onClickDay"></month>
+  </scroll-view>
+
+  <view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
+    <slot name="footer"></slot>
+  </view>
+
+  <view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
+    <van-button v-if="showConfirm" round block type="danger" :color="color" custom-class="van-calendar__confirm" :disabled="computed.getButtonDisabled(type, currentDate)" nativeType="text" @click="onConfirm">
+      {{
+        computed.getButtonDisabled(type, currentDate)
+          ? confirmDisabledText
+          : confirmText
+      }}
+    </van-button>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/calendar/calendar'
+
+Component({})
+
+export default global['__wxComponents']['vant/calendar/calendar']
+</script>
+<style platform="mp-weixin">
+
+</style>

+ 65 - 0
src/ttcomponents/vant/calendar/calendar.wxml

@@ -0,0 +1,65 @@
+<view class="van-calendar">
+  <header
+    title="{{ title }}"
+    showTitle="{{ showTitle }}"
+    subtitle="{{ subtitle }}"
+    showSubtitle="{{ showSubtitle }}"
+  >
+    <slot name="title" slot="title"></slot>
+  </header>
+
+  <scroll-view
+    class="van-calendar__body"
+    scroll-y
+    scroll-into-view="{{ scrollIntoView }}"
+  >
+    <month
+      wx:for="{{ computed.getMonths(minDate, maxDate) }}"
+      wx:key="index"
+      id="month{{ index }}"
+      class="month"
+      data-date="{{ item }}"
+      date="{{ item }}"
+      type="{{ type }}"
+      color="{{ color }}"
+      minDate="{{ minDate }}"
+      maxDate="{{ maxDate }}"
+      showMark="{{ showMark }}"
+      formatter="{{ formatter }}"
+      rowHeight="{{ rowHeight }}"
+      currentDate="{{ currentDate }}"
+      showSubtitle="{{ showSubtitle }}"
+      allowSameDay="{{ allowSameDay }}"
+      showMonthTitle="{{ index !== 0 || !showSubtitle }}"
+      bind:click="onClickDay"
+    />
+  </scroll-view>
+
+  <view
+    class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
+  >
+    <slot name="footer"></slot>
+  </view>
+
+  <view
+    class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
+  >
+    <van-button
+      wx:if="{{ showConfirm }}"
+      round
+      block
+      type="danger"
+      color="{{ color }}"
+      custom-class="van-calendar__confirm"
+      disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
+      nativeType="text"
+      bind:click="onConfirm"
+    >
+      {{
+        computed.getButtonDisabled(type, currentDate)
+          ? confirmDisabledText
+          : confirmText
+      }}
+    </van-button>
+  </view>
+</view>

+ 1 - 0
src/ttcomponents/vant/calendar/components/header/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 16 - 0
src/ttcomponents/vant/calendar/components/header/index.js

@@ -0,0 +1,16 @@
+import { VantComponent } from '../../../common/component';
+VantComponent({
+  props: {
+    title: {
+      type: String,
+      value: '日期选择',
+    },
+    subtitle: String,
+    showTitle: Boolean,
+    showSubtitle: Boolean,
+  },
+  data: {
+    weekdays: ['日', '一', '二', '三', '四', '五', '六'],
+  },
+  methods: {},
+});

+ 3 - 0
src/ttcomponents/vant/calendar/components/header/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 43 - 0
src/ttcomponents/vant/calendar/components/header/index.vue

@@ -0,0 +1,43 @@
+<template>
+<uni-shadow-root class="vant-calendar-components-header-index"><view class="van-calendar__header">
+  <block v-if="showTitle">
+    <view class="van-calendar__header-title"><slot name="title"></slot></view>
+    <view class="van-calendar__header-title">{{ title }}</view>
+  </block>
+
+  <view v-if="showSubtitle" class="van-calendar__header-subtitle">
+    {{ subtitle }}
+  </view>
+
+  <view class="van-calendar__weekdays">
+    <view v-for="(item,index) in (weekdays)" :key="item.index" class="van-calendar__weekday">
+      {{ item }}
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/calendar/components/header/index'
+import { VantComponent } from '../../../common/component';
+VantComponent({
+  props: {
+    title: {
+      type: String,
+      value: '日期选择',
+    },
+    subtitle: String,
+    showTitle: Boolean,
+    showSubtitle: Boolean,
+  },
+  data: {
+    weekdays: ['日', '一', '二', '三', '四', '五', '六'],
+  },
+  methods: {},
+});
+export default global['__wxComponents']['vant/calendar/components/header/index']
+</script>
+<style platform="mp-weixin">
+@import '../../../common/index.css';.van-calendar__header{-webkit-flex-shrink:0;flex-shrink:0;box-shadow:0 2px 10px rgba(125,126,128,.16);box-shadow:var(--calendar-header-box-shadow,0 2px 10px rgba(125,126,128,.16))}.van-calendar__header-subtitle,.van-calendar__header-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:-webkit-flex;display:flex}.van-calendar__weekday{-webkit-flex:1;flex:1;text-align:center;font-size:12px;font-size:var(--calendar-weekdays-font-size,12px);line-height:30px;line-height:var(--calendar-weekdays-height,30px)}
+</style>

+ 16 - 0
src/ttcomponents/vant/calendar/components/header/index.wxml

@@ -0,0 +1,16 @@
+<view class="van-calendar__header">
+  <block wx:if="{{ showTitle }}">
+    <view class="van-calendar__header-title"><slot name="title"></slot></view>
+    <view class="van-calendar__header-title">{{ title }}</view>
+  </block>
+
+  <view wx:if="{{ showSubtitle }}" class="van-calendar__header-subtitle">
+    {{ subtitle }}
+  </view>
+
+  <view class="van-calendar__weekdays">
+    <view wx:for="{{ weekdays }}" wx:key="index" class="van-calendar__weekday">
+      {{ item }}
+    </view>
+  </view>
+</view>

+ 1 - 0
src/ttcomponents/vant/calendar/components/header/index.wxss

@@ -0,0 +1 @@
+@import '../../../common/index.wxss';.van-calendar__header{-webkit-flex-shrink:0;flex-shrink:0;box-shadow:0 2px 10px rgba(125,126,128,.16);box-shadow:var(--calendar-header-box-shadow,0 2px 10px rgba(125,126,128,.16))}.van-calendar__header-subtitle,.van-calendar__header-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:-webkit-flex;display:flex}.van-calendar__weekday{-webkit-flex:1;flex:1;text-align:center;font-size:12px;font-size:var(--calendar-weekdays-font-size,12px);line-height:30px;line-height:var(--calendar-weekdays-height,30px)}

+ 1 - 0
src/ttcomponents/vant/calendar/components/month/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 157 - 0
src/ttcomponents/vant/calendar/components/month/index.js

@@ -0,0 +1,157 @@
+import { VantComponent } from '../../../common/component';
+import {
+  getMonthEndDay,
+  compareDay,
+  getPrevDay,
+  getNextDay,
+} from '../../utils';
+VantComponent({
+  props: {
+    date: {
+      type: null,
+      observer: 'setDays',
+    },
+    type: {
+      type: String,
+      observer: 'setDays',
+    },
+    color: String,
+    minDate: {
+      type: null,
+      observer: 'setDays',
+    },
+    maxDate: {
+      type: null,
+      observer: 'setDays',
+    },
+    showMark: Boolean,
+    rowHeight: null,
+    formatter: {
+      type: null,
+      observer: 'setDays',
+    },
+    currentDate: {
+      type: null,
+      observer: 'setDays',
+    },
+    allowSameDay: Boolean,
+    showSubtitle: Boolean,
+    showMonthTitle: Boolean,
+  },
+  data: {
+    visible: true,
+    days: [],
+  },
+  methods: {
+    onClick(event) {
+      const { index } = event.currentTarget.dataset;
+      const item = this.data.days[index];
+      if (item.type !== 'disabled') {
+        this.$emit('click', item);
+      }
+    },
+    setDays() {
+      const days = [];
+      const startDate = new Date(this.data.date);
+      const year = startDate.getFullYear();
+      const month = startDate.getMonth();
+      const totalDay = getMonthEndDay(
+        startDate.getFullYear(),
+        startDate.getMonth() + 1
+      );
+      for (let day = 1; day <= totalDay; day++) {
+        const date = new Date(year, month, day);
+        const type = this.getDayType(date);
+        let config = {
+          date,
+          type,
+          text: day,
+          bottomInfo: this.getBottomInfo(type),
+        };
+        if (this.data.formatter) {
+          config = this.data.formatter(config);
+        }
+        days.push(config);
+      }
+      this.setData({ days });
+    },
+    getMultipleDayType(day) {
+      const { currentDate } = this.data;
+      if (!Array.isArray(currentDate)) {
+        return '';
+      }
+      const isSelected = (date) =>
+        currentDate.some((item) => compareDay(item, date) === 0);
+      if (isSelected(day)) {
+        const prevDay = getPrevDay(day);
+        const nextDay = getNextDay(day);
+        const prevSelected = isSelected(prevDay);
+        const nextSelected = isSelected(nextDay);
+        if (prevSelected && nextSelected) {
+          return 'multiple-middle';
+        }
+        if (prevSelected) {
+          return 'end';
+        }
+        return nextSelected ? 'start' : 'multiple-selected';
+      }
+      return '';
+    },
+    getRangeDayType(day) {
+      const { currentDate, allowSameDay } = this.data;
+      if (!Array.isArray(currentDate)) {
+        return;
+      }
+      const [startDay, endDay] = currentDate;
+      if (!startDay) {
+        return;
+      }
+      const compareToStart = compareDay(day, startDay);
+      if (!endDay) {
+        return compareToStart === 0 ? 'start' : '';
+      }
+      const compareToEnd = compareDay(day, endDay);
+      if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
+        return 'start-end';
+      }
+      if (compareToStart === 0) {
+        return 'start';
+      }
+      if (compareToEnd === 0) {
+        return 'end';
+      }
+      if (compareToStart > 0 && compareToEnd < 0) {
+        return 'middle';
+      }
+    },
+    getDayType(day) {
+      const { type, minDate, maxDate, currentDate } = this.data;
+      if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
+        return 'disabled';
+      }
+      if (type === 'single') {
+        return compareDay(day, currentDate) === 0 ? 'selected' : '';
+      }
+      if (type === 'multiple') {
+        return this.getMultipleDayType(day);
+      }
+      /* istanbul ignore else */
+      if (type === 'range') {
+        return this.getRangeDayType(day);
+      }
+    },
+    getBottomInfo(type) {
+      if (this.data.type === 'range') {
+        if (type === 'start') {
+          return '开始';
+        }
+        if (type === 'end') {
+          return '结束';
+        }
+        if (type === 'start-end') {
+          return '开始/结束';
+        }
+      }
+    },
+  },
+});

+ 3 - 0
src/ttcomponents/vant/calendar/components/month/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 195 - 0
src/ttcomponents/vant/calendar/components/month/index.vue


+ 39 - 0
src/ttcomponents/vant/calendar/components/month/index.wxml

@@ -0,0 +1,39 @@
+<wxs src="./index.wxs" module="computed"></wxs>
+<wxs src="../../../wxs/utils.wxs" module="utils" />
+
+<view class="van-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
+  <view wx:if="{{ showMonthTitle }}" class="van-calendar__month-title">
+    {{ computed.formatMonthTitle(date) }}
+  </view>
+
+  <view wx:if="{{ visible }}" class="van-calendar__days">
+    <view wx:if="{{ showMark }}" class="van-calendar__month-mark">
+      {{ computed.getMark(date) }}
+    </view>
+
+    <view
+      wx:for="{{ days }}"
+      wx:key="index"
+      style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color) }}"
+      class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
+      data-index="{{ index }}"
+      bindtap="onClick"
+    >
+      <view wx:if="{{ item.type === 'selected' }}" class="van-calendar__selected-day" style="background: {{ color }}">
+        <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
+        {{ item.text }}
+        <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
+          {{ item.bottomInfo }}
+        </view>
+      </view>
+
+      <view wx:else>
+        <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
+        {{ item.text }}
+        <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
+          {{ item.bottomInfo }}
+        </view>
+      </view>
+    </view>
+  </view>
+</view>

+ 67 - 0
src/ttcomponents/vant/calendar/components/month/index.wxs

@@ -0,0 +1,67 @@
+/* eslint-disable */
+var utils = require('../../utils.wxs');
+
+function getMark(date) {
+  return getDate(date).getMonth() + 1;
+}
+
+var ROW_HEIGHT = 64;
+
+function getDayStyle(type, index, date, rowHeight, color) {
+  var style = [];
+  var offset = getDate(date).getDay();
+
+  if (index === 0) {
+    style.push(['margin-left', (100 * offset) / 7 + '%']);
+  }
+
+  if (rowHeight !== ROW_HEIGHT) {
+    style.push(['height', rowHeight + 'px']);
+  }
+
+  if (color) {
+    if (
+      type === 'start' ||
+      type === 'end' ||
+      type === 'multiple-selected' ||
+      type === 'multiple-middle'
+    ) {
+      style.push(['background', color]);
+    } else if (type === 'middle') {
+      style.push(['color', color]);
+    }
+  }
+
+  return style
+    .map(function(item) {
+      return item.join(':');
+    })
+    .join(';');
+}
+
+function formatMonthTitle(date) {
+  date = getDate(date);
+  return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
+}
+
+function getMonthStyle(visible, date, rowHeight) {
+  if (!visible) {
+    date = getDate(date);
+
+    var totalDay = utils.getMonthEndDay(
+      date.getFullYear(),
+      date.getMonth() + 1
+    );
+    var offset = getDate(date).getDay();
+    var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
+
+    return 'padding-bottom:' + padding + 'px';
+  }
+}
+
+module.exports = {
+  getMark: getMark,
+  getDayStyle: getDayStyle,
+  formatMonthTitle: formatMonthTitle,
+  getMonthStyle: getMonthStyle
+};

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
src/ttcomponents/vant/calendar/components/month/index.wxss


+ 1 - 0
src/ttcomponents/vant/calendar/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 297 - 0
src/ttcomponents/vant/calendar/index.js

@@ -0,0 +1,297 @@
+import { VantComponent } from '../common/component';
+import {
+  ROW_HEIGHT,
+  getNextDay,
+  compareDay,
+  copyDates,
+  calcDateNum,
+  formatMonthTitle,
+  compareMonth,
+  getMonths,
+  getDayByOffset,
+} from './utils';
+import Toast from '../toast/toast';
+import { requestAnimationFrame } from '../common/utils';
+VantComponent({
+  props: {
+    title: {
+      type: String,
+      value: '日期选择',
+    },
+    color: String,
+    show: {
+      type: Boolean,
+      observer(val) {
+        if (val) {
+          this.initRect();
+          this.scrollIntoView();
+        }
+      },
+    },
+    formatter: null,
+    confirmText: {
+      type: String,
+      value: '确定',
+    },
+    rangePrompt: String,
+    defaultDate: {
+      type: null,
+      observer(val) {
+        this.setData({ currentDate: val });
+        this.scrollIntoView();
+      },
+    },
+    allowSameDay: Boolean,
+    confirmDisabledText: String,
+    type: {
+      type: String,
+      value: 'single',
+      observer: 'reset',
+    },
+    minDate: {
+      type: null,
+      value: Date.now(),
+    },
+    maxDate: {
+      type: null,
+      value: new Date(
+        new Date().getFullYear(),
+        new Date().getMonth() + 6,
+        new Date().getDate()
+      ).getTime(),
+    },
+    position: {
+      type: String,
+      value: 'bottom',
+    },
+    rowHeight: {
+      type: null,
+      value: ROW_HEIGHT,
+    },
+    round: {
+      type: Boolean,
+      value: true,
+    },
+    poppable: {
+      type: Boolean,
+      value: true,
+    },
+    showMark: {
+      type: Boolean,
+      value: true,
+    },
+    showTitle: {
+      type: Boolean,
+      value: true,
+    },
+    showConfirm: {
+      type: Boolean,
+      value: true,
+    },
+    showSubtitle: {
+      type: Boolean,
+      value: true,
+    },
+    safeAreaInsetBottom: {
+      type: Boolean,
+      value: true,
+    },
+    closeOnClickOverlay: {
+      type: Boolean,
+      value: true,
+    },
+    maxRange: {
+      type: null,
+      value: null,
+    },
+  },
+  data: {
+    subtitle: '',
+    currentDate: null,
+    scrollIntoView: '',
+  },
+  created() {
+    this.setData({
+      currentDate: this.getInitialDate(),
+    });
+  },
+  mounted() {
+    if (this.data.show || !this.data.poppable) {
+      this.initRect();
+      this.scrollIntoView();
+    }
+  },
+  methods: {
+    reset() {
+      this.setData({ currentDate: this.getInitialDate() });
+      this.scrollIntoView();
+    },
+    initRect() {
+      if (this.contentObserver != null) {
+        this.contentObserver.disconnect();
+      }
+      const contentObserver = this.createIntersectionObserver({
+        thresholds: [0, 0.1, 0.9, 1],
+        observeAll: true,
+      });
+      this.contentObserver = contentObserver;
+      contentObserver.relativeTo('.van-calendar__body');
+      contentObserver.observe('.month', (res) => {
+        if (res.boundingClientRect.top <= res.relativeRect.top) {
+          // @ts-ignore
+          this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
+        }
+      });
+    },
+    getInitialDate() {
+      const { type, defaultDate, minDate } = this.data;
+      if (type === 'range') {
+        const [startDay, endDay] = defaultDate || [];
+        return [
+          startDay || minDate,
+          endDay || getNextDay(new Date(minDate)).getTime(),
+        ];
+      }
+      if (type === 'multiple') {
+        return defaultDate || [minDate];
+      }
+      return defaultDate || minDate;
+    },
+    scrollIntoView() {
+      requestAnimationFrame(() => {
+        const {
+          currentDate,
+          type,
+          show,
+          poppable,
+          minDate,
+          maxDate,
+        } = this.data;
+        // @ts-ignore
+        const targetDate = type === 'single' ? currentDate : currentDate[0];
+        const displayed = show || !poppable;
+        if (!targetDate || !displayed) {
+          return;
+        }
+        const months = getMonths(minDate, maxDate);
+        months.some((month, index) => {
+          if (compareMonth(month, targetDate) === 0) {
+            this.setData({ scrollIntoView: `month${index}` });
+            return true;
+          }
+          return false;
+        });
+      });
+    },
+    onOpen() {
+      this.$emit('open');
+    },
+    onOpened() {
+      this.$emit('opened');
+    },
+    onClose() {
+      this.$emit('close');
+    },
+    onClosed() {
+      this.$emit('closed');
+    },
+    onClickDay(event) {
+      const { date } = event.detail;
+      const { type, currentDate, allowSameDay } = this.data;
+      if (type === 'range') {
+        // @ts-ignore
+        const [startDay, endDay] = currentDate;
+        if (startDay && !endDay) {
+          const compareToStart = compareDay(date, startDay);
+          if (compareToStart === 1) {
+            this.select([startDay, date], true);
+          } else if (compareToStart === -1) {
+            this.select([date, null]);
+          } else if (allowSameDay) {
+            this.select([date, date]);
+          }
+        } else {
+          this.select([date, null]);
+        }
+      } else if (type === 'multiple') {
+        let selectedIndex;
+        // @ts-ignore
+        const selected = currentDate.some((dateItem, index) => {
+          const equal = compareDay(dateItem, date) === 0;
+          if (equal) {
+            selectedIndex = index;
+          }
+          return equal;
+        });
+        if (selected) {
+          // @ts-ignore
+          const cancelDate = currentDate.splice(selectedIndex, 1);
+          this.setData({ currentDate });
+          this.unselect(cancelDate);
+        } else {
+          // @ts-ignore
+          this.select([...currentDate, date]);
+        }
+      } else {
+        this.select(date, true);
+      }
+    },
+    unselect(dateArray) {
+      const date = dateArray[0];
+      if (date) {
+        this.$emit('unselect', copyDates(date));
+      }
+    },
+    select(date, complete) {
+      if (complete && this.data.type === 'range') {
+        const valid = this.checkRange(date);
+        if (!valid) {
+          // auto selected to max range if showConfirm
+          if (this.data.showConfirm) {
+            this.emit([
+              date[0],
+              getDayByOffset(date[0], this.data.maxRange - 1),
+            ]);
+          } else {
+            this.emit(date);
+          }
+          return;
+        }
+      }
+      this.emit(date);
+      if (complete && !this.data.showConfirm) {
+        this.onConfirm();
+      }
+    },
+    emit(date) {
+      const getTime = (date) => (date instanceof Date ? date.getTime() : date);
+      this.setData({
+        currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
+      });
+      this.$emit('select', copyDates(date));
+    },
+    checkRange(date) {
+      const { maxRange, rangePrompt } = this.data;
+      if (maxRange && calcDateNum(date) > maxRange) {
+        Toast({
+          context: this,
+          message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
+        });
+        return false;
+      }
+      return true;
+    },
+    onConfirm() {
+      if (
+        this.data.type === 'range' &&
+        !this.checkRange(this.data.currentDate)
+      ) {
+        return;
+      }
+      wx.nextTick(() => {
+        // @ts-ignore
+        this.$emit('confirm', copyDates(this.data.currentDate));
+      });
+    },
+  },
+});

+ 10 - 0
src/ttcomponents/vant/calendar/index.json

@@ -0,0 +1,10 @@
+{
+  "component": true,
+  "usingComponents": {
+    "header": "./components/header/index",
+    "month": "./components/month/index",
+    "van-button": "../button/index",
+    "van-popup": "../popup/index",
+    "van-toast": "../toast/index"
+  }
+}

+ 325 - 0
src/ttcomponents/vant/calendar/index.vue

@@ -0,0 +1,325 @@
+<template>
+<uni-shadow-root class="vant-calendar-index"><van-popup v-if="poppable" :custom-class="'van-calendar__popup--'+(position)" close-icon-class="van-calendar__close-icon" :show="show" :round="round" :position="position" :closeable="showTitle || showSubtitle" :close-on-click-overlay="closeOnClickOverlay" @enter="onOpen" @close="onClose" @after-enter="onOpened" @after-leave="onClosed">
+  <include src="calendar.wxml"></include>
+</van-popup>
+
+<include v-else src="calendar.wxml"></include>
+
+<van-toast id="van-toast"></van-toast></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs><wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+const __wxTemplateComponentProps = {}
+import __wxTemplateComponent0 from './calendar.vue'
+
+import Header from './components/header/index.vue'
+import Month from './components/month/index.vue'
+import VanButton from '../button/index.vue'
+import VanPopup from '../popup/index.vue'
+import VanToast from '../toast/index.vue'
+global['__wxVueOptions'] = {components:{'header': Header,'month': Month,'van-button': VanButton,'van-popup': VanPopup,'van-toast': VanToast,}}
+
+global['__wxRoute'] = 'vant/calendar/index'
+import { VantComponent } from '../common/component';
+import {
+  ROW_HEIGHT,
+  getNextDay,
+  compareDay,
+  copyDates,
+  calcDateNum,
+  formatMonthTitle,
+  compareMonth,
+  getMonths,
+  getDayByOffset,
+} from './utils';
+import Toast from '../toast/toast';
+import { requestAnimationFrame } from '../common/utils';
+VantComponent({
+  props: {
+    title: {
+      type: String,
+      value: '日期选择',
+    },
+    color: String,
+    show: {
+      type: Boolean,
+      observer(val) {
+        if (val) {
+          this.initRect();
+          this.scrollIntoView();
+        }
+      },
+    },
+    formatter: null,
+    confirmText: {
+      type: String,
+      value: '确定',
+    },
+    rangePrompt: String,
+    defaultDate: {
+      type: null,
+      observer(val) {
+        this.setData({ currentDate: val });
+        this.scrollIntoView();
+      },
+    },
+    allowSameDay: Boolean,
+    confirmDisabledText: String,
+    type: {
+      type: String,
+      value: 'single',
+      observer: 'reset',
+    },
+    minDate: {
+      type: null,
+      value: Date.now(),
+    },
+    maxDate: {
+      type: null,
+      value: new Date(
+        new Date().getFullYear(),
+        new Date().getMonth() + 6,
+        new Date().getDate()
+      ).getTime(),
+    },
+    position: {
+      type: String,
+      value: 'bottom',
+    },
+    rowHeight: {
+      type: null,
+      value: ROW_HEIGHT,
+    },
+    round: {
+      type: Boolean,
+      value: true,
+    },
+    poppable: {
+      type: Boolean,
+      value: true,
+    },
+    showMark: {
+      type: Boolean,
+      value: true,
+    },
+    showTitle: {
+      type: Boolean,
+      value: true,
+    },
+    showConfirm: {
+      type: Boolean,
+      value: true,
+    },
+    showSubtitle: {
+      type: Boolean,
+      value: true,
+    },
+    safeAreaInsetBottom: {
+      type: Boolean,
+      value: true,
+    },
+    closeOnClickOverlay: {
+      type: Boolean,
+      value: true,
+    },
+    maxRange: {
+      type: null,
+      value: null,
+    },
+  },
+  data: {
+    subtitle: '',
+    currentDate: null,
+    scrollIntoView: '',
+  },
+  created() {
+    this.setData({
+      currentDate: this.getInitialDate(),
+    });
+  },
+  mounted() {
+    if (this.data.show || !this.data.poppable) {
+      this.initRect();
+      this.scrollIntoView();
+    }
+  },
+  methods: {
+    reset() {
+      this.setData({ currentDate: this.getInitialDate() });
+      this.scrollIntoView();
+    },
+    initRect() {
+      if (this.contentObserver != null) {
+        this.contentObserver.disconnect();
+      }
+      const contentObserver = this.createIntersectionObserver({
+        thresholds: [0, 0.1, 0.9, 1],
+        observeAll: true,
+      });
+      this.contentObserver = contentObserver;
+      contentObserver.relativeTo('.van-calendar__body');
+      contentObserver.observe('.month', (res) => {
+        if (res.boundingClientRect.top <= res.relativeRect.top) {
+          // @ts-ignore
+          this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
+        }
+      });
+    },
+    getInitialDate() {
+      const { type, defaultDate, minDate } = this.data;
+      if (type === 'range') {
+        const [startDay, endDay] = defaultDate || [];
+        return [
+          startDay || minDate,
+          endDay || getNextDay(new Date(minDate)).getTime(),
+        ];
+      }
+      if (type === 'multiple') {
+        return defaultDate || [minDate];
+      }
+      return defaultDate || minDate;
+    },
+    scrollIntoView() {
+      requestAnimationFrame(() => {
+        const {
+          currentDate,
+          type,
+          show,
+          poppable,
+          minDate,
+          maxDate,
+        } = this.data;
+        // @ts-ignore
+        const targetDate = type === 'single' ? currentDate : currentDate[0];
+        const displayed = show || !poppable;
+        if (!targetDate || !displayed) {
+          return;
+        }
+        const months = getMonths(minDate, maxDate);
+        months.some((month, index) => {
+          if (compareMonth(month, targetDate) === 0) {
+            this.setData({ scrollIntoView: `month${index}` });
+            return true;
+          }
+          return false;
+        });
+      });
+    },
+    onOpen() {
+      this.$emit('open');
+    },
+    onOpened() {
+      this.$emit('opened');
+    },
+    onClose() {
+      this.$emit('close');
+    },
+    onClosed() {
+      this.$emit('closed');
+    },
+    onClickDay(event) {
+      const { date } = event.detail;
+      const { type, currentDate, allowSameDay } = this.data;
+      if (type === 'range') {
+        // @ts-ignore
+        const [startDay, endDay] = currentDate;
+        if (startDay && !endDay) {
+          const compareToStart = compareDay(date, startDay);
+          if (compareToStart === 1) {
+            this.select([startDay, date], true);
+          } else if (compareToStart === -1) {
+            this.select([date, null]);
+          } else if (allowSameDay) {
+            this.select([date, date]);
+          }
+        } else {
+          this.select([date, null]);
+        }
+      } else if (type === 'multiple') {
+        let selectedIndex;
+        // @ts-ignore
+        const selected = currentDate.some((dateItem, index) => {
+          const equal = compareDay(dateItem, date) === 0;
+          if (equal) {
+            selectedIndex = index;
+          }
+          return equal;
+        });
+        if (selected) {
+          // @ts-ignore
+          const cancelDate = currentDate.splice(selectedIndex, 1);
+          this.setData({ currentDate });
+          this.unselect(cancelDate);
+        } else {
+          // @ts-ignore
+          this.select([...currentDate, date]);
+        }
+      } else {
+        this.select(date, true);
+      }
+    },
+    unselect(dateArray) {
+      const date = dateArray[0];
+      if (date) {
+        this.$emit('unselect', copyDates(date));
+      }
+    },
+    select(date, complete) {
+      if (complete && this.data.type === 'range') {
+        const valid = this.checkRange(date);
+        if (!valid) {
+          // auto selected to max range if showConfirm
+          if (this.data.showConfirm) {
+            this.emit([
+              date[0],
+              getDayByOffset(date[0], this.data.maxRange - 1),
+            ]);
+          } else {
+            this.emit(date);
+          }
+          return;
+        }
+      }
+      this.emit(date);
+      if (complete && !this.data.showConfirm) {
+        this.onConfirm();
+      }
+    },
+    emit(date) {
+      const getTime = (date) => (date instanceof Date ? date.getTime() : date);
+      this.setData({
+        currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
+      });
+      this.$emit('select', copyDates(date));
+    },
+    checkRange(date) {
+      const { maxRange, rangePrompt } = this.data;
+      if (maxRange && calcDateNum(date) > maxRange) {
+        Toast({
+          context: this,
+          message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
+        });
+        return false;
+      }
+      return true;
+    },
+    onConfirm() {
+      if (
+        this.data.type === 'range' &&
+        !this.checkRange(this.data.currentDate)
+      ) {
+        return;
+      }
+      wx.nextTick(() => {
+        // @ts-ignore
+        this.$emit('confirm', copyDates(this.data.currentDate));
+      });
+    },
+  },
+});
+export default global['__wxComponents']['vant/calendar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;height:var(--calendar-height,100%);background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:80%;height:var(--calendar-popup-height,80%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-flex:1;flex:1;overflow:auto;-webkit-overflow-scrolling:touch}.van-calendar__footer{-webkit-flex-shrink:0;flex-shrink:0;padding:0 16px;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:36px!important;height:var(--calendar-confirm-button-height,36px)!important;margin:7px 0!important;margin:var(--calendar-confirm-button-margin,7px 0)!important;line-height:34px!important;line-height:var(--calendar-confirm-button-line-height,34px)!important}
+</style>

+ 25 - 0
src/ttcomponents/vant/calendar/index.wxml

@@ -0,0 +1,25 @@
+<wxs src="./index.wxs" module="computed" />
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<import src="./calendar.wxml" />
+
+<van-popup
+  wx:if="{{ poppable }}"
+  custom-class="van-calendar__popup--{{ position }}"
+  close-icon-class="van-calendar__close-icon"
+  show="{{ show }}"
+  round="{{ round }}"
+  position="{{ position }}"
+  closeable="{{ showTitle || showSubtitle }}"
+  close-on-click-overlay="{{ closeOnClickOverlay }}"
+  bind:enter="onOpen"
+  bind:close="onClose"
+  bind:after-enter="onOpened"
+  bind:after-leave="onClosed"
+>
+  <include src="calendar.wxml" />
+</van-popup>
+
+<include wx:else src="calendar.wxml" />
+
+<van-toast id="van-toast" />

+ 37 - 0
src/ttcomponents/vant/calendar/index.wxs

@@ -0,0 +1,37 @@
+/* eslint-disable */
+var utils = require('./utils.wxs');
+
+function getMonths(minDate, maxDate) {
+  var months = [];
+  var cursor = getDate(minDate);
+
+  cursor.setDate(1);
+
+  do {
+    months.push(cursor.getTime());
+    cursor.setMonth(cursor.getMonth() + 1);
+  } while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
+
+  return months;
+}
+
+function getButtonDisabled(type, currentDate) {
+  if (currentDate == null) {
+    return true;
+  }
+
+  if (type === 'range') {
+    return !currentDate[0] || !currentDate[1];
+  }
+
+  if (type === 'multiple') {
+    return !currentDate.length;
+  }
+
+  return !currentDate;
+}
+
+module.exports = {
+  getMonths: getMonths,
+  getButtonDisabled: getButtonDisabled
+};

+ 1 - 0
src/ttcomponents/vant/calendar/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;height:var(--calendar-height,100%);background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:80%;height:var(--calendar-popup-height,80%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-flex:1;flex:1;overflow:auto;-webkit-overflow-scrolling:touch}.van-calendar__footer{-webkit-flex-shrink:0;flex-shrink:0;padding:0 16px;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:36px!important;height:var(--calendar-confirm-button-height,36px)!important;margin:7px 0!important;margin:var(--calendar-confirm-button-margin,7px 0)!important;line-height:34px!important;line-height:var(--calendar-confirm-button-line-height,34px)!important}

+ 17 - 0
src/ttcomponents/vant/calendar/utils.d.ts

@@ -0,0 +1,17 @@
+export declare const ROW_HEIGHT = 64;
+export declare function formatMonthTitle(date: Date): string;
+export declare function compareMonth(
+  date1: Date | number,
+  date2: Date | number
+): 0 | 1 | -1;
+export declare function compareDay(
+  day1: Date | number,
+  day2: Date | number
+): 0 | 1 | -1;
+export declare function getDayByOffset(date: Date, offset: number): Date;
+export declare function getPrevDay(date: Date): Date;
+export declare function getNextDay(date: Date): Date;
+export declare function calcDateNum(date: [Date, Date]): number;
+export declare function copyDates(dates: Date | Date[]): Date | Date[];
+export declare function getMonthEndDay(year: number, month: number): number;
+export declare function getMonths(minDate: number, maxDate: number): number[];

+ 78 - 0
src/ttcomponents/vant/calendar/utils.js

@@ -0,0 +1,78 @@
+export const ROW_HEIGHT = 64;
+export function formatMonthTitle(date) {
+  if (!(date instanceof Date)) {
+    date = new Date(date);
+  }
+  return `${date.getFullYear()}年${date.getMonth() + 1}月`;
+}
+export function compareMonth(date1, date2) {
+  if (!(date1 instanceof Date)) {
+    date1 = new Date(date1);
+  }
+  if (!(date2 instanceof Date)) {
+    date2 = new Date(date2);
+  }
+  const year1 = date1.getFullYear();
+  const year2 = date2.getFullYear();
+  const month1 = date1.getMonth();
+  const month2 = date2.getMonth();
+  if (year1 === year2) {
+    return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
+  }
+  return year1 > year2 ? 1 : -1;
+}
+export function compareDay(day1, day2) {
+  if (!(day1 instanceof Date)) {
+    day1 = new Date(day1);
+  }
+  if (!(day2 instanceof Date)) {
+    day2 = new Date(day2);
+  }
+  const compareMonthResult = compareMonth(day1, day2);
+  if (compareMonthResult === 0) {
+    const date1 = day1.getDate();
+    const date2 = day2.getDate();
+    return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
+  }
+  return compareMonthResult;
+}
+export function getDayByOffset(date, offset) {
+  date = new Date(date);
+  date.setDate(date.getDate() + offset);
+  return date;
+}
+export function getPrevDay(date) {
+  return getDayByOffset(date, -1);
+}
+export function getNextDay(date) {
+  return getDayByOffset(date, 1);
+}
+export function calcDateNum(date) {
+  const day1 = new Date(date[0]).getTime();
+  const day2 = new Date(date[1]).getTime();
+  return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
+}
+export function copyDates(dates) {
+  if (Array.isArray(dates)) {
+    return dates.map((date) => {
+      if (date === null) {
+        return date;
+      }
+      return new Date(date);
+    });
+  }
+  return new Date(dates);
+}
+export function getMonthEndDay(year, month) {
+  return 32 - new Date(year, month - 1, 32).getDate();
+}
+export function getMonths(minDate, maxDate) {
+  const months = [];
+  const cursor = new Date(minDate);
+  cursor.setDate(1);
+  do {
+    months.push(cursor.getTime());
+    cursor.setMonth(cursor.getMonth() + 1);
+  } while (compareMonth(cursor, maxDate) !== 1);
+  return months;
+}

+ 25 - 0
src/ttcomponents/vant/calendar/utils.wxs

@@ -0,0 +1,25 @@
+/* eslint-disable */
+function getMonthEndDay(year, month) {
+  return 32 -  getDate(year, month - 1, 32).getDate();
+}
+
+function compareMonth(date1, date2) {
+  date1 = getDate(date1);
+  date2 = getDate(date2);
+
+  var year1 = date1.getFullYear();
+  var year2 = date2.getFullYear();
+  var month1 = date1.getMonth();
+  var month2 = date2.getMonth();
+
+  if (year1 === year2) {
+    return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
+  }
+
+  return year1 > year2 ? 1 : -1;
+}
+
+module.exports = {
+  getMonthEndDay: getMonthEndDay,
+  compareMonth: compareMonth
+};

+ 1 - 0
src/ttcomponents/vant/card/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 49 - 0
src/ttcomponents/vant/card/index.js

@@ -0,0 +1,49 @@
+import { link } from '../mixins/link';
+import { VantComponent } from '../common/component';
+VantComponent({
+  classes: [
+    'num-class',
+    'desc-class',
+    'thumb-class',
+    'title-class',
+    'price-class',
+    'origin-price-class',
+  ],
+  mixins: [link],
+  props: {
+    tag: String,
+    num: String,
+    desc: String,
+    thumb: String,
+    title: String,
+    price: {
+      type: String,
+      observer: 'updatePrice',
+    },
+    centered: Boolean,
+    lazyLoad: Boolean,
+    thumbLink: String,
+    originPrice: String,
+    thumbMode: {
+      type: String,
+      value: 'aspectFit',
+    },
+    currency: {
+      type: String,
+      value: '¥',
+    },
+  },
+  methods: {
+    updatePrice() {
+      const { price } = this.data;
+      const priceArr = price.toString().split('.');
+      this.setData({
+        integerStr: priceArr[0],
+        decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
+      });
+    },
+    onClickThumb() {
+      this.jumpLink('thumbLink');
+    },
+  },
+});

+ 6 - 0
src/ttcomponents/vant/card/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-tag": "../tag/index"
+  }
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 103 - 0
src/ttcomponents/vant/card/index.vue


+ 56 - 0
src/ttcomponents/vant/card/index.wxml

@@ -0,0 +1,56 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view class="custom-class van-card">
+  <view class="{{ utils.bem('card__header', { center: centered }) }}">
+    <view class="van-card__thumb" bind:tap="onClickThumb">
+      <image
+        wx:if="{{ thumb }}"
+        src="{{ thumb }}"
+        mode="{{ thumbMode }}"
+        lazy-load="{{ lazyLoad }}"
+        class="van-card__img thumb-class"
+      />
+      <slot wx:else name="thumb" />
+      <van-tag
+        wx:if="{{ tag }}"
+        mark
+        type="danger"
+        custom-class="van-card__tag"
+      >
+        {{ tag }}
+      </van-tag>
+      <slot wx:else name="tag" />
+    </view>
+
+    <view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
+      <view>
+        <view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
+        <slot wx:else name="title" />
+
+        <view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
+        <slot wx:else name="desc" />
+
+        <slot name="tags" />
+      </view>
+
+      <view class="van-card__bottom">
+        <slot name="price-top" />
+        <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">
+          <text>{{ currency }}</text>
+          <text class="van-card__price-integer">{{ integerStr }}</text>
+          <text class="van-card__price-decimal">{{ decimalStr }}</text>
+        </view>
+        <slot wx:else name="price" />
+        <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
+        <slot wx:else name="origin-price" />
+        <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
+        <slot wx:else  name="num" />
+        <slot name="bottom" />
+      </view>
+    </view>
+  </view>
+
+  <view class="van-card__footer">
+    <slot name="footer" />
+  </view>
+</view>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
src/ttcomponents/vant/card/index.wxss


+ 1 - 0
src/ttcomponents/vant/cell-group/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 10 - 0
src/ttcomponents/vant/cell-group/index.js

@@ -0,0 +1,10 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+  props: {
+    title: String,
+    border: {
+      type: Boolean,
+      value: true,
+    },
+  },
+});

+ 3 - 0
src/ttcomponents/vant/cell-group/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 27 - 0
src/ttcomponents/vant/cell-group/index.vue

@@ -0,0 +1,27 @@
+<template>
+<uni-shadow-root class="vant-cell-group-index"><view v-if="title" class="van-cell-group__title">
+  {{ title }}
+</view>
+<view :class="'custom-class van-cell-group '+(border ? 'van-hairline--top-bottom' : '')">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/cell-group/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+  props: {
+    title: String,
+    border: {
+      type: Boolean,
+      value: true,
+    },
+  },
+});
+export default global['__wxComponents']['vant/cell-group/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}
+</style>

+ 9 - 0
src/ttcomponents/vant/cell-group/index.wxml

@@ -0,0 +1,9 @@
+<view
+  wx:if="{{ title }}"
+  class="van-cell-group__title"
+>
+  {{ title }}
+</view>
+<view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
+  <slot />
+</view>

+ 1 - 0
src/ttcomponents/vant/cell-group/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}

+ 1 - 0
src/ttcomponents/vant/cell/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 38 - 0
src/ttcomponents/vant/cell/index.js

@@ -0,0 +1,38 @@
+import { link } from '../mixins/link';
+import { VantComponent } from '../common/component';
+VantComponent({
+  classes: [
+    'title-class',
+    'label-class',
+    'value-class',
+    'right-icon-class',
+    'hover-class',
+  ],
+  mixins: [link],
+  props: {
+    title: null,
+    value: null,
+    icon: String,
+    size: String,
+    label: String,
+    center: Boolean,
+    isLink: Boolean,
+    required: Boolean,
+    clickable: Boolean,
+    titleWidth: String,
+    customStyle: String,
+    arrowDirection: String,
+    useLabelSlot: Boolean,
+    border: {
+      type: Boolean,
+      value: true,
+    },
+    titleStyle: String,
+  },
+  methods: {
+    onClick(event) {
+      this.$emit('click', event.detail);
+      this.jumpLink();
+    },
+  },
+});

+ 6 - 0
src/ttcomponents/vant/cell/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index"
+  }
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 73 - 0
src/ttcomponents/vant/cell/index.vue


+ 46 - 0
src/ttcomponents/vant/cell/index.wxml

@@ -0,0 +1,46 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
+
+<view
+  class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
+  hover-class="van-cell--hover hover-class"
+  hover-stay-time="70"
+  style="{{ customStyle }}"
+  bind:tap="onClick"
+>
+  <van-icon
+    wx:if="{{ icon }}"
+    name="{{ icon }}"
+    class="van-cell__left-icon-wrap"
+    custom-class="van-cell__left-icon"
+  />
+  <slot wx:else name="icon" />
+
+  <view
+    style="{{ computed.titleStyle({ titleWidth, titleStyle }) }}"
+    class="van-cell__title title-class"
+  >
+    <block wx:if="{{ title }}">{{ title }}</block>
+    <slot wx:else name="title" />
+
+    <view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
+      <slot wx:if="{{ useLabelSlot }}" name="label" />
+      <block wx:elif="{{ label }}">{{ label }}</block>
+    </view>
+  </view>
+
+  <view class="van-cell__value value-class">
+    <block wx:if="{{ value || value === 0 }}">{{ value }}</block>
+    <slot wx:else />
+  </view>
+
+  <van-icon
+    wx:if="{{ isLink }}"
+    name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
+    class="van-cell__right-icon-wrap right-icon-class"
+    custom-class="van-cell__right-icon"
+  />
+  <slot wx:else name="right-icon" />
+
+  <slot name="extra" />
+</view>

+ 17 - 0
src/ttcomponents/vant/cell/index.wxs

@@ -0,0 +1,17 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+var addUnit = require('../wxs/add-unit.wxs');
+
+function titleStyle(data) {
+  return style([
+    {
+      'max-width': addUnit(data.titleWidth),
+      'min-width': addUnit(data.titleWidth),
+    },
+    data.titleStyle,
+  ]);
+}
+
+module.exports = {
+  titleStyle: titleStyle,
+};

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
src/ttcomponents/vant/cell/index.wxss


+ 1 - 0
src/ttcomponents/vant/checkbox-group/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 31 - 0
src/ttcomponents/vant/checkbox-group/index.js

@@ -0,0 +1,31 @@
+import { useChildren } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+  field: true,
+  relation: useChildren('checkbox', function (target) {
+    this.updateChild(target);
+  }),
+  props: {
+    max: Number,
+    value: {
+      type: Array,
+      observer: 'updateChildren',
+    },
+    disabled: {
+      type: Boolean,
+      observer: 'updateChildren',
+    },
+  },
+  methods: {
+    updateChildren() {
+      this.children.forEach((child) => this.updateChild(child));
+    },
+    updateChild(child) {
+      const { value, disabled } = this.data;
+      child.setData({
+        value: value.indexOf(child.data.name) !== -1,
+        parentDisabled: disabled,
+      });
+    },
+  },
+});

+ 3 - 0
src/ttcomponents/vant/checkbox-group/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 43 - 0
src/ttcomponents/vant/checkbox-group/index.vue

@@ -0,0 +1,43 @@
+<template>
+<uni-shadow-root class="vant-checkbox-group-index"><slot></slot></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/checkbox-group/index'
+import { useChildren } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+  field: true,
+  relation: useChildren('checkbox', function (target) {
+    this.updateChild(target);
+  }),
+  props: {
+    max: Number,
+    value: {
+      type: Array,
+      observer: 'updateChildren',
+    },
+    disabled: {
+      type: Boolean,
+      observer: 'updateChildren',
+    },
+  },
+  methods: {
+    updateChildren() {
+      this.children.forEach((child) => this.updateChild(child));
+    },
+    updateChild(child) {
+      const { value, disabled } = this.data;
+      child.setData({
+        value: value.indexOf(child.data.name) !== -1,
+        parentDisabled: disabled,
+      });
+    },
+  },
+});
+export default global['__wxComponents']['vant/checkbox-group/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';
+</style>

+ 1 - 0
src/ttcomponents/vant/checkbox-group/index.wxml

@@ -0,0 +1 @@
+<slot />

+ 1 - 0
src/ttcomponents/vant/checkbox-group/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';

+ 1 - 0
src/ttcomponents/vant/checkbox/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 74 - 0
src/ttcomponents/vant/checkbox/index.js

@@ -0,0 +1,74 @@
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+function emit(target, value) {
+  target.$emit('input', value);
+  target.$emit('change', value);
+}
+VantComponent({
+  field: true,
+  relation: useParent('checkbox-group'),
+  classes: ['icon-class', 'label-class'],
+  props: {
+    value: Boolean,
+    disabled: Boolean,
+    useIconSlot: Boolean,
+    checkedColor: String,
+    labelPosition: {
+      type: String,
+      value: 'right',
+    },
+    labelDisabled: Boolean,
+    shape: {
+      type: String,
+      value: 'round',
+    },
+    iconSize: {
+      type: null,
+      value: 20,
+    },
+  },
+  data: {
+    parentDisabled: false,
+  },
+  methods: {
+    emitChange(value) {
+      if (this.parent) {
+        this.setParentValue(this.parent, value);
+      } else {
+        emit(this, value);
+      }
+    },
+    toggle() {
+      const { parentDisabled, disabled, value } = this.data;
+      if (!disabled && !parentDisabled) {
+        this.emitChange(!value);
+      }
+    },
+    onClickLabel() {
+      const { labelDisabled, parentDisabled, disabled, value } = this.data;
+      if (!disabled && !labelDisabled && !parentDisabled) {
+        this.emitChange(!value);
+      }
+    },
+    setParentValue(parent, value) {
+      const parentValue = parent.data.value.slice();
+      const { name } = this.data;
+      const { max } = parent.data;
+      if (value) {
+        if (max && parentValue.length >= max) {
+          return;
+        }
+        if (parentValue.indexOf(name) === -1) {
+          parentValue.push(name);
+          emit(parent, parentValue);
+        }
+      } else {
+        const index = parentValue.indexOf(name);
+        if (index !== -1) {
+          parentValue.splice(index, 1);
+          emit(parent, parentValue);
+        }
+      }
+    },
+  },
+});

+ 6 - 0
src/ttcomponents/vant/checkbox/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index"
+  }
+}

+ 99 - 0
src/ttcomponents/vant/checkbox/index.vue

@@ -0,0 +1,99 @@
+<template>
+<uni-shadow-root class="vant-checkbox-index"><view class="van-checkbox custom-class">
+  <view v-if="labelPosition === 'left'" :class="'label-class '+(utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]))" @click="onClickLabel">
+    <slot></slot>
+  </view>
+  <view class="van-checkbox__icon-wrap" @click="toggle">
+    <slot v-if="useIconSlot" name="icon"></slot>
+    <van-icon v-else name="success" size="0.8em" :class="utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }])" :style="computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize)" custom-class="icon-class" custom-style="line-height: 1.25em;"></van-icon>
+  </view>
+  <view v-if="labelPosition === 'right'" :class="'label-class '+(utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]))" @click="onClickLabel">
+    <slot></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/checkbox/index'
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+function emit(target, value) {
+  target.$emit('input', value);
+  target.$emit('change', value);
+}
+VantComponent({
+  field: true,
+  relation: useParent('checkbox-group'),
+  classes: ['icon-class', 'label-class'],
+  props: {
+    value: Boolean,
+    disabled: Boolean,
+    useIconSlot: Boolean,
+    checkedColor: String,
+    labelPosition: {
+      type: String,
+      value: 'right',
+    },
+    labelDisabled: Boolean,
+    shape: {
+      type: String,
+      value: 'round',
+    },
+    iconSize: {
+      type: null,
+      value: 20,
+    },
+  },
+  data: {
+    parentDisabled: false,
+  },
+  methods: {
+    emitChange(value) {
+      if (this.parent) {
+        this.setParentValue(this.parent, value);
+      } else {
+        emit(this, value);
+      }
+    },
+    toggle() {
+      const { parentDisabled, disabled, value } = this.data;
+      if (!disabled && !parentDisabled) {
+        this.emitChange(!value);
+      }
+    },
+    onClickLabel() {
+      const { labelDisabled, parentDisabled, disabled, value } = this.data;
+      if (!disabled && !labelDisabled && !parentDisabled) {
+        this.emitChange(!value);
+      }
+    },
+    setParentValue(parent, value) {
+      const parentValue = parent.data.value.slice();
+      const { name } = this.data;
+      const { max } = parent.data;
+      if (value) {
+        if (max && parentValue.length >= max) {
+          return;
+        }
+        if (parentValue.indexOf(name) === -1) {
+          parentValue.push(name);
+          emit(parent, parentValue);
+        }
+      } else {
+        const index = parentValue.indexOf(name);
+        if (index !== -1) {
+          parentValue.splice(index, 1);
+          emit(parent, parentValue);
+        }
+      }
+    },
+  },
+});
+export default global['__wxComponents']['vant/checkbox/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-checkbox{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #c8c9cc;border:1px solid var(--checkbox-border-color,#c8c9cc);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
+</style>

+ 31 - 0
src/ttcomponents/vant/checkbox/index.wxml

@@ -0,0 +1,31 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
+
+<view class="van-checkbox custom-class">
+  <view
+    wx:if="{{ labelPosition === 'left' }}"
+    class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
+    bindtap="onClickLabel"
+  >
+    <slot />
+  </view>
+  <view class="van-checkbox__icon-wrap" bindtap="toggle">
+    <slot wx:if="{{ useIconSlot }}" name="icon" />
+    <van-icon
+      wx:else
+      name="success"
+      size="0.8em"
+      class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
+      style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
+      custom-class="icon-class"
+      custom-style="line-height: 1.25em;"
+    />
+  </view>
+  <view
+    wx:if="{{ labelPosition === 'right' }}"
+    class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
+    bindtap="onClickLabel"
+  >
+    <slot />
+  </view>
+</view>

+ 20 - 0
src/ttcomponents/vant/checkbox/index.wxs

@@ -0,0 +1,20 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+var addUnit = require('../wxs/add-unit.wxs');
+
+function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
+  var styles = {
+    'font-size': addUnit(iconSize),
+  };
+
+  if (checkedColor && value && !disabled && !parentDisabled) {
+    styles['border-color'] = checkedColor;
+    styles['background-color'] = checkedColor;
+  }
+
+  return style(styles);
+}
+
+module.exports = {
+  iconStyle: iconStyle,
+};

+ 1 - 0
src/ttcomponents/vant/checkbox/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #c8c9cc;border:1px solid var(--checkbox-border-color,#c8c9cc);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}

+ 6 - 0
src/ttcomponents/vant/circle/canvas.d.ts

@@ -0,0 +1,6 @@
+/// <reference types="miniprogram-api-typings" />
+declare type CanvasContext = WechatMiniprogram.CanvasContext;
+export declare function adaptor(
+  ctx: CanvasContext & Record<string, unknown>
+): CanvasContext;
+export {};

+ 43 - 0
src/ttcomponents/vant/circle/canvas.js

@@ -0,0 +1,43 @@
+export function adaptor(ctx) {
+  // @ts-ignore
+  return Object.assign(ctx, {
+    setStrokeStyle(val) {
+      ctx.strokeStyle = val;
+    },
+    setLineWidth(val) {
+      ctx.lineWidth = val;
+    },
+    setLineCap(val) {
+      ctx.lineCap = val;
+    },
+    setFillStyle(val) {
+      ctx.fillStyle = val;
+    },
+    setFontSize(val) {
+      ctx.font = String(val);
+    },
+    setGlobalAlpha(val) {
+      ctx.globalAlpha = val;
+    },
+    setLineJoin(val) {
+      ctx.lineJoin = val;
+    },
+    setTextAlign(val) {
+      ctx.textAlign = val;
+    },
+    setMiterLimit(val) {
+      ctx.miterLimit = val;
+    },
+    setShadow(offsetX, offsetY, blur, color) {
+      ctx.shadowOffsetX = offsetX;
+      ctx.shadowOffsetY = offsetY;
+      ctx.shadowBlur = blur;
+      ctx.shadowColor = color;
+    },
+    setTextBaseline(val) {
+      ctx.textBaseline = val;
+    },
+    createCircularGradient() {},
+    draw() {},
+  });
+}

+ 1 - 0
src/ttcomponents/vant/circle/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 186 - 0
src/ttcomponents/vant/circle/index.js

@@ -0,0 +1,186 @@
+import { BLUE, WHITE } from '../common/color';
+import { VantComponent } from '../common/component';
+import { getSystemInfoSync } from '../common/utils';
+import { isObj } from '../common/validator';
+import { canIUseCanvas2d } from '../common/version';
+import { adaptor } from './canvas';
+function format(rate) {
+  return Math.min(Math.max(rate, 0), 100);
+}
+const PERIMETER = 2 * Math.PI;
+const BEGIN_ANGLE = -Math.PI / 2;
+const STEP = 1;
+VantComponent({
+  props: {
+    text: String,
+    lineCap: {
+      type: String,
+      value: 'round',
+    },
+    value: {
+      type: Number,
+      value: 0,
+      observer: 'reRender',
+    },
+    speed: {
+      type: Number,
+      value: 50,
+    },
+    size: {
+      type: Number,
+      value: 100,
+      observer() {
+        this.drawCircle(this.currentValue);
+      },
+    },
+    fill: String,
+    layerColor: {
+      type: String,
+      value: WHITE,
+    },
+    color: {
+      type: null,
+      value: BLUE,
+      observer() {
+        this.setHoverColor().then(() => {
+          this.drawCircle(this.currentValue);
+        });
+      },
+    },
+    type: {
+      type: String,
+      value: '',
+    },
+    strokeWidth: {
+      type: Number,
+      value: 4,
+    },
+    clockwise: {
+      type: Boolean,
+      value: true,
+    },
+  },
+  data: {
+    hoverColor: BLUE,
+  },
+  methods: {
+    getContext() {
+      const { type, size } = this.data;
+      if (type === '' || !canIUseCanvas2d()) {
+        const ctx = wx.createCanvasContext('van-circle', this);
+        return Promise.resolve(ctx);
+      }
+      const dpr = getSystemInfoSync().pixelRatio;
+      return new Promise((resolve) => {
+        wx.createSelectorQuery()
+          .in(this)
+          .select('#van-circle')
+          .node()
+          .exec((res) => {
+            const canvas = res[0].node;
+            const ctx = canvas.getContext(type);
+            if (!this.inited) {
+              this.inited = true;
+              canvas.width = size * dpr;
+              canvas.height = size * dpr;
+              ctx.scale(dpr, dpr);
+            }
+            resolve(adaptor(ctx));
+          });
+      });
+    },
+    setHoverColor() {
+      const { color, size } = this.data;
+      if (isObj(color)) {
+        return this.getContext().then((context) => {
+          const LinearColor = context.createLinearGradient(size, 0, 0, 0);
+          Object.keys(color)
+            .sort((a, b) => parseFloat(a) - parseFloat(b))
+            .map((key) =>
+              LinearColor.addColorStop(parseFloat(key) / 100, color[key])
+            );
+          this.hoverColor = LinearColor;
+        });
+      }
+      this.hoverColor = color;
+      return Promise.resolve();
+    },
+    presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
+      const { strokeWidth, lineCap, clockwise, size } = this.data;
+      const position = size / 2;
+      const radius = position - strokeWidth / 2;
+      context.setStrokeStyle(strokeStyle);
+      context.setLineWidth(strokeWidth);
+      context.setLineCap(lineCap);
+      context.beginPath();
+      context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
+      context.stroke();
+      if (fill) {
+        context.setFillStyle(fill);
+        context.fill();
+      }
+    },
+    renderLayerCircle(context) {
+      const { layerColor, fill } = this.data;
+      this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
+    },
+    renderHoverCircle(context, formatValue) {
+      const { clockwise } = this.data;
+      // 结束角度
+      const progress = PERIMETER * (formatValue / 100);
+      const endAngle = clockwise
+        ? BEGIN_ANGLE + progress
+        : 3 * Math.PI - (BEGIN_ANGLE + progress);
+      this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
+    },
+    drawCircle(currentValue) {
+      const { size } = this.data;
+      this.getContext().then((context) => {
+        context.clearRect(0, 0, size, size);
+        this.renderLayerCircle(context);
+        const formatValue = format(currentValue);
+        if (formatValue !== 0) {
+          this.renderHoverCircle(context, formatValue);
+        }
+        context.draw();
+      });
+    },
+    reRender() {
+      // tofector 动画暂时没有想到好的解决方案
+      const { value, speed } = this.data;
+      if (speed <= 0 || speed > 1000) {
+        this.drawCircle(value);
+        return;
+      }
+      this.clearInterval();
+      this.currentValue = this.currentValue || 0;
+      this.interval = setInterval(() => {
+        if (this.currentValue !== value) {
+          if (this.currentValue < value) {
+            this.currentValue += STEP;
+          } else {
+            this.currentValue -= STEP;
+          }
+          this.drawCircle(this.currentValue);
+        } else {
+          this.clearInterval();
+        }
+      }, 1000 / speed);
+    },
+    clearInterval() {
+      if (this.interval) {
+        clearInterval(this.interval);
+        this.interval = null;
+      }
+    },
+  },
+  mounted() {
+    this.currentValue = this.data.value;
+    this.setHoverColor().then(() => {
+      this.drawCircle(this.currentValue);
+    });
+  },
+  destroyed() {
+    this.clearInterval();
+  },
+});

+ 3 - 0
src/ttcomponents/vant/circle/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 204 - 0
src/ttcomponents/vant/circle/index.vue

@@ -0,0 +1,204 @@
+<template>
+<uni-shadow-root class="vant-circle-index"><view class="van-circle">
+  <canvas class="van-circle__canvas" :type="type" :style="'width: '+(utils.addUnit(size))+';height:'+(utils.addUnit(size))" id="van-circle" canvas-id="van-circle"></canvas>
+  <view v-if="(!text)" class="van-circle__text">
+    <slot></slot>
+  </view>
+  <cover-view v-else class="van-circle__text">{{ text }}</cover-view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/circle/index'
+import { BLUE, WHITE } from '../common/color';
+import { VantComponent } from '../common/component';
+import { getSystemInfoSync } from '../common/utils';
+import { isObj } from '../common/validator';
+import { canIUseCanvas2d } from '../common/version';
+import { adaptor } from './canvas';
+function format(rate) {
+  return Math.min(Math.max(rate, 0), 100);
+}
+const PERIMETER = 2 * Math.PI;
+const BEGIN_ANGLE = -Math.PI / 2;
+const STEP = 1;
+VantComponent({
+  props: {
+    text: String,
+    lineCap: {
+      type: String,
+      value: 'round',
+    },
+    value: {
+      type: Number,
+      value: 0,
+      observer: 'reRender',
+    },
+    speed: {
+      type: Number,
+      value: 50,
+    },
+    size: {
+      type: Number,
+      value: 100,
+      observer() {
+        this.drawCircle(this.currentValue);
+      },
+    },
+    fill: String,
+    layerColor: {
+      type: String,
+      value: WHITE,
+    },
+    color: {
+      type: null,
+      value: BLUE,
+      observer() {
+        this.setHoverColor().then(() => {
+          this.drawCircle(this.currentValue);
+        });
+      },
+    },
+    type: {
+      type: String,
+      value: '',
+    },
+    strokeWidth: {
+      type: Number,
+      value: 4,
+    },
+    clockwise: {
+      type: Boolean,
+      value: true,
+    },
+  },
+  data: {
+    hoverColor: BLUE,
+  },
+  methods: {
+    getContext() {
+      const { type, size } = this.data;
+      if (type === '' || !canIUseCanvas2d()) {
+        const ctx = wx.createCanvasContext('van-circle', this);
+        return Promise.resolve(ctx);
+      }
+      const dpr = getSystemInfoSync().pixelRatio;
+      return new Promise((resolve) => {
+        wx.createSelectorQuery()
+          .in(this)
+          .select('#van-circle')
+          .node()
+          .exec((res) => {
+            const canvas = res[0].node;
+            const ctx = canvas.getContext(type);
+            if (!this.inited) {
+              this.inited = true;
+              canvas.width = size * dpr;
+              canvas.height = size * dpr;
+              ctx.scale(dpr, dpr);
+            }
+            resolve(adaptor(ctx));
+          });
+      });
+    },
+    setHoverColor() {
+      const { color, size } = this.data;
+      if (isObj(color)) {
+        return this.getContext().then((context) => {
+          const LinearColor = context.createLinearGradient(size, 0, 0, 0);
+          Object.keys(color)
+            .sort((a, b) => parseFloat(a) - parseFloat(b))
+            .map((key) =>
+              LinearColor.addColorStop(parseFloat(key) / 100, color[key])
+            );
+          this.hoverColor = LinearColor;
+        });
+      }
+      this.hoverColor = color;
+      return Promise.resolve();
+    },
+    presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
+      const { strokeWidth, lineCap, clockwise, size } = this.data;
+      const position = size / 2;
+      const radius = position - strokeWidth / 2;
+      context.setStrokeStyle(strokeStyle);
+      context.setLineWidth(strokeWidth);
+      context.setLineCap(lineCap);
+      context.beginPath();
+      context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
+      context.stroke();
+      if (fill) {
+        context.setFillStyle(fill);
+        context.fill();
+      }
+    },
+    renderLayerCircle(context) {
+      const { layerColor, fill } = this.data;
+      this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
+    },
+    renderHoverCircle(context, formatValue) {
+      const { clockwise } = this.data;
+      // 结束角度
+      const progress = PERIMETER * (formatValue / 100);
+      const endAngle = clockwise
+        ? BEGIN_ANGLE + progress
+        : 3 * Math.PI - (BEGIN_ANGLE + progress);
+      this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
+    },
+    drawCircle(currentValue) {
+      const { size } = this.data;
+      this.getContext().then((context) => {
+        context.clearRect(0, 0, size, size);
+        this.renderLayerCircle(context);
+        const formatValue = format(currentValue);
+        if (formatValue !== 0) {
+          this.renderHoverCircle(context, formatValue);
+        }
+        context.draw();
+      });
+    },
+    reRender() {
+      // tofector 动画暂时没有想到好的解决方案
+      const { value, speed } = this.data;
+      if (speed <= 0 || speed > 1000) {
+        this.drawCircle(value);
+        return;
+      }
+      this.clearInterval();
+      this.currentValue = this.currentValue || 0;
+      this.interval = setInterval(() => {
+        if (this.currentValue !== value) {
+          if (this.currentValue < value) {
+            this.currentValue += STEP;
+          } else {
+            this.currentValue -= STEP;
+          }
+          this.drawCircle(this.currentValue);
+        } else {
+          this.clearInterval();
+        }
+      }, 1000 / speed);
+    },
+    clearInterval() {
+      if (this.interval) {
+        clearInterval(this.interval);
+        this.interval = null;
+      }
+    },
+  },
+  mounted() {
+    this.currentValue = this.data.value;
+    this.setHoverColor().then(() => {
+      this.drawCircle(this.currentValue);
+    });
+  },
+  destroyed() {
+    this.clearInterval();
+  },
+});
+export default global['__wxComponents']['vant/circle/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-circle{position:relative;display:inline-block;text-align:center}.van-circle__text{position:absolute;top:50%;left:0;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#323233;color:var(--circle-text-color,#323233)}
+</style>

+ 9 - 0
src/ttcomponents/vant/circle/index.wxml

@@ -0,0 +1,9 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view class="van-circle">
+  <canvas class="van-circle__canvas" type="{{ type }}" style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}" id="van-circle" canvas-id="van-circle"></canvas>
+  <view wx:if="{{ !text }}" class="van-circle__text">
+    <slot></slot>
+  </view>
+  <cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
+</view>

+ 1 - 0
src/ttcomponents/vant/circle/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-circle{position:relative;display:inline-block;text-align:center}.van-circle__text{position:absolute;top:50%;left:0;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#323233;color:var(--circle-text-color,#323233)}

+ 1 - 0
src/ttcomponents/vant/col/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 9 - 0
src/ttcomponents/vant/col/index.js

@@ -0,0 +1,9 @@
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+  relation: useParent('row'),
+  props: {
+    span: Number,
+    offset: Number,
+  },
+});

+ 3 - 0
src/ttcomponents/vant/col/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 23 - 0
src/ttcomponents/vant/col/index.vue

@@ -0,0 +1,23 @@
+<template>
+<uni-shadow-root class="vant-col-index"><view :class="'custom-class '+(utils.bem('col', [span]))+' '+(offset ? 'van-col--offset-' + offset : '')" :style="computed.rootStyle({ gutter })">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/col/index'
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+  relation: useParent('row'),
+  props: {
+    span: Number,
+    offset: Number,
+  },
+});
+export default global['__wxComponents']['vant/col/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-col{float:left;box-sizing:border-box}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}
+</style>

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov