diff --git a/components/qk/qk-send-sms-code/qk-send-sms-code.vue b/components/qk/qk-send-sms-code/qk-send-sms-code.vue
new file mode 100644
index 0000000..385d707
--- /dev/null
+++ b/components/qk/qk-send-sms-code/qk-send-sms-code.vue
@@ -0,0 +1,130 @@
+
+
+ {{innerText}}
+
+
+
+
+
+
diff --git a/components/qk/qk-statusbar-block/qk-statusbar-block.vue b/components/qk/qk-statusbar-block/qk-statusbar-block.vue
new file mode 100644
index 0000000..f5b8142
--- /dev/null
+++ b/components/qk/qk-statusbar-block/qk-statusbar-block.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-actionsheet/tui-actionsheet.vue b/components/thorui/tui-actionsheet/tui-actionsheet.vue
new file mode 100644
index 0000000..a21427a
--- /dev/null
+++ b/components/thorui/tui-actionsheet/tui-actionsheet.vue
@@ -0,0 +1,186 @@
+
+
+
+
+ {{tips}}
+
+
+
+ {{item.text}}
+
+
+ 取消
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-alert/tui-alert.vue b/components/thorui/tui-alert/tui-alert.vue
new file mode 100644
index 0000000..adb7b9e
--- /dev/null
+++ b/components/thorui/tui-alert/tui-alert.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+ {{btnText}}
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-badge/tui-badge.vue b/components/thorui/tui-badge/tui-badge.vue
new file mode 100644
index 0000000..208aaa6
--- /dev/null
+++ b/components/thorui/tui-badge/tui-badge.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-bottom-navigation/tui-bottom-navigation.vue b/components/thorui/tui-bottom-navigation/tui-bottom-navigation.vue
new file mode 100644
index 0000000..b676c3f
--- /dev/null
+++ b/components/thorui/tui-bottom-navigation/tui-bottom-navigation.vue
@@ -0,0 +1,387 @@
+
+
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-bottom-popup/tui-bottom-popup.vue b/components/thorui/tui-bottom-popup/tui-bottom-popup.vue
new file mode 100644
index 0000000..a8fb45c
--- /dev/null
+++ b/components/thorui/tui-bottom-popup/tui-bottom-popup.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-bubble-popup/tui-bubble-popup.vue b/components/thorui/tui-bubble-popup/tui-bubble-popup.vue
new file mode 100644
index 0000000..a8991e7
--- /dev/null
+++ b/components/thorui/tui-bubble-popup/tui-bubble-popup.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-button/tui-button.vue b/components/thorui/tui-button/tui-button.vue
new file mode 100644
index 0000000..03cf517
--- /dev/null
+++ b/components/thorui/tui-button/tui-button.vue
@@ -0,0 +1,519 @@
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-calendar/tui-calendar.js b/components/thorui/tui-calendar/tui-calendar.js
new file mode 100644
index 0000000..8d10e6d
--- /dev/null
+++ b/components/thorui/tui-calendar/tui-calendar.js
@@ -0,0 +1,562 @@
+/**
+ * @1900-2100区间内的公历、农历互转
+ * @公历转农历:solar2lunar(1987,11,01);
+ * @农历转公历:lunar2solar(1987,09,10);
+ */
+let calendar = {
+ /**
+ * 农历1900-2100的润大小信息表
+ * @Array Of Property
+ * @return Hex
+ */
+ lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-1909
+ 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, //1910-1919
+ 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, //1920-1929
+ 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, //1930-1939
+ 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, //1940-1949
+ 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, //1950-1959
+ 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, //1960-1969
+ 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, //1970-1979
+ 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //1980-1989
+ 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, //1990-1999
+ 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, //2000-2009
+ 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, //2010-2019
+ 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029
+ 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039
+ 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, //2040-2049
+ 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, //2050-2059
+ 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, //2060-2069
+ 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, //2070-2079
+ 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, //2080-2089
+ 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099
+ 0x0d520
+ ], //2100
+ /**
+ * 公历每个月份的天数普通表
+ * @Array Of Property
+ * @return Number
+ */
+ solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
+ /**
+ * 天干地支之天干速查表
+ * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
+ * @return Cn string
+ */
+ Gan: ["\u7532", "\u4e59", "\u4e19", "\u4e01", "\u620a", "\u5df1", "\u5e9a", "\u8f9b", "\u58ec", "\u7678"],
+ /**
+ * 天干地支之地支速查表
+ * @Array Of Property
+ * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
+ * @return Cn string
+ */
+ Zhi: ["\u5b50", "\u4e11", "\u5bc5", "\u536f", "\u8fb0", "\u5df3", "\u5348", "\u672a", "\u7533", "\u9149", "\u620c",
+ "\u4ea5"
+ ],
+ /**
+ * 天干地支之地支速查表<=>生肖
+ * @Array Of Property
+ * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
+ * @return Cn string
+ */
+ Animals: ["\u9f20", "\u725b", "\u864e", "\u5154", "\u9f99", "\u86c7", "\u9a6c", "\u7f8a", "\u7334", "\u9e21",
+ "\u72d7", "\u732a"
+ ],
+ /**
+ * 24节气速查表
+ * @Array Of Property
+ * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
+ * @return Cn string
+ */
+ solarTerm: ["\u5c0f\u5bd2", "\u5927\u5bd2", "\u7acb\u6625", "\u96e8\u6c34", "\u60ca\u86f0", "\u6625\u5206",
+ "\u6e05\u660e", "\u8c37\u96e8", "\u7acb\u590f", "\u5c0f\u6ee1", "\u8292\u79cd", "\u590f\u81f3", "\u5c0f\u6691",
+ "\u5927\u6691", "\u7acb\u79cb", "\u5904\u6691", "\u767d\u9732", "\u79cb\u5206", "\u5bd2\u9732", "\u971c\u964d",
+ "\u7acb\u51ac", "\u5c0f\u96ea", "\u5927\u96ea", "\u51ac\u81f3"
+ ],
+ /**
+ * 1900-2100各年的24节气日期速查表
+ * @Array Of Property
+ * @return 0x string For splice
+ */
+ sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
+ '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
+ 'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
+ '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
+ '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
+ '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
+ '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
+ '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+ '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
+ '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+ '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
+ '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
+ '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
+ '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
+ '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
+ '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
+ '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
+ '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
+ '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
+ '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'
+ ],
+ /**
+ * 数字转中文速查表
+ * @Array Of Property
+ * @trans ['日','一','二','三','四','五','六','七','八','九','十']
+ * @return Cn string
+ */
+ nStr1: ["\u65e5", "\u4e00", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341"],
+ /**
+ * 日期转农历称呼速查表
+ * @Array Of Property
+ * @trans ['初','十','廿','卅']
+ * @return Cn string
+ */
+ nStr2: ["\u521d", "\u5341", "\u5eff", "\u5345"],
+ /**
+ * 月份转农历称呼速查表
+ * @Array Of Property
+ * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
+ * @return Cn string
+ */
+ nStr3: ["\u6b63", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341", "\u51ac",
+ "\u814a"
+ ],
+ /**
+ * 返回农历y年一整年的总天数
+ * @param lunar Year
+ * @return Number
+ * @eg:let count = calendar.lYearDays(1987) ;//count=387
+ */
+ lYearDays: function(y) {
+ let i, sum = 348;
+ for (i = 0x8000; i > 0x8; i >>= 1) {
+ sum += (calendar.lunarInfo[y - 1900] & i) ? 1 : 0;
+ }
+ return (sum + calendar.leapDays(y));
+ },
+ /**
+ * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0
+ * @param lunar Year
+ * @return Number (0-12)
+ * @eg:let leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
+ */
+ leapMonth: function(y) { //闰字编码 \u95f0
+ return (calendar.lunarInfo[y - 1900] & 0xf);
+ },
+ /**
+ * 返回农历y年闰月的天数 若该年没有闰月则返回0
+ * @param lunar Year
+ * @return Number (0、29、30)
+ * @eg:let leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
+ */
+ leapDays: function(y) {
+ if (calendar.leapMonth(y)) {
+ return ((calendar.lunarInfo[y - 1900] & 0x10000) ? 30 : 29);
+ }
+ return (0);
+ },
+ /**
+ * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法
+ * @param lunar Year
+ * @return Number (-1、29、30)
+ * @eg:let MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
+ */
+ monthDays: function(y, m) {
+ if (m > 12 || m < 1) {
+ return -1
+ } //月份参数从1至12,参数错误返回-1
+ return ((calendar.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29);
+ },
+ /**
+ * 返回公历(!)y年m月的天数
+ * @param solar Year
+ * @return Number (-1、28、29、30、31)
+ * @eg:let solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
+ */
+ solarDays: function(y, m) {
+ if (m > 12 || m < 1) {
+ return -1
+ } //若参数错误 返回-1
+ let ms = m - 1;
+ if (ms == 1) { //2月份的闰平规律测算后确认返回28或29
+ return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28);
+ } else {
+ return (calendar.solarMonth[ms]);
+ }
+ },
+ /**
+ * 农历年份转换为干支纪年
+ * @param lYear 农历年的年份数
+ * @return Cn string
+ */
+ toGanZhiYear: function(lYear) {
+ let ganKey = (lYear - 3) % 10;
+ let zhiKey = (lYear - 3) % 12;
+ if (ganKey == 0) ganKey = 10; //如果余数为0则为最后一个天干
+ if (zhiKey == 0) zhiKey = 12; //如果余数为0则为最后一个地支
+ return calendar.Gan[ganKey - 1] + calendar.Zhi[zhiKey - 1];
+ },
+ /**
+ * 公历月、日判断所属星座
+ * @param cMonth [description]
+ * @param cDay [description]
+ * @return Cn string
+ */
+ toAstro: function(cMonth, cDay) {
+ let s =
+ "\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf";
+ let arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22];
+ return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + "\u5ea7"; //座
+ },
+ /**
+ * 传入offset偏移量返回干支
+ * @param offset 相对甲子的偏移量
+ * @return Cn string
+ */
+ toGanZhi: function(offset) {
+ return calendar.Gan[offset % 10] + calendar.Zhi[offset % 12];
+ },
+ /**
+ * 传入公历(!)y年获得该年第n个节气的公历日期
+ * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起
+ * @return day Number
+ * @eg:let _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
+ */
+ getTerm: function(y, n) {
+ if (y < 1900 || y > 2100) {
+ return -1;
+ }
+ if (n < 1 || n > 24) {
+ return -1;
+ }
+ let _table = calendar.sTermInfo[y - 1900];
+ let _info = [
+ parseInt('0x' + _table.substr(0, 5)).toString(),
+ parseInt('0x' + _table.substr(5, 5)).toString(),
+ parseInt('0x' + _table.substr(10, 5)).toString(),
+ parseInt('0x' + _table.substr(15, 5)).toString(),
+ parseInt('0x' + _table.substr(20, 5)).toString(),
+ parseInt('0x' + _table.substr(25, 5)).toString()
+ ];
+ let _calday = [
+ _info[0].substr(0, 1),
+ _info[0].substr(1, 2),
+ _info[0].substr(3, 1),
+ _info[0].substr(4, 2),
+ _info[1].substr(0, 1),
+ _info[1].substr(1, 2),
+ _info[1].substr(3, 1),
+ _info[1].substr(4, 2),
+ _info[2].substr(0, 1),
+ _info[2].substr(1, 2),
+ _info[2].substr(3, 1),
+ _info[2].substr(4, 2),
+ _info[3].substr(0, 1),
+ _info[3].substr(1, 2),
+ _info[3].substr(3, 1),
+ _info[3].substr(4, 2),
+ _info[4].substr(0, 1),
+ _info[4].substr(1, 2),
+ _info[4].substr(3, 1),
+ _info[4].substr(4, 2),
+ _info[5].substr(0, 1),
+ _info[5].substr(1, 2),
+ _info[5].substr(3, 1),
+ _info[5].substr(4, 2),
+ ];
+ return parseInt(_calday[n - 1]);
+ },
+ /**
+ * 传入农历数字月份返回汉语通俗表示法
+ * @param lunar month
+ * @return Cn string
+ * @eg:let cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
+ */
+ toChinaMonth: function(m) { // 月 => \u6708
+ if (m > 12 || m < 1) {
+ return -1
+ } //若参数错误 返回-1
+ let s = calendar.nStr3[m - 1];
+ s += "\u6708"; //加上月字
+ return s;
+ },
+ /**
+ * 传入农历日期数字返回汉字表示法
+ * @param lunar day
+ * @return Cn string
+ * @eg:let cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
+ */
+ toChinaDay: function(d) { //日 => \u65e5
+ let s;
+ switch (d) {
+ case 10:
+ s = '\u521d\u5341';
+ break;
+ case 20:
+ s = '\u4e8c\u5341';
+ break;
+ break;
+ case 30:
+ s = '\u4e09\u5341';
+ break;
+ break;
+ default:
+ s = calendar.nStr2[Math.floor(d / 10)];
+ s += calendar.nStr1[d % 10];
+ }
+ return (s);
+ },
+ /**
+ * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
+ * @param y year
+ * @return Cn string
+ * @eg:let animal = calendar.getAnimal(1987) ;//animal='兔'
+ */
+ getAnimal: function(y) {
+ return calendar.Animals[(y - 4) % 12]
+ },
+ /**
+ * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
+ * @param y solar year
+ * @param m solar month
+ * @param d solar day
+ * @return JSON object
+ * @eg:console.log(calendar.solar2lunar(1987,11,01));
+ */
+ solar2lunar: function(y, m, d) { //参数区间1900.1.31~2100.12.31
+ if (y < 1900 || y > 2100) {
+ return -1;
+ } //年份限定、上限
+ if (y == 1900 && m == 1 && d < 31) {
+ return -1;
+ } //下限
+ let objDate;
+ if (!y) { //未传参 获得当天
+ objDate = new Date();
+ } else {
+ objDate = new Date(y, parseInt(m) - 1, d)
+ }
+ let i, leap = 0,
+ temp = 0;
+ //修正ymd参数
+ y = objDate.getFullYear();
+ m = objDate.getMonth() + 1;
+ d = objDate.getDate();
+ let offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) /
+ 86400000;
+ for (i = 1900; i < 2101 && offset > 0; i++) {
+ temp = calendar.lYearDays(i);
+ offset -= temp;
+ }
+ if (offset < 0) {
+ offset += temp;
+ i--;
+ }
+ //是否今天
+ let isTodayObj = new Date(),
+ isToday = false;
+ if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
+ isToday = true;
+ }
+ //星期几
+ let nWeek = objDate.getDay(),
+ cWeek = calendar.nStr1[nWeek];
+ if (nWeek == 0) {
+ nWeek = 7;
+ } //数字表示周几顺应天朝周一开始的惯例
+ //农历年
+ let year = i;
+ leap = calendar.leapMonth(i); //闰哪个月
+ let isLeap = false;
+ //效验闰月
+ for (i = 1; i < 13 && offset > 0; i++) {
+ //闰月
+ if (leap > 0 && i == (leap + 1) && isLeap == false) {
+ --i;
+ isLeap = true;
+ temp = calendar.leapDays(year); //计算农历闰月天数
+ } else {
+ temp = calendar.monthDays(year, i); //计算农历普通月天数
+ }
+ //解除闰月
+ if (isLeap == true && i == (leap + 1)) {
+ isLeap = false;
+ }
+ offset -= temp;
+ }
+ if (offset == 0 && leap > 0 && i == leap + 1)
+ if (isLeap) {
+ isLeap = false;
+ } else {
+ isLeap = true;
+ --i;
+ }
+ if (offset < 0) {
+ offset += temp;
+ --i;
+ }
+ //农历月
+ let month = i;
+ //农历日
+ let day = offset + 1;
+ //天干地支处理
+ let sm = m - 1;
+ let gzY = calendar.toGanZhiYear(year);
+ //月柱 1900年1月小寒以前为 丙子月(60进制12)
+ let firstNode = calendar.getTerm(year, (m * 2 - 1)); //返回当月「节」为几日开始
+ let secondNode = calendar.getTerm(year, (m * 2)); //返回当月「节」为几日开始
+ //依据12节气修正干支月
+ let gzM = calendar.toGanZhi((y - 1900) * 12 + m + 11);
+ if (d >= firstNode) {
+ gzM = calendar.toGanZhi((y - 1900) * 12 + m + 12);
+ }
+ //传入的日期的节气与否
+ let isTerm = false;
+ let Term = null;
+ if (firstNode == d) {
+ isTerm = true;
+ Term = calendar.solarTerm[m * 2 - 2];
+ }
+ if (secondNode == d) {
+ isTerm = true;
+ Term = calendar.solarTerm[m * 2 - 1];
+ }
+ //日柱 当月一日与 1900/1/1 相差天数
+ let dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10;
+ let gzD = calendar.toGanZhi(dayCyclical + d - 1);
+ //该日期所属的星座
+ let astro = calendar.toAstro(m, d);
+ return {
+ 'lYear': year,
+ 'lMonth': month,
+ 'lDay': day,
+ 'Animal': calendar.getAnimal(year),
+ 'IMonthCn': (isLeap ? "\u95f0" : '') + calendar.toChinaMonth(month),
+ 'IDayCn': calendar.toChinaDay(day),
+ 'cYear': y,
+ 'cMonth': m,
+ 'cDay': d,
+ 'gzYear': gzY,
+ 'gzMonth': gzM,
+ 'gzDay': gzD,
+ 'isToday': isToday,
+ 'isLeap': isLeap,
+ 'nWeek': nWeek,
+ 'ncWeek': "\u661f\u671f" + cWeek,
+ 'isTerm': isTerm,
+ 'Term': Term,
+ 'astro': astro
+ };
+ },
+ /**
+ * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
+ * @param y lunar year
+ * @param m lunar month
+ * @param d lunar day
+ * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
+ * @return JSON object
+ * @eg:console.log(calendar.lunar2solar(1987,9,10));
+ */
+ lunar2solar: function(y, m, d, isLeapMonth) { //参数区间1900.1.31~2100.12.1
+ isLeapMonth = !!isLeapMonth;
+ let leapOffset = 0;
+ let leapMonth = calendar.leapMonth(y);
+ let leapDay = calendar.leapDays(y);
+ if (isLeapMonth && (leapMonth != m)) {
+ return -1;
+ } //传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
+ if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) {
+ return -1;
+ } //超出了最大极限值
+ let day = calendar.monthDays(y, m);
+ let _day = day;
+ //bugFix 2016-9-25
+ //if month is leap, _day use leapDays method
+ if (isLeapMonth) {
+ _day = calendar.leapDays(y, m);
+ }
+ if (y < 1900 || y > 2100 || d > _day) {
+ return -1;
+ } //参数合法性效验
+ //计算农历的时间差
+ let offset = 0;
+ for (let i = 1900; i < y; i++) {
+ offset += calendar.lYearDays(i);
+ }
+ let leap = 0,
+ isAdd = false;
+ for (let i = 1; i < m; i++) {
+ leap = calendar.leapMonth(y);
+ if (!isAdd) { //处理闰月
+ if (leap <= i && leap > 0) {
+ offset += calendar.leapDays(y);
+ isAdd = true;
+ }
+ }
+ offset += calendar.monthDays(y, i);
+ }
+ //转换闰月农历 需补充该年闰月的前一个月的时差
+ if (isLeapMonth) {
+ offset += day;
+ }
+ //1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
+ let stmap = Date.UTC(1900, 1, 30, 0, 0, 0);
+ let calObj = new Date((offset + d - 31) * 86400000 + stmap);
+ let cY = calObj.getUTCFullYear();
+ let cM = calObj.getUTCMonth() + 1;
+ let cD = calObj.getUTCDate();
+ return calendar.solar2lunar(cY, cM, cD);
+ }
+};
+
+module.exports = {
+ solar2lunar: calendar.solar2lunar,
+ lunar2solar: calendar.lunar2solar
+};
diff --git a/components/thorui/tui-calendar/tui-calendar.vue b/components/thorui/tui-calendar/tui-calendar.vue
new file mode 100644
index 0000000..8d4eee0
--- /dev/null
+++ b/components/thorui/tui-calendar/tui-calendar.vue
@@ -0,0 +1,925 @@
+
+
+
+
+
+
+
+
+
+
+ {{ showTitle }}
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+ {{ getDescText(index, startDate, endDate) }}
+
+
+
+
+ {{ startText }}
+
+ {{ endText }}
+
+ {{ month }}
+
+
+
+
+
+
diff --git a/components/thorui/tui-card/tui-card.vue b/components/thorui/tui-card/tui-card.vue
new file mode 100644
index 0000000..7214b33
--- /dev/null
+++ b/components/thorui/tui-card/tui-card.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-cascade-selection/tui-cascade-selection.vue b/components/thorui/tui-cascade-selection/tui-cascade-selection.vue
new file mode 100644
index 0000000..69729c5
--- /dev/null
+++ b/components/thorui/tui-cascade-selection/tui-cascade-selection.vue
@@ -0,0 +1,521 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ subItem.text }}
+
+ {{ subItem.subText }}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-circular-progress/tui-circular-progress.vue b/components/thorui/tui-circular-progress/tui-circular-progress.vue
new file mode 100644
index 0000000..19ab3ec
--- /dev/null
+++ b/components/thorui/tui-circular-progress/tui-circular-progress.vue
@@ -0,0 +1,264 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/thorui/tui-collapse/tui-collapse.vue b/components/thorui/tui-collapse/tui-collapse.vue
new file mode 100644
index 0000000..a812a2a
--- /dev/null
+++ b/components/thorui/tui-collapse/tui-collapse.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-countdown-verify/tui-countdown-verify.vue b/components/thorui/tui-countdown-verify/tui-countdown-verify.vue
new file mode 100644
index 0000000..695e99c
--- /dev/null
+++ b/components/thorui/tui-countdown-verify/tui-countdown-verify.vue
@@ -0,0 +1,226 @@
+
+
+ {{ showText }}
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-countdown/tui-countdown.vue b/components/thorui/tui-countdown/tui-countdown.vue
new file mode 100644
index 0000000..acdd0ba
--- /dev/null
+++ b/components/thorui/tui-countdown/tui-countdown.vue
@@ -0,0 +1,335 @@
+
+
+
+
+ {{ d }}
+
+
+
+ {{ isColon ? ':' : '天' }}
+
+
+
+ {{ h }}
+
+
+
+ {{ isColon ? ':' : '时' }}
+
+
+
+ {{ i }}
+
+
+
+ {{ isColon ? ':' : '分' }}
+
+
+
+ {{ s }}
+
+
+
+ {{ unitEn ? 's' : '秒' }}
+
+
+ .
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-cropper-app/tui-cropper-app.vue b/components/thorui/tui-cropper-app/tui-cropper-app.vue
new file mode 100644
index 0000000..e5fcd4c
--- /dev/null
+++ b/components/thorui/tui-cropper-app/tui-cropper-app.vue
@@ -0,0 +1,780 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+ 完成
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-cropper-app/tui-cropper-app.wxs b/components/thorui/tui-cropper-app/tui-cropper-app.wxs
new file mode 100644
index 0000000..7d7c119
--- /dev/null
+++ b/components/thorui/tui-cropper-app/tui-cropper-app.wxs
@@ -0,0 +1,560 @@
+var cropper = {
+ CUT_START: null,
+ cutX: 0, //画布x轴起点
+ cutY: 0, //画布y轴起点0
+ touchRelative: [{
+ x: 0,
+ y: 0
+ }], //手指或鼠标和图片中心的相对位置
+ flagCutTouch: false, //是否是拖动裁剪框
+ hypotenuseLength: 0, //双指触摸时斜边长度
+ flagEndTouch: false, //是否结束触摸
+ canvasWidth: 0,
+ canvasHeight: 0,
+ imgWidth: 0, //图片宽度
+ imgHeight: 0, //图片高度
+ scale: 1, //图片缩放比
+ angle: 0, //图片旋转角度
+ imgTop: 0, //图片上边距
+ imgLeft: 0, //图片左边距
+ //是否限制移动范围(剪裁框只能在图片内,为true不可触摸转动图片)
+ limitMove: true,
+ minHeight: 0,
+ maxHeight: 0,
+ minWidth: 0,
+ maxWidth: 0,
+ windowHeight: 0,
+ windowWidth: 0,
+ init: true
+}
+
+function bool(str) {
+ return str === 'true' || str == true ? true : false
+}
+
+function touchstart(e, ins) {
+ //var instance = e.instance;
+ // var state = instance.getState();
+ var touch = e.touches || e.changedTouches;
+ cropper.flagEndTouch = false;
+ if (touch.length == 1) {
+ cropper.touchRelative[0] = {
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ };
+ } else {
+ var width = Math.abs(touch[0].pageX - touch[1].pageX);
+ var height = Math.abs(touch[0].pageY - touch[1].pageY);
+ cropper.touchRelative = [{
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ },
+ {
+ x: touch[1].pageX - cropper.imgLeft,
+ y: touch[1].pageY - cropper.imgTop
+ }
+ ];
+ cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+ }
+
+}
+
+function moveDuring(ins) {
+ if (!ins) return;
+ ins.callMethod('moveDuring')
+}
+
+function moveStop(ins) {
+ if (!ins) return;
+ ins.callMethod('moveStop')
+};
+
+function setCutCenter(ins) {
+ var cutY = (cropper.windowHeight - cropper.canvasHeight) * 0.5;
+ var cutX = (cropper.windowWidth - cropper.canvasWidth) * 0.5;
+ //顺序不能变
+ cropper.imgTop = cropper.imgTop - cropper.cutY + cutY;
+ cropper.cutY = cutY; //截取的框上边距
+ cropper.imgLeft = cropper.imgLeft - cropper.cutX + cutX;
+ cropper.cutX = cutX; //截取的框左边距
+ styleUpdate(ins)
+ cutDetectionPosition(ins)
+ imgTransform(ins)
+ updateData(ins)
+}
+
+function touchmove(e, ins) {
+ var touch = e.touches || e.changedTouches;
+ if (cropper.flagEndTouch) return;
+ moveDuring(ins);
+ if (e.touches.length == 1) {
+ var left = touch[0].pageX - cropper.touchRelative[0].x,
+ top = touch[0].pageY - cropper.touchRelative[0].y;
+ cropper.imgLeft = left;
+ cropper.imgTop = top;
+ imgTransform(ins);
+ imgMarginDetectionPosition(ins);
+ } else {
+ var res = e.instance.getDataset();
+ var minScale = +res.minscale;
+ var maxScale = +res.maxscale;
+ var disableRotate = bool(res.disablerotate)
+ var width = Math.abs(touch[0].pageX - touch[1].pageX),
+ height = Math.abs(touch[0].pageY - touch[1].pageY),
+ hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
+ scale = cropper.scale * (hypotenuse / cropper.hypotenuseLength),
+ current_deg = 0;
+ scale = scale <= minScale ? minScale : scale;
+ scale = scale >= maxScale ? maxScale : scale;
+ cropper.scale = scale;
+ imgMarginDetectionScale(ins, true);
+ var touchRelative = [{
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ },
+ {
+ x: touch[1].pageX - cropper.imgLeft,
+ y: touch[1].pageY - cropper.imgTop
+ }
+ ];
+ if (!disableRotate) {
+ var first_atan = (180 / Math.PI) * Math.atan2(touchRelative[0].y, touchRelative[0].x);
+ var first_atan_old = (180 / Math.PI) * Math.atan2(cropper.touchRelative[0].y, cropper.touchRelative[0].x);
+ var second_atan = (180 / Math.PI) * Math.atan2(touchRelative[1].y, touchRelative[1].x);
+ var second_atan_old = (180 / Math.PI) * Math.atan2(cropper.touchRelative[1].y, cropper.touchRelative[1].x);
+ var first_deg = first_atan - first_atan_old,
+ second_deg = second_atan - second_atan_old;
+ if (first_deg != 0) {
+ current_deg = first_deg;
+ } else if (second_deg != 0) {
+ current_deg = second_deg;
+ }
+ }
+ cropper.touchRelative = touchRelative;
+ cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+ //更新视图
+ cropper.angle = cropper.angle + current_deg;
+ imgTransform(ins);
+ }
+}
+
+function touchend(e, ins) {
+ cropper.flagEndTouch = true;
+ moveStop(ins);
+ updateData(ins)
+}
+
+
+function cutTouchStart(e, ins) {
+ var touch = e.touches || e.changedTouches;
+ var currentX = touch[0].pageX;
+ var currentY = touch[0].pageY;
+
+ /*
+ * (右下-1 右上-2 左上-3 左下-4)
+ * left_x [3,4]
+ * top_y [2,3]
+ * right_x [1,2]
+ * bottom_y [1,4]
+ */
+ var left_x1 = cropper.cutX - 30;
+ var left_x2 = cropper.cutX + 30;
+
+ var top_y1 = cropper.cutY - 30;
+ var top_y2 = cropper.cutY + 30;
+
+ var right_x1 = cropper.cutX + cropper.canvasWidth - 30;
+ var right_x2 = cropper.cutX + cropper.canvasWidth + 30;
+
+ var bottom_y1 = cropper.cutY + cropper.canvasHeight - 30;
+ var bottom_y2 = cropper.cutY + cropper.canvasHeight + 30;
+
+ if (currentX > right_x1 && currentX < right_x2 && currentY > bottom_y1 && currentY < bottom_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ x: currentX,
+ y: currentY,
+ corner: 1
+ };
+ } else if (currentX > right_x1 && currentX < right_x2 && currentY > top_y1 && currentY < top_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ x: currentX,
+ y: currentY,
+ cutY: cropper.cutY,
+ cutX: cropper.cutX,
+ corner: 2
+ };
+ } else if (currentX > left_x1 && currentX < left_x2 && currentY > top_y1 && currentY < top_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ cutY: cropper.cutY,
+ cutX: cropper.cutX,
+ x: currentX,
+ y: currentY,
+ corner: 3
+ };
+ } else if (currentX > left_x1 && currentX < left_x2 && currentY > bottom_y1 && currentY < bottom_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ cutY: cropper.cutY,
+ cutX: cropper.cutX,
+ x: currentX,
+ y: currentY,
+ corner: 4
+ };
+ }
+}
+
+function cutTouchMove(e, ins) {
+ if (!cropper.CUT_START || cropper.CUT_START === 'null') return;
+ if (cropper.flagCutTouch) {
+ var touch = e.touches || e.changedTouches;
+ var res = e.instance.getDataset();
+ var lockRatio = bool(res.lockratio);
+ var lockWidth = bool(res.lockwidth);
+ var lockHeight = bool(res.lockheight);
+ if (lockRatio && (lockWidth || lockHeight)) return;
+ var width = cropper.canvasWidth,
+ height = cropper.canvasHeight,
+ cutY = cropper.cutY,
+ cutX = cropper.cutX;
+
+ var size_correct = function() {
+ width = width <= cropper.maxWidth ? (width >= cropper.minWidth ? width : cropper.minWidth) : cropper.maxWidth;
+ height = height <= cropper.maxHeight ? (height >= cropper.minHeight ? height : cropper.minHeight) : cropper.maxHeight;
+ }
+
+ var size_inspect = function() {
+ if ((width > cropper.maxWidth || width < cropper.minWidth || height > cropper.maxHeight || height < cropper.minHeight) &&
+ lockRatio) {
+ size_correct();
+ return false;
+ } else {
+ size_correct();
+ return true;
+ }
+ };
+ height = cropper.CUT_START.height + (cropper.CUT_START.corner > 1 && cropper.CUT_START.corner < 4 ? 1 : -1) * (
+ cropper.CUT_START.y - touch[0].pageY);
+ switch (cropper.CUT_START.corner) {
+ case 1:
+ width = cropper.CUT_START.width - cropper.CUT_START.x + touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ break;
+ case 2:
+ width = cropper.CUT_START.width - cropper.CUT_START.x + touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ cutY = cropper.CUT_START.cutY - (height - cropper.CUT_START.height);
+ break;
+ case 3:
+ width = cropper.CUT_START.width + cropper.CUT_START.x - touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ cutY = cropper.CUT_START.cutY - (height - cropper.CUT_START.height);
+ cutX = cropper.CUT_START.cutX - (width - cropper.CUT_START.width);
+ break;
+ case 4:
+ width = cropper.CUT_START.width + cropper.CUT_START.x - touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ cutX = cropper.CUT_START.cutX - (width - cropper.CUT_START.width);
+ break;
+ default:
+ break;
+ }
+ if (!lockWidth && !lockHeight) {
+ cropper.canvasWidth = width;
+ cropper.cutX = cutX;
+ cropper.canvasHeight = height;
+ cropper.cutY = cutY;
+ canvasHeight(ins);
+ canvasWidth(ins);
+ } else if (!lockWidth) {
+ cropper.canvasWidth = width;
+ cropper.cutX = cutX;
+ canvasWidth(ins);
+ } else if (!lockHeight) {
+ cropper.canvasHeight = height;
+ cropper.cutY = cutY;
+ canvasHeight(ins);
+ }
+ styleUpdate(ins)
+ imgMarginDetectionScale(ins);
+ }
+}
+
+//检测剪裁框位置是否在允许的范围内(屏幕内)
+function cutDetectionPosition(ins) {
+ var windowHeight = cropper.windowHeight,
+ windowWidth = cropper.windowWidth;
+
+ var cutDetectionPositionTop = function() {
+ //检测上边距是否在范围内
+ if (cropper.cutY < 0) {
+ cropper.cutY = 0;
+ }
+ if (cropper.cutY > windowHeight - cropper.canvasHeight) {
+ cropper.cutY = windowHeight - cropper.canvasHeight;
+ }
+ }
+
+ var cutDetectionPositionLeft = function() {
+ //检测左边距是否在范围内
+ if (cropper.cutX < 0) {
+ cropper.cutX = 0;
+ }
+ if (cropper.cutX > windowWidth - cropper.canvasWidth) {
+ cropper.cutX = windowWidth - cropper.canvasWidth;
+ }
+ }
+ //裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)
+ if (cropper.cutY == null && cropper.cutX == null) {
+ var cutY = (windowHeight - cropper.canvasHeight) * 0.5;
+ var cutX = (windowWidth - cropper.canvasWidth) * 0.5;
+ cropper.cutY = cutY; //截取的框上边距
+ cropper.cutX = cutX; //截取的框左边距
+ } else if (cropper.cutY != null && cropper.cutX != null) {
+ cutDetectionPositionTop();
+ cutDetectionPositionLeft();
+ } else if (cropper.cutY != null && cropper.cutX == null) {
+ cutDetectionPositionTop();
+ cropper.cutX = (windowWidth - cropper.canvasWidth) / 2;
+ } else if (cropper.cutY == null && cropper.cutX != null) {
+ cutDetectionPositionLeft();
+ cropper.cutY = (windowHeight - cropper.canvasHeight) / 2;
+ }
+
+ styleUpdate(ins)
+}
+
+/**
+ * 图片边缘检测-缩放
+ */
+function imgMarginDetectionScale(ins, delay) {
+ if (!cropper.limitMove) return;
+ var scale = cropper.scale;
+ var imgWidth = cropper.imgWidth;
+ var imgHeight = cropper.imgHeight;
+ if ((cropper.angle / 90) % 2) {
+ imgWidth = cropper.imgHeight;
+ imgHeight = cropper.imgWidth;
+ }
+ if (imgWidth * scale < cropper.canvasWidth) {
+ scale = cropper.canvasWidth / imgWidth;
+ }
+ if (imgHeight * scale < cropper.canvasHeight) {
+ scale = Math.max(scale, cropper.canvasHeight / imgHeight);
+ }
+ imgMarginDetectionPosition(ins, scale, delay);
+}
+/**
+ * 图片边缘检测-位置
+ */
+function imgMarginDetectionPosition(ins, scale, delay) {
+ if (!cropper.limitMove) return;
+ var left = cropper.imgLeft;
+ var top = cropper.imgTop;
+ scale = scale || cropper.scale;
+ var imgWidth = cropper.imgWidth;
+ var imgHeight = cropper.imgHeight;
+ if ((cropper.angle / 90) % 2) {
+ imgWidth = cropper.imgHeight;
+ imgHeight = cropper.imgWidth;
+ }
+ left = cropper.cutX + (imgWidth * scale) / 2 >= left ? left : cropper.cutX + (imgWidth * scale) / 2;
+ left = cropper.cutX + cropper.canvasWidth - (imgWidth * scale) / 2 <= left ? left : cropper.cutX + cropper.canvasWidth -
+ (imgWidth * scale) / 2;
+ top = cropper.cutY + (imgHeight * scale) / 2 >= top ? top : cropper.cutY + (imgHeight * scale) / 2;
+ top = cropper.cutY + cropper.canvasHeight - (imgHeight * scale) / 2 <= top ? top : cropper.cutY + cropper.canvasHeight -
+ (imgHeight * scale) / 2;
+
+ cropper.imgLeft = left;
+ cropper.imgTop = top;
+ cropper.scale = scale;
+ styleUpdate(ins)
+ if (!delay || delay === 'null') {
+ imgTransform(ins);
+ }
+}
+
+
+function cutTouchEnd(e, ins) {
+ moveStop(ins);
+ cropper.flagCutTouch = false;
+ updateData(ins)
+}
+
+
+//改变截取框大小
+function computeCutSize(ins) {
+ if (cropper.canvasWidth > cropper.windowWidth) {
+ cropper.canvasWidth = cropper.windowWidth;
+ // canvasWidth(ins)
+ } else if (cropper.canvasWidth + cropper.cutX > cropper.windowWidth) {
+ cropper.cutX = cropper.windowWidth - cropper.cutX;
+ }
+ if (cropper.canvasHeight > cropper.windowHeight) {
+ cropper.canvasHeight = cropper.windowHeight;
+ // canvasHeight(ins)
+ } else if (cropper.canvasHeight + cropper.cutY > cropper.windowHeight) {
+ cropper.cutY = cropper.windowHeight - cropper.cutY;
+ }
+ // styleUpdate(ins)
+}
+
+function styleUpdate(ins) {
+ if (!ins) return;
+ ins.selectComponent('.tui-cropper-box').setStyle({
+ 'width': cropper.canvasWidth + 'px',
+ 'height': cropper.canvasHeight + 'px'
+ })
+ ins.selectComponent('.tui-content-middle').setStyle({
+ 'height': cropper.canvasHeight + 'px'
+ })
+ ins.selectComponent('.tui-content-top').setStyle({
+ 'height': cropper.cutY + 'px'
+ })
+ ins.selectComponent('.tui-wxs-bg').setStyle({
+ 'width': cropper.cutX + 'px'
+ })
+
+}
+
+function imgTransform(ins) {
+ var owner = ins.selectComponent('.tui-cropper-image')
+ if (!owner) return
+ var x = cropper.imgLeft - cropper.imgWidth / 2;
+ var y = cropper.imgTop - cropper.imgHeight / 2;
+ owner.setStyle({
+ 'transform': 'translate3d(' + x + 'px,' + y + 'px,0) scale(' + cropper.scale + ') rotate(' + cropper.angle + 'deg)'
+ })
+}
+
+function imageReset(ins) {
+ cropper.scale = 1;
+ cropper.angle = 0;
+ imgTransform(ins);
+}
+//监听截取框宽高变化
+function canvasWidth(ins) {
+ if (cropper.canvasWidth < cropper.minWidth) {
+ cropper.canvasWidth = cropper.minWidth;
+ }
+ if (!ins) return;
+ computeCutSize(ins);
+}
+
+function canvasHeight(ins) {
+ if (cropper.canvasHeight < cropper.minHeight) {
+ cropper.canvasHeight = cropper.minHeight;
+ }
+ if (!ins) return;
+ computeCutSize(ins);
+}
+
+function updateData(ins) {
+ if (!ins) return;
+ ins.callMethod('change', {
+ cutX: cropper.cutX,
+ cutY: cropper.cutY,
+ canvasWidth: cropper.canvasWidth,
+ canvasHeight: cropper.canvasHeight,
+ imgWidth: cropper.imgWidth,
+ imgHeight: cropper.imgHeight,
+ scale: cropper.scale,
+ angle: cropper.angle,
+ imgTop: cropper.imgTop,
+ imgLeft: cropper.imgLeft
+ })
+}
+
+function propsChange(prop, oldProp, ownerInstance, ins) {
+ if (prop && prop !== 'null') {
+ var params = prop.split(',')
+ var type = +params[0]
+ var dataset = ins.getDataset();
+ if (cropper.init || type == 4) {
+ cropper.maxHeight = +dataset.maxheight;
+ cropper.minHeight = +dataset.minheight;
+ cropper.maxWidth = +dataset.maxwidth;
+ cropper.minWidth = +dataset.minwidth;
+ cropper.canvasWidth = +dataset.width;
+ cropper.canvasHeight = +dataset.height;
+ cropper.imgTop = dataset.windowheight / 2;
+ cropper.imgLeft = dataset.windowwidth / 2;
+ cropper.imgWidth = +dataset.imgwidth;
+ cropper.imgHeight = +dataset.imgheight;
+ cropper.windowHeight = +dataset.windowheight;
+ cropper.windowWidth = +dataset.windowwidth;
+ cropper.init = false
+ } else if (type == 2 || type == 3) {
+ cropper.imgWidth = +dataset.imgwidth;
+ cropper.imgHeight = +dataset.imgheight;
+ }
+ cropper.limitMove = bool(dataset.limitmove);
+ cropper.angle = +dataset.angle;
+ if (type == 3) {
+ imgTransform(ownerInstance);
+ }
+ switch (type) {
+ case 1:
+ setCutCenter(ownerInstance);
+ //设置裁剪框大小>设置图片尺寸>绘制canvas
+ computeCutSize(ownerInstance);
+ //检查裁剪框是否在范围内
+ cutDetectionPosition(ownerInstance);
+ break;
+ case 2:
+ setCutCenter(ownerInstance);
+ break;
+ case 3:
+ imgMarginDetectionScale(ownerInstance)
+ break;
+ case 4:
+ imageReset(ownerInstance);
+ break;
+ case 5:
+ setCutCenter(ownerInstance);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+module.exports = {
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ cutTouchStart: cutTouchStart,
+ cutTouchMove: cutTouchMove,
+ cutTouchEnd: cutTouchEnd,
+ propsChange: propsChange
+}
diff --git a/components/thorui/tui-cropper/tui-cropper.vue b/components/thorui/tui-cropper/tui-cropper.vue
new file mode 100644
index 0000000..e18a562
--- /dev/null
+++ b/components/thorui/tui-cropper/tui-cropper.vue
@@ -0,0 +1,505 @@
+
+
+
+
+
+
+
+
+ 取消
+
+ 完成
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-cropper/tui-cropper.wxs b/components/thorui/tui-cropper/tui-cropper.wxs
new file mode 100644
index 0000000..122e5d9
--- /dev/null
+++ b/components/thorui/tui-cropper/tui-cropper.wxs
@@ -0,0 +1,321 @@
+var cropper = {
+ cutX: 0, //画布x轴起点
+ cutY: 0, //画布y轴起点0
+ touchRelative: [{
+ x: 0,
+ y: 0
+ }], //手指或鼠标和图片中心的相对位置
+ hypotenuseLength: 0, //双指触摸时斜边长度
+ flagEndTouch: false, //是否结束触摸
+ canvasWidth: 0,
+ canvasHeight: 0,
+ imgWidth: 0, //图片宽度
+ imgHeight: 0, //图片高度
+ scale: 1, //图片缩放比
+ angle: 0, //图片旋转角度
+ imgTop: 0, //图片上边距
+ imgLeft: 0, //图片左边距
+ windowHeight: 0,
+ windowWidth: 0,
+ init: true
+}
+
+function bool(str) {
+ return str === 'true' || str == true ? true : false
+}
+
+function touchstart(e, ins) {
+ var touch = e.touches || e.changedTouches;
+ cropper.flagEndTouch = false;
+ if (touch.length == 1) {
+ cropper.touchRelative[0] = {
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ };
+ } else {
+ var width = Math.abs(touch[0].pageX - touch[1].pageX);
+ var height = Math.abs(touch[0].pageY - touch[1].pageY);
+ cropper.touchRelative = [{
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ },
+ {
+ x: touch[1].pageX - cropper.imgLeft,
+ y: touch[1].pageY - cropper.imgTop
+ }
+ ];
+ cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+ }
+
+}
+
+function moveDuring(ins) {
+ if (!ins) return;
+ ins.callMethod('moveDuring')
+}
+
+function moveStop(ins) {
+ if (!ins) return;
+ ins.callMethod('moveStop')
+};
+
+function setCutCenter(ins) {
+ var cutY = (cropper.windowHeight - cropper.canvasHeight) * 0.5;
+ var cutX = (cropper.windowWidth - cropper.canvasWidth) * 0.5;
+ //顺序不能变
+ cropper.imgTop = cropper.imgTop - cropper.cutY + cutY;
+ cropper.cutY = cutY; //截取的框上边距
+ cropper.imgLeft = cropper.imgLeft - cropper.cutX + cutX;
+ cropper.cutX = cutX; //截取的框左边距
+ cutDetectionPosition(ins)
+ imgTransform(ins)
+ updateData(ins)
+}
+
+function touchmove(e, ins) {
+ var touch = e.touches || e.changedTouches;
+ if (cropper.flagEndTouch) return;
+ moveDuring(ins);
+ if (e.touches.length == 1) {
+ var left = touch[0].pageX - cropper.touchRelative[0].x,
+ top = touch[0].pageY - cropper.touchRelative[0].y;
+ cropper.imgLeft = left;
+ cropper.imgTop = top;
+ imgTransform(ins);
+ imgMarginDetectionPosition(ins);
+ } else {
+ var res = e.instance.getDataset();
+ var minScale = +res.minscale;
+ var maxScale = +res.maxscale;
+ var width = Math.abs(touch[0].pageX - touch[1].pageX),
+ height = Math.abs(touch[0].pageY - touch[1].pageY),
+ hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
+ scale = cropper.scale * (hypotenuse / cropper.hypotenuseLength),
+ current_deg = 0;
+ scale = scale <= minScale ? minScale : scale;
+ scale = scale >= maxScale ? maxScale : scale;
+ cropper.scale = scale;
+ imgMarginDetectionScale(ins, true);
+ var touchRelative = [{
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ },
+ {
+ x: touch[1].pageX - cropper.imgLeft,
+ y: touch[1].pageY - cropper.imgTop
+ }
+ ];
+ cropper.touchRelative = touchRelative;
+ cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+ //更新视图
+ cropper.angle = cropper.angle + current_deg;
+ imgTransform(ins);
+ }
+}
+
+function touchend(e, ins) {
+ cropper.flagEndTouch = true;
+ moveStop(ins);
+ updateData(ins)
+}
+
+
+//检测剪裁框位置是否在允许的范围内(屏幕内)
+function cutDetectionPosition(ins) {
+ var windowHeight = cropper.windowHeight,
+ windowWidth = cropper.windowWidth;
+
+ var cutDetectionPositionTop = function() {
+ //检测上边距是否在范围内
+ if (cropper.cutY < 0) {
+ cropper.cutY = 0;
+ }
+ if (cropper.cutY > windowHeight - cropper.canvasHeight) {
+ cropper.cutY = windowHeight - cropper.canvasHeight;
+ }
+ }
+
+ var cutDetectionPositionLeft = function() {
+ //检测左边距是否在范围内
+ if (cropper.cutX < 0) {
+ cropper.cutX = 0;
+ }
+ if (cropper.cutX > windowWidth - cropper.canvasWidth) {
+ cropper.cutX = windowWidth - cropper.canvasWidth;
+ }
+ }
+ //裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)
+ if (cropper.cutY == null && cropper.cutX == null) {
+ var cutY = (windowHeight - cropper.canvasHeight) * 0.5;
+ var cutX = (windowWidth - cropper.canvasWidth) * 0.5;
+ cropper.cutY = cutY; //截取的框上边距
+ cropper.cutX = cutX; //截取的框左边距
+ } else if (cropper.cutY != null && cropper.cutX != null) {
+ cutDetectionPositionTop();
+ cutDetectionPositionLeft();
+ } else if (cropper.cutY != null && cropper.cutX == null) {
+ cutDetectionPositionTop();
+ cropper.cutX = (windowWidth - cropper.canvasWidth) / 2;
+ } else if (cropper.cutY == null && cropper.cutX != null) {
+ cutDetectionPositionLeft();
+ cropper.cutY = (windowHeight - cropper.canvasHeight) / 2;
+ }
+}
+
+/**
+ * 图片边缘检测-缩放
+ */
+function imgMarginDetectionScale(ins, delay) {
+ var scale = cropper.scale;
+ var imgWidth = cropper.imgWidth;
+ var imgHeight = cropper.imgHeight;
+ if ((cropper.angle / 90) % 2) {
+ imgWidth = cropper.imgHeight;
+ imgHeight = cropper.imgWidth;
+ }
+ if (imgWidth * scale < cropper.canvasWidth) {
+ scale = cropper.canvasWidth / imgWidth;
+ }
+ if (imgHeight * scale < cropper.canvasHeight) {
+ scale = Math.max(scale, cropper.canvasHeight / imgHeight);
+ }
+ imgMarginDetectionPosition(ins, scale, delay);
+}
+/**
+ * 图片边缘检测-位置
+ */
+function imgMarginDetectionPosition(ins, scale, delay) {
+ var left = cropper.imgLeft;
+ var top = cropper.imgTop;
+ scale = scale || cropper.scale;
+ var imgWidth = cropper.imgWidth;
+ var imgHeight = cropper.imgHeight;
+ if ((cropper.angle / 90) % 2) {
+ imgWidth = cropper.imgHeight;
+ imgHeight = cropper.imgWidth;
+ }
+ left = cropper.cutX + (imgWidth * scale) / 2 >= left ? left : cropper.cutX + (imgWidth * scale) / 2;
+ left = cropper.cutX + cropper.canvasWidth - (imgWidth * scale) / 2 <= left ? left : cropper.cutX + cropper.canvasWidth -
+ (imgWidth * scale) / 2;
+ top = cropper.cutY + (imgHeight * scale) / 2 >= top ? top : cropper.cutY + (imgHeight * scale) / 2;
+ top = cropper.cutY + cropper.canvasHeight - (imgHeight * scale) / 2 <= top ? top : cropper.cutY + cropper.canvasHeight -
+ (imgHeight * scale) / 2;
+
+ cropper.imgLeft = left;
+ cropper.imgTop = top;
+ cropper.scale = scale;
+ if (!delay || delay === 'null') {
+ imgTransform(ins);
+ }
+}
+
+
+//改变截取框大小
+function computeCutSize(ins) {
+ if (cropper.canvasWidth > cropper.windowWidth) {
+ cropper.canvasWidth = cropper.windowWidth;
+ } else if (cropper.canvasWidth + cropper.cutX > cropper.windowWidth) {
+ cropper.cutX = cropper.windowWidth - cropper.cutX;
+ }
+ if (cropper.canvasHeight > cropper.windowHeight) {
+ cropper.canvasHeight = cropper.windowHeight;
+ } else if (cropper.canvasHeight + cropper.cutY > cropper.windowHeight) {
+ cropper.cutY = cropper.windowHeight - cropper.cutY;
+ }
+}
+
+function imgTransform(ins) {
+ var owner = ins.selectComponent('.tui-cropper__image')
+ if (!owner) return
+ var x = cropper.imgLeft - cropper.imgWidth / 2;
+ var y = cropper.imgTop - cropper.imgHeight / 2;
+ owner.setStyle({
+ 'transform': 'translate3d(' + x + 'px,' + y + 'px,0) scale(' + cropper.scale + ') rotate(' + cropper.angle + 'deg)'
+ })
+}
+
+function imageReset(ins) {
+ cropper.scale = 1;
+ cropper.angle = 0;
+ imgTransform(ins);
+}
+//监听截取框宽高变化
+function canvasWidth(ins) {
+ if (!ins) return;
+ computeCutSize(ins);
+}
+
+function canvasHeight(ins) {
+ if (!ins) return;
+ computeCutSize(ins);
+}
+
+function updateData(ins) {
+ if (!ins) return;
+ ins.callMethod('change', {
+ cutX: cropper.cutX,
+ cutY: cropper.cutY,
+ imgWidth: cropper.imgWidth,
+ imgHeight: cropper.imgHeight,
+ scale: cropper.scale,
+ angle: cropper.angle,
+ imgTop: cropper.imgTop,
+ imgLeft: cropper.imgLeft
+ })
+}
+
+function propsChange(prop, oldProp, ownerInstance, ins) {
+ if (prop && prop !== 'null') {
+ var params = prop.split(',')
+ var type = +params[0]
+ var dataset = ins.getDataset();
+ if (cropper.init || type == 4) {
+ cropper.canvasWidth = +dataset.width;
+ cropper.canvasHeight = +dataset.height;
+ cropper.imgTop = dataset.windowheight / 2;
+ cropper.imgLeft = dataset.windowwidth / 2;
+ cropper.imgWidth = +dataset.imgwidth;
+ cropper.imgHeight = +dataset.imgheight;
+ cropper.windowHeight = +dataset.windowheight;
+ cropper.windowWidth = +dataset.windowwidth;
+ cropper.init = false
+ } else if (type == 2 || type == 3) {
+ cropper.imgWidth = +dataset.imgwidth;
+ cropper.imgHeight = +dataset.imgheight;
+ }
+ cropper.angle = +dataset.angle;
+ if (type == 3) {
+ imgTransform(ownerInstance);
+ }
+ switch (type) {
+ case 1:
+ setCutCenter(ownerInstance);
+ //设置裁剪框大小>设置图片尺寸>绘制canvas
+ computeCutSize(ownerInstance);
+ //检查裁剪框是否在范围内
+ cutDetectionPosition(ownerInstance);
+ break;
+ case 2:
+ setCutCenter(ownerInstance);
+ break;
+ case 3:
+ imgMarginDetectionScale(ownerInstance)
+ break;
+ case 4:
+ imageReset(ownerInstance);
+ break;
+ case 5:
+ setCutCenter(ownerInstance);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+module.exports = {
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ propsChange: propsChange
+}
diff --git a/components/thorui/tui-datetime/tui-datetime.vue b/components/thorui/tui-datetime/tui-datetime.vue
new file mode 100644
index 0000000..9b30017
--- /dev/null
+++ b/components/thorui/tui-datetime/tui-datetime.vue
@@ -0,0 +1,548 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-divider/tui-divider.vue b/components/thorui/tui-divider/tui-divider.vue
new file mode 100644
index 0000000..ec96112
--- /dev/null
+++ b/components/thorui/tui-divider/tui-divider.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-drawer/tui-drawer.vue b/components/thorui/tui-drawer/tui-drawer.vue
new file mode 100644
index 0000000..e183223
--- /dev/null
+++ b/components/thorui/tui-drawer/tui-drawer.vue
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-dropdown-list/tui-dropdown-list.vue b/components/thorui/tui-dropdown-list/tui-dropdown-list.vue
new file mode 100644
index 0000000..e9eb77d
--- /dev/null
+++ b/components/thorui/tui-dropdown-list/tui-dropdown-list.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-fab/tui-fab.vue b/components/thorui/tui-fab/tui-fab.vue
new file mode 100644
index 0000000..5efd197
--- /dev/null
+++ b/components/thorui/tui-fab/tui-fab.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
+ {{item.text || ""}}
+
+ {{item.text || ""}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-footer/tui-footer.vue b/components/thorui/tui-footer/tui-footer.vue
new file mode 100644
index 0000000..b0dd70d
--- /dev/null
+++ b/components/thorui/tui-footer/tui-footer.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-grid-item/tui-grid-item.vue b/components/thorui/tui-grid-item/tui-grid-item.vue
new file mode 100644
index 0000000..e0f1ea3
--- /dev/null
+++ b/components/thorui/tui-grid-item/tui-grid-item.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-grid/tui-grid.vue b/components/thorui/tui-grid/tui-grid.vue
new file mode 100644
index 0000000..f4f189a
--- /dev/null
+++ b/components/thorui/tui-grid/tui-grid.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-icon/tui-icon.vue b/components/thorui/tui-icon/tui-icon.vue
new file mode 100644
index 0000000..55a9c74
--- /dev/null
+++ b/components/thorui/tui-icon/tui-icon.vue
@@ -0,0 +1,816 @@
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-image-cropper/tui-image-cropper.vue b/components/thorui/tui-image-cropper/tui-image-cropper.vue
new file mode 100644
index 0000000..523f57a
--- /dev/null
+++ b/components/thorui/tui-image-cropper/tui-image-cropper.vue
@@ -0,0 +1,1030 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+ 完成
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-image-group/tui-image-group.vue b/components/thorui/tui-image-group/tui-image-group.vue
new file mode 100644
index 0000000..0bd0eec
--- /dev/null
+++ b/components/thorui/tui-image-group/tui-image-group.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-keyboard-input/tui-keyboard-input.vue b/components/thorui/tui-keyboard-input/tui-keyboard-input.vue
new file mode 100644
index 0000000..143bc6c
--- /dev/null
+++ b/components/thorui/tui-keyboard-input/tui-keyboard-input.vue
@@ -0,0 +1,73 @@
+
+
+
+ {{item}}
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-keyboard/tui-keyboard.vue b/components/thorui/tui-keyboard/tui-keyboard.vue
new file mode 100644
index 0000000..df391e1
--- /dev/null
+++ b/components/thorui/tui-keyboard/tui-keyboard.vue
@@ -0,0 +1,240 @@
+
+
+
+
+
+
+
+
+ {{getKeyBoard(index,action)}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-lazyload-img/tui-lazyload-img.vue b/components/thorui/tui-lazyload-img/tui-lazyload-img.vue
new file mode 100644
index 0000000..c093483
--- /dev/null
+++ b/components/thorui/tui-lazyload-img/tui-lazyload-img.vue
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-list-cell/tui-list-cell.vue b/components/thorui/tui-list-cell/tui-list-cell.vue
new file mode 100644
index 0000000..19ac128
--- /dev/null
+++ b/components/thorui/tui-list-cell/tui-list-cell.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-list-view/tui-list-view.vue b/components/thorui/tui-list-view/tui-list-view.vue
new file mode 100644
index 0000000..d14ebdb
--- /dev/null
+++ b/components/thorui/tui-list-view/tui-list-view.vue
@@ -0,0 +1,97 @@
+
+
+ {{title}}
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-loading/tui-loading.vue b/components/thorui/tui-loading/tui-loading.vue
new file mode 100644
index 0000000..4c38a09
--- /dev/null
+++ b/components/thorui/tui-loading/tui-loading.vue
@@ -0,0 +1,78 @@
+
+
+
+ {{text}}
+
+
+
+
+
+
diff --git a/components/thorui/tui-loadmore/tui-loadmore.vue b/components/thorui/tui-loadmore/tui-loadmore.vue
new file mode 100644
index 0000000..4c9ab65
--- /dev/null
+++ b/components/thorui/tui-loadmore/tui-loadmore.vue
@@ -0,0 +1,161 @@
+
+
+
+ {{text}}
+
+
+
+
+
+
diff --git a/components/thorui/tui-modal/tui-modal.vue b/components/thorui/tui-modal/tui-modal.vue
new file mode 100644
index 0000000..4e34929
--- /dev/null
+++ b/components/thorui/tui-modal/tui-modal.vue
@@ -0,0 +1,407 @@
+
+
+
+
+ {{ title }}
+ {{ content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-navigation-bar/tui-navigation-bar.vue b/components/thorui/tui-navigation-bar/tui-navigation-bar.vue
new file mode 100644
index 0000000..07ffd5c
--- /dev/null
+++ b/components/thorui/tui-navigation-bar/tui-navigation-bar.vue
@@ -0,0 +1,250 @@
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-no-data/tui-no-data.vue b/components/thorui/tui-no-data/tui-no-data.vue
new file mode 100644
index 0000000..c825052
--- /dev/null
+++ b/components/thorui/tui-no-data/tui-no-data.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+ {{btnText}}
+
+
+
+
+
+
diff --git a/components/thorui/tui-nomore/tui-nomore.vue b/components/thorui/tui-nomore/tui-nomore.vue
new file mode 100644
index 0000000..cbc9d61
--- /dev/null
+++ b/components/thorui/tui-nomore/tui-nomore.vue
@@ -0,0 +1,115 @@
+
+
+
+ {{isDot?dotText:text}}
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-numberbox/tui-numberbox.vue b/components/thorui/tui-numberbox/tui-numberbox.vue
new file mode 100644
index 0000000..dd301f0
--- /dev/null
+++ b/components/thorui/tui-numberbox/tui-numberbox.vue
@@ -0,0 +1,222 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-overflow-hidden/tui-overflow-hidden.vue b/components/thorui/tui-overflow-hidden/tui-overflow-hidden.vue
new file mode 100644
index 0000000..20f4a7a
--- /dev/null
+++ b/components/thorui/tui-overflow-hidden/tui-overflow-hidden.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-picture-cropper/tui-picture-cropper.vue b/components/thorui/tui-picture-cropper/tui-picture-cropper.vue
new file mode 100644
index 0000000..f9b5328
--- /dev/null
+++ b/components/thorui/tui-picture-cropper/tui-picture-cropper.vue
@@ -0,0 +1,699 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+ 完成
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-picture-cropper/tui-picture-cropper.wxs b/components/thorui/tui-picture-cropper/tui-picture-cropper.wxs
new file mode 100644
index 0000000..7d7c119
--- /dev/null
+++ b/components/thorui/tui-picture-cropper/tui-picture-cropper.wxs
@@ -0,0 +1,560 @@
+var cropper = {
+ CUT_START: null,
+ cutX: 0, //画布x轴起点
+ cutY: 0, //画布y轴起点0
+ touchRelative: [{
+ x: 0,
+ y: 0
+ }], //手指或鼠标和图片中心的相对位置
+ flagCutTouch: false, //是否是拖动裁剪框
+ hypotenuseLength: 0, //双指触摸时斜边长度
+ flagEndTouch: false, //是否结束触摸
+ canvasWidth: 0,
+ canvasHeight: 0,
+ imgWidth: 0, //图片宽度
+ imgHeight: 0, //图片高度
+ scale: 1, //图片缩放比
+ angle: 0, //图片旋转角度
+ imgTop: 0, //图片上边距
+ imgLeft: 0, //图片左边距
+ //是否限制移动范围(剪裁框只能在图片内,为true不可触摸转动图片)
+ limitMove: true,
+ minHeight: 0,
+ maxHeight: 0,
+ minWidth: 0,
+ maxWidth: 0,
+ windowHeight: 0,
+ windowWidth: 0,
+ init: true
+}
+
+function bool(str) {
+ return str === 'true' || str == true ? true : false
+}
+
+function touchstart(e, ins) {
+ //var instance = e.instance;
+ // var state = instance.getState();
+ var touch = e.touches || e.changedTouches;
+ cropper.flagEndTouch = false;
+ if (touch.length == 1) {
+ cropper.touchRelative[0] = {
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ };
+ } else {
+ var width = Math.abs(touch[0].pageX - touch[1].pageX);
+ var height = Math.abs(touch[0].pageY - touch[1].pageY);
+ cropper.touchRelative = [{
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ },
+ {
+ x: touch[1].pageX - cropper.imgLeft,
+ y: touch[1].pageY - cropper.imgTop
+ }
+ ];
+ cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+ }
+
+}
+
+function moveDuring(ins) {
+ if (!ins) return;
+ ins.callMethod('moveDuring')
+}
+
+function moveStop(ins) {
+ if (!ins) return;
+ ins.callMethod('moveStop')
+};
+
+function setCutCenter(ins) {
+ var cutY = (cropper.windowHeight - cropper.canvasHeight) * 0.5;
+ var cutX = (cropper.windowWidth - cropper.canvasWidth) * 0.5;
+ //顺序不能变
+ cropper.imgTop = cropper.imgTop - cropper.cutY + cutY;
+ cropper.cutY = cutY; //截取的框上边距
+ cropper.imgLeft = cropper.imgLeft - cropper.cutX + cutX;
+ cropper.cutX = cutX; //截取的框左边距
+ styleUpdate(ins)
+ cutDetectionPosition(ins)
+ imgTransform(ins)
+ updateData(ins)
+}
+
+function touchmove(e, ins) {
+ var touch = e.touches || e.changedTouches;
+ if (cropper.flagEndTouch) return;
+ moveDuring(ins);
+ if (e.touches.length == 1) {
+ var left = touch[0].pageX - cropper.touchRelative[0].x,
+ top = touch[0].pageY - cropper.touchRelative[0].y;
+ cropper.imgLeft = left;
+ cropper.imgTop = top;
+ imgTransform(ins);
+ imgMarginDetectionPosition(ins);
+ } else {
+ var res = e.instance.getDataset();
+ var minScale = +res.minscale;
+ var maxScale = +res.maxscale;
+ var disableRotate = bool(res.disablerotate)
+ var width = Math.abs(touch[0].pageX - touch[1].pageX),
+ height = Math.abs(touch[0].pageY - touch[1].pageY),
+ hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
+ scale = cropper.scale * (hypotenuse / cropper.hypotenuseLength),
+ current_deg = 0;
+ scale = scale <= minScale ? minScale : scale;
+ scale = scale >= maxScale ? maxScale : scale;
+ cropper.scale = scale;
+ imgMarginDetectionScale(ins, true);
+ var touchRelative = [{
+ x: touch[0].pageX - cropper.imgLeft,
+ y: touch[0].pageY - cropper.imgTop
+ },
+ {
+ x: touch[1].pageX - cropper.imgLeft,
+ y: touch[1].pageY - cropper.imgTop
+ }
+ ];
+ if (!disableRotate) {
+ var first_atan = (180 / Math.PI) * Math.atan2(touchRelative[0].y, touchRelative[0].x);
+ var first_atan_old = (180 / Math.PI) * Math.atan2(cropper.touchRelative[0].y, cropper.touchRelative[0].x);
+ var second_atan = (180 / Math.PI) * Math.atan2(touchRelative[1].y, touchRelative[1].x);
+ var second_atan_old = (180 / Math.PI) * Math.atan2(cropper.touchRelative[1].y, cropper.touchRelative[1].x);
+ var first_deg = first_atan - first_atan_old,
+ second_deg = second_atan - second_atan_old;
+ if (first_deg != 0) {
+ current_deg = first_deg;
+ } else if (second_deg != 0) {
+ current_deg = second_deg;
+ }
+ }
+ cropper.touchRelative = touchRelative;
+ cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+ //更新视图
+ cropper.angle = cropper.angle + current_deg;
+ imgTransform(ins);
+ }
+}
+
+function touchend(e, ins) {
+ cropper.flagEndTouch = true;
+ moveStop(ins);
+ updateData(ins)
+}
+
+
+function cutTouchStart(e, ins) {
+ var touch = e.touches || e.changedTouches;
+ var currentX = touch[0].pageX;
+ var currentY = touch[0].pageY;
+
+ /*
+ * (右下-1 右上-2 左上-3 左下-4)
+ * left_x [3,4]
+ * top_y [2,3]
+ * right_x [1,2]
+ * bottom_y [1,4]
+ */
+ var left_x1 = cropper.cutX - 30;
+ var left_x2 = cropper.cutX + 30;
+
+ var top_y1 = cropper.cutY - 30;
+ var top_y2 = cropper.cutY + 30;
+
+ var right_x1 = cropper.cutX + cropper.canvasWidth - 30;
+ var right_x2 = cropper.cutX + cropper.canvasWidth + 30;
+
+ var bottom_y1 = cropper.cutY + cropper.canvasHeight - 30;
+ var bottom_y2 = cropper.cutY + cropper.canvasHeight + 30;
+
+ if (currentX > right_x1 && currentX < right_x2 && currentY > bottom_y1 && currentY < bottom_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ x: currentX,
+ y: currentY,
+ corner: 1
+ };
+ } else if (currentX > right_x1 && currentX < right_x2 && currentY > top_y1 && currentY < top_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ x: currentX,
+ y: currentY,
+ cutY: cropper.cutY,
+ cutX: cropper.cutX,
+ corner: 2
+ };
+ } else if (currentX > left_x1 && currentX < left_x2 && currentY > top_y1 && currentY < top_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ cutY: cropper.cutY,
+ cutX: cropper.cutX,
+ x: currentX,
+ y: currentY,
+ corner: 3
+ };
+ } else if (currentX > left_x1 && currentX < left_x2 && currentY > bottom_y1 && currentY < bottom_y2) {
+ moveDuring();
+ cropper.flagCutTouch = true;
+ cropper.flagEndTouch = true;
+ cropper.CUT_START = {
+ width: cropper.canvasWidth,
+ height: cropper.canvasHeight,
+ cutY: cropper.cutY,
+ cutX: cropper.cutX,
+ x: currentX,
+ y: currentY,
+ corner: 4
+ };
+ }
+}
+
+function cutTouchMove(e, ins) {
+ if (!cropper.CUT_START || cropper.CUT_START === 'null') return;
+ if (cropper.flagCutTouch) {
+ var touch = e.touches || e.changedTouches;
+ var res = e.instance.getDataset();
+ var lockRatio = bool(res.lockratio);
+ var lockWidth = bool(res.lockwidth);
+ var lockHeight = bool(res.lockheight);
+ if (lockRatio && (lockWidth || lockHeight)) return;
+ var width = cropper.canvasWidth,
+ height = cropper.canvasHeight,
+ cutY = cropper.cutY,
+ cutX = cropper.cutX;
+
+ var size_correct = function() {
+ width = width <= cropper.maxWidth ? (width >= cropper.minWidth ? width : cropper.minWidth) : cropper.maxWidth;
+ height = height <= cropper.maxHeight ? (height >= cropper.minHeight ? height : cropper.minHeight) : cropper.maxHeight;
+ }
+
+ var size_inspect = function() {
+ if ((width > cropper.maxWidth || width < cropper.minWidth || height > cropper.maxHeight || height < cropper.minHeight) &&
+ lockRatio) {
+ size_correct();
+ return false;
+ } else {
+ size_correct();
+ return true;
+ }
+ };
+ height = cropper.CUT_START.height + (cropper.CUT_START.corner > 1 && cropper.CUT_START.corner < 4 ? 1 : -1) * (
+ cropper.CUT_START.y - touch[0].pageY);
+ switch (cropper.CUT_START.corner) {
+ case 1:
+ width = cropper.CUT_START.width - cropper.CUT_START.x + touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ break;
+ case 2:
+ width = cropper.CUT_START.width - cropper.CUT_START.x + touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ cutY = cropper.CUT_START.cutY - (height - cropper.CUT_START.height);
+ break;
+ case 3:
+ width = cropper.CUT_START.width + cropper.CUT_START.x - touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ cutY = cropper.CUT_START.cutY - (height - cropper.CUT_START.height);
+ cutX = cropper.CUT_START.cutX - (width - cropper.CUT_START.width);
+ break;
+ case 4:
+ width = cropper.CUT_START.width + cropper.CUT_START.x - touch[0].pageX;
+ if (lockRatio) {
+ height = width / (cropper.canvasWidth / cropper.canvasHeight);
+ }
+ if (!size_inspect()) return;
+ cutX = cropper.CUT_START.cutX - (width - cropper.CUT_START.width);
+ break;
+ default:
+ break;
+ }
+ if (!lockWidth && !lockHeight) {
+ cropper.canvasWidth = width;
+ cropper.cutX = cutX;
+ cropper.canvasHeight = height;
+ cropper.cutY = cutY;
+ canvasHeight(ins);
+ canvasWidth(ins);
+ } else if (!lockWidth) {
+ cropper.canvasWidth = width;
+ cropper.cutX = cutX;
+ canvasWidth(ins);
+ } else if (!lockHeight) {
+ cropper.canvasHeight = height;
+ cropper.cutY = cutY;
+ canvasHeight(ins);
+ }
+ styleUpdate(ins)
+ imgMarginDetectionScale(ins);
+ }
+}
+
+//检测剪裁框位置是否在允许的范围内(屏幕内)
+function cutDetectionPosition(ins) {
+ var windowHeight = cropper.windowHeight,
+ windowWidth = cropper.windowWidth;
+
+ var cutDetectionPositionTop = function() {
+ //检测上边距是否在范围内
+ if (cropper.cutY < 0) {
+ cropper.cutY = 0;
+ }
+ if (cropper.cutY > windowHeight - cropper.canvasHeight) {
+ cropper.cutY = windowHeight - cropper.canvasHeight;
+ }
+ }
+
+ var cutDetectionPositionLeft = function() {
+ //检测左边距是否在范围内
+ if (cropper.cutX < 0) {
+ cropper.cutX = 0;
+ }
+ if (cropper.cutX > windowWidth - cropper.canvasWidth) {
+ cropper.cutX = windowWidth - cropper.canvasWidth;
+ }
+ }
+ //裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)
+ if (cropper.cutY == null && cropper.cutX == null) {
+ var cutY = (windowHeight - cropper.canvasHeight) * 0.5;
+ var cutX = (windowWidth - cropper.canvasWidth) * 0.5;
+ cropper.cutY = cutY; //截取的框上边距
+ cropper.cutX = cutX; //截取的框左边距
+ } else if (cropper.cutY != null && cropper.cutX != null) {
+ cutDetectionPositionTop();
+ cutDetectionPositionLeft();
+ } else if (cropper.cutY != null && cropper.cutX == null) {
+ cutDetectionPositionTop();
+ cropper.cutX = (windowWidth - cropper.canvasWidth) / 2;
+ } else if (cropper.cutY == null && cropper.cutX != null) {
+ cutDetectionPositionLeft();
+ cropper.cutY = (windowHeight - cropper.canvasHeight) / 2;
+ }
+
+ styleUpdate(ins)
+}
+
+/**
+ * 图片边缘检测-缩放
+ */
+function imgMarginDetectionScale(ins, delay) {
+ if (!cropper.limitMove) return;
+ var scale = cropper.scale;
+ var imgWidth = cropper.imgWidth;
+ var imgHeight = cropper.imgHeight;
+ if ((cropper.angle / 90) % 2) {
+ imgWidth = cropper.imgHeight;
+ imgHeight = cropper.imgWidth;
+ }
+ if (imgWidth * scale < cropper.canvasWidth) {
+ scale = cropper.canvasWidth / imgWidth;
+ }
+ if (imgHeight * scale < cropper.canvasHeight) {
+ scale = Math.max(scale, cropper.canvasHeight / imgHeight);
+ }
+ imgMarginDetectionPosition(ins, scale, delay);
+}
+/**
+ * 图片边缘检测-位置
+ */
+function imgMarginDetectionPosition(ins, scale, delay) {
+ if (!cropper.limitMove) return;
+ var left = cropper.imgLeft;
+ var top = cropper.imgTop;
+ scale = scale || cropper.scale;
+ var imgWidth = cropper.imgWidth;
+ var imgHeight = cropper.imgHeight;
+ if ((cropper.angle / 90) % 2) {
+ imgWidth = cropper.imgHeight;
+ imgHeight = cropper.imgWidth;
+ }
+ left = cropper.cutX + (imgWidth * scale) / 2 >= left ? left : cropper.cutX + (imgWidth * scale) / 2;
+ left = cropper.cutX + cropper.canvasWidth - (imgWidth * scale) / 2 <= left ? left : cropper.cutX + cropper.canvasWidth -
+ (imgWidth * scale) / 2;
+ top = cropper.cutY + (imgHeight * scale) / 2 >= top ? top : cropper.cutY + (imgHeight * scale) / 2;
+ top = cropper.cutY + cropper.canvasHeight - (imgHeight * scale) / 2 <= top ? top : cropper.cutY + cropper.canvasHeight -
+ (imgHeight * scale) / 2;
+
+ cropper.imgLeft = left;
+ cropper.imgTop = top;
+ cropper.scale = scale;
+ styleUpdate(ins)
+ if (!delay || delay === 'null') {
+ imgTransform(ins);
+ }
+}
+
+
+function cutTouchEnd(e, ins) {
+ moveStop(ins);
+ cropper.flagCutTouch = false;
+ updateData(ins)
+}
+
+
+//改变截取框大小
+function computeCutSize(ins) {
+ if (cropper.canvasWidth > cropper.windowWidth) {
+ cropper.canvasWidth = cropper.windowWidth;
+ // canvasWidth(ins)
+ } else if (cropper.canvasWidth + cropper.cutX > cropper.windowWidth) {
+ cropper.cutX = cropper.windowWidth - cropper.cutX;
+ }
+ if (cropper.canvasHeight > cropper.windowHeight) {
+ cropper.canvasHeight = cropper.windowHeight;
+ // canvasHeight(ins)
+ } else if (cropper.canvasHeight + cropper.cutY > cropper.windowHeight) {
+ cropper.cutY = cropper.windowHeight - cropper.cutY;
+ }
+ // styleUpdate(ins)
+}
+
+function styleUpdate(ins) {
+ if (!ins) return;
+ ins.selectComponent('.tui-cropper-box').setStyle({
+ 'width': cropper.canvasWidth + 'px',
+ 'height': cropper.canvasHeight + 'px'
+ })
+ ins.selectComponent('.tui-content-middle').setStyle({
+ 'height': cropper.canvasHeight + 'px'
+ })
+ ins.selectComponent('.tui-content-top').setStyle({
+ 'height': cropper.cutY + 'px'
+ })
+ ins.selectComponent('.tui-wxs-bg').setStyle({
+ 'width': cropper.cutX + 'px'
+ })
+
+}
+
+function imgTransform(ins) {
+ var owner = ins.selectComponent('.tui-cropper-image')
+ if (!owner) return
+ var x = cropper.imgLeft - cropper.imgWidth / 2;
+ var y = cropper.imgTop - cropper.imgHeight / 2;
+ owner.setStyle({
+ 'transform': 'translate3d(' + x + 'px,' + y + 'px,0) scale(' + cropper.scale + ') rotate(' + cropper.angle + 'deg)'
+ })
+}
+
+function imageReset(ins) {
+ cropper.scale = 1;
+ cropper.angle = 0;
+ imgTransform(ins);
+}
+//监听截取框宽高变化
+function canvasWidth(ins) {
+ if (cropper.canvasWidth < cropper.minWidth) {
+ cropper.canvasWidth = cropper.minWidth;
+ }
+ if (!ins) return;
+ computeCutSize(ins);
+}
+
+function canvasHeight(ins) {
+ if (cropper.canvasHeight < cropper.minHeight) {
+ cropper.canvasHeight = cropper.minHeight;
+ }
+ if (!ins) return;
+ computeCutSize(ins);
+}
+
+function updateData(ins) {
+ if (!ins) return;
+ ins.callMethod('change', {
+ cutX: cropper.cutX,
+ cutY: cropper.cutY,
+ canvasWidth: cropper.canvasWidth,
+ canvasHeight: cropper.canvasHeight,
+ imgWidth: cropper.imgWidth,
+ imgHeight: cropper.imgHeight,
+ scale: cropper.scale,
+ angle: cropper.angle,
+ imgTop: cropper.imgTop,
+ imgLeft: cropper.imgLeft
+ })
+}
+
+function propsChange(prop, oldProp, ownerInstance, ins) {
+ if (prop && prop !== 'null') {
+ var params = prop.split(',')
+ var type = +params[0]
+ var dataset = ins.getDataset();
+ if (cropper.init || type == 4) {
+ cropper.maxHeight = +dataset.maxheight;
+ cropper.minHeight = +dataset.minheight;
+ cropper.maxWidth = +dataset.maxwidth;
+ cropper.minWidth = +dataset.minwidth;
+ cropper.canvasWidth = +dataset.width;
+ cropper.canvasHeight = +dataset.height;
+ cropper.imgTop = dataset.windowheight / 2;
+ cropper.imgLeft = dataset.windowwidth / 2;
+ cropper.imgWidth = +dataset.imgwidth;
+ cropper.imgHeight = +dataset.imgheight;
+ cropper.windowHeight = +dataset.windowheight;
+ cropper.windowWidth = +dataset.windowwidth;
+ cropper.init = false
+ } else if (type == 2 || type == 3) {
+ cropper.imgWidth = +dataset.imgwidth;
+ cropper.imgHeight = +dataset.imgheight;
+ }
+ cropper.limitMove = bool(dataset.limitmove);
+ cropper.angle = +dataset.angle;
+ if (type == 3) {
+ imgTransform(ownerInstance);
+ }
+ switch (type) {
+ case 1:
+ setCutCenter(ownerInstance);
+ //设置裁剪框大小>设置图片尺寸>绘制canvas
+ computeCutSize(ownerInstance);
+ //检查裁剪框是否在范围内
+ cutDetectionPosition(ownerInstance);
+ break;
+ case 2:
+ setCutCenter(ownerInstance);
+ break;
+ case 3:
+ imgMarginDetectionScale(ownerInstance)
+ break;
+ case 4:
+ imageReset(ownerInstance);
+ break;
+ case 5:
+ setCutCenter(ownerInstance);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+module.exports = {
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ cutTouchStart: cutTouchStart,
+ cutTouchMove: cutTouchMove,
+ cutTouchEnd: cutTouchEnd,
+ propsChange: propsChange
+}
diff --git a/components/thorui/tui-popup/tui-popup.vue b/components/thorui/tui-popup/tui-popup.vue
new file mode 100644
index 0000000..3349d0c
--- /dev/null
+++ b/components/thorui/tui-popup/tui-popup.vue
@@ -0,0 +1,266 @@
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-rate/tui-rate.vue b/components/thorui/tui-rate/tui-rate.vue
new file mode 100644
index 0000000..d670f3f
--- /dev/null
+++ b/components/thorui/tui-rate/tui-rate.vue
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-round-progress/tui-round-progress.vue b/components/thorui/tui-round-progress/tui-round-progress.vue
new file mode 100644
index 0000000..4b50fe9
--- /dev/null
+++ b/components/thorui/tui-round-progress/tui-round-progress.vue
@@ -0,0 +1,292 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-scroll-top/tui-scroll-top.vue b/components/thorui/tui-scroll-top/tui-scroll-top.vue
new file mode 100644
index 0000000..3c15cb6
--- /dev/null
+++ b/components/thorui/tui-scroll-top/tui-scroll-top.vue
@@ -0,0 +1,178 @@
+
+
+
+
+ 首页
+
+
+
+
+
+
+
+ 顶部
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-skeleton/tui-skeleton.vue b/components/thorui/tui-skeleton/tui-skeleton.vue
new file mode 100644
index 0000000..9d63ba4
--- /dev/null
+++ b/components/thorui/tui-skeleton/tui-skeleton.vue
@@ -0,0 +1,239 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-slide-verify/tui-slide-verify.vue b/components/thorui/tui-slide-verify/tui-slide-verify.vue
new file mode 100644
index 0000000..8f53909
--- /dev/null
+++ b/components/thorui/tui-slide-verify/tui-slide-verify.vue
@@ -0,0 +1,217 @@
+
+
+ 拖动滑块验证
+
+ {{passText}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-slide-verify/tui-slide-verify.wxs b/components/thorui/tui-slide-verify/tui-slide-verify.wxs
new file mode 100644
index 0000000..1ab80e7
--- /dev/null
+++ b/components/thorui/tui-slide-verify/tui-slide-verify.wxs
@@ -0,0 +1,73 @@
+var slideBarWidth = 200;
+var slideBlockWidth = 32;
+var errorRange = 2
+var disabled = false
+
+function bool(str) {
+ return str === 'true' || str == true ? true : false
+}
+
+function touchstart(e, ins) {
+ var state=e.instance.getState()
+ var touch = e.touches[0] || e.changedTouches[0]
+ var dataset = e.instance.getDataset()
+ state.startX = touch.pageX
+ slideBarWidth = +dataset.slidebarwidth
+ slideBlockWidth = +dataset.slideblockwidth
+ errorRange = +dataset.errorrange
+ disabled = bool(dataset.disabled)
+}
+
+function styleChange(left, ins) {
+ if (!ins) return;
+ ins.selectComponent('.tui-slider-block').setStyle({
+ transform: 'translate3d(' + left + 'px,0,0)'
+ })
+ ins.selectComponent('.tui-slide-glided').setStyle({
+ width: left + 'px'
+ })
+}
+
+function touchmove(e, ins) {
+ if (disabled) return;
+ var state=e.instance.getState()
+ var touch = e.touches[0] || e.changedTouches[0]
+ var pageX = touch.pageX;
+ var left = pageX - state.startX + (state.lastLeft || 0);
+ left = left < 0 ? 0 : left;
+ var width = slideBarWidth - slideBlockWidth;
+ left = left >= width ? width : left;
+ state.startX = pageX
+ state.lastLeft = left
+ styleChange(left, ins)
+}
+
+function touchend(e, ins) {
+ if (disabled) return;
+ var state=e.instance.getState()
+ let left = slideBarWidth - slideBlockWidth
+ if (left - state.lastLeft <= errorRange) {
+ styleChange(left, ins)
+ ins.callMethod('success')
+ } else {
+ state.startX = 0;
+ state.lastLeft = 0;
+ styleChange(0, ins)
+ }
+}
+
+function slidereset(reset, oldreset, owner, ins) {
+ var state=ins.getState()
+ if (reset > 0) {
+ state.startX = 0;
+ state.lastLeft = 0;
+ styleChange(0, owner)
+ }
+}
+
+module.exports = {
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ slidereset: slidereset
+}
\ No newline at end of file
diff --git a/components/thorui/tui-steps/tui-steps.vue b/components/thorui/tui-steps/tui-steps.vue
new file mode 100644
index 0000000..e11fd2a
--- /dev/null
+++ b/components/thorui/tui-steps/tui-steps.vue
@@ -0,0 +1,254 @@
+
+
+
+
+
+ {{ type == 1 ? '' : index + 1 }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+ {{ item.desc }}
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-sticky-wxs/tui-sticky-wxs.vue b/components/thorui/tui-sticky-wxs/tui-sticky-wxs.vue
new file mode 100644
index 0000000..8eb8e03
--- /dev/null
+++ b/components/thorui/tui-sticky-wxs/tui-sticky-wxs.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-sticky-wxs/tui-sticky.wxs b/components/thorui/tui-sticky-wxs/tui-sticky.wxs
new file mode 100644
index 0000000..044a23d
--- /dev/null
+++ b/components/thorui/tui-sticky-wxs/tui-sticky.wxs
@@ -0,0 +1,44 @@
+var stickyChange = function(scrollTop, oldScrollTop, ownerInstance, ins) {
+ if (!oldScrollTop && scrollTop === 0) return false;
+ var dataset = ins.getDataset()
+ var top = +dataset.top;
+ var height = +dataset.height;
+ var stickyTop = +dataset.stickytop;
+ var isNativeHeader = dataset.isnativeheader;
+ var isFixed = false;
+ var distance = stickyTop
+ // #ifdef H5
+ if (isNativeHeader) {
+ distance = distance - 44
+ distance = distance < 0 ? 0 : distance
+ }
+ // #endif
+ if (dataset.container) {
+ isFixed = (scrollTop + distance >= top && scrollTop + distance < top + height) ? true : false
+ } else {
+ isFixed = scrollTop + distance >= top ? true : false
+ }
+ if (isFixed) {
+ ownerInstance.selectComponent('.tui-sticky-bar').setStyle({
+ "top": stickyTop + 'px'
+ }).addClass('tui-sticky-fixed')
+ ownerInstance.selectComponent('.tui-sticky-seat').setStyle({
+ "display": 'block'
+ })
+ } else {
+ ownerInstance.selectComponent('.tui-sticky-bar').setStyle({
+ "top": 'auto'
+ }).removeClass('tui-sticky-fixed')
+ ownerInstance.selectComponent('.tui-sticky-seat').setStyle({
+ "display": 'none'
+ })
+ }
+ ownerInstance.triggerEvent("sticky", {
+ isFixed: isFixed,
+ index: parseInt(dataset.index)
+ })
+}
+
+module.exports = {
+ stickyChange: stickyChange
+}
diff --git a/components/thorui/tui-sticky/tui-sticky.vue b/components/thorui/tui-sticky/tui-sticky.vue
new file mode 100644
index 0000000..9199d4f
--- /dev/null
+++ b/components/thorui/tui-sticky/tui-sticky.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-swipe-action/tui-swipe-action.vue b/components/thorui/tui-swipe-action/tui-swipe-action.vue
new file mode 100644
index 0000000..634defc
--- /dev/null
+++ b/components/thorui/tui-swipe-action/tui-swipe-action.vue
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-tab/tui-tab.vue b/components/thorui/tui-tab/tui-tab.vue
new file mode 100644
index 0000000..13825bc
--- /dev/null
+++ b/components/thorui/tui-tab/tui-tab.vue
@@ -0,0 +1,273 @@
+
+
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-tabbar/tui-tabbar.vue b/components/thorui/tui-tabbar/tui-tabbar.vue
new file mode 100644
index 0000000..24d282c
--- /dev/null
+++ b/components/thorui/tui-tabbar/tui-tabbar.vue
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+
+ {{ item.isDot ? '' : item.num }}
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-tabs/tui-tabs.vue b/components/thorui/tui-tabs/tui-tabs.vue
new file mode 100644
index 0000000..5ee5837
--- /dev/null
+++ b/components/thorui/tui-tabs/tui-tabs.vue
@@ -0,0 +1,276 @@
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-tag/tui-tag.vue b/components/thorui/tui-tag/tui-tag.vue
new file mode 100644
index 0000000..82b9d08
--- /dev/null
+++ b/components/thorui/tui-tag/tui-tag.vue
@@ -0,0 +1,354 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-time-axis/tui-time-axis.vue b/components/thorui/tui-time-axis/tui-time-axis.vue
new file mode 100644
index 0000000..dc346c0
--- /dev/null
+++ b/components/thorui/tui-time-axis/tui-time-axis.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-timeaxis-item/tui-timeaxis-item.vue b/components/thorui/tui-timeaxis-item/tui-timeaxis-item.vue
new file mode 100644
index 0000000..154b8f6
--- /dev/null
+++ b/components/thorui/tui-timeaxis-item/tui-timeaxis-item.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-tips/tui-tips.vue b/components/thorui/tui-tips/tui-tips.vue
new file mode 100644
index 0000000..bd6900a
--- /dev/null
+++ b/components/thorui/tui-tips/tui-tips.vue
@@ -0,0 +1,129 @@
+
+
+ {{ msg }}
+
+
+
+ {{ msg }}
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-toast/tui-toast.vue b/components/thorui/tui-toast/tui-toast.vue
new file mode 100644
index 0000000..31b6f8f
--- /dev/null
+++ b/components/thorui/tui-toast/tui-toast.vue
@@ -0,0 +1,121 @@
+
+
+
+ {{title}}
+ {{content}}
+
+
+
+
+
+
diff --git a/components/thorui/tui-top-dropdown/tui-top-dropdown.vue b/components/thorui/tui-top-dropdown/tui-top-dropdown.vue
new file mode 100644
index 0000000..d343231
--- /dev/null
+++ b/components/thorui/tui-top-dropdown/tui-top-dropdown.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-upload/tui-upload.vue b/components/thorui/tui-upload/tui-upload.vue
new file mode 100644
index 0000000..0220e58
--- /dev/null
+++ b/components/thorui/tui-upload/tui-upload.vue
@@ -0,0 +1,467 @@
+
+
+
+
+
+
+
+
+ {{statusArr[index]==2?'上传中...':'上传失败'}}
+ 重新上传
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/thorui/tui-waterfall/tui-waterfall.vue b/components/thorui/tui-waterfall/tui-waterfall.vue
new file mode 100644
index 0000000..1cee8bc
--- /dev/null
+++ b/components/thorui/tui-waterfall/tui-waterfall.vue
@@ -0,0 +1,223 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages2/balance/balance.vue b/pages2/balance/balance.vue
new file mode 100644
index 0000000..3db5b7e
--- /dev/null
+++ b/pages2/balance/balance.vue
@@ -0,0 +1,526 @@
+
+
+
+ 我的余额
+
+
+
+
+
+
+
+
+ 用户名:{{ userInfo.nickname }}
+ uid: ({{ userInfo._id }})
+ 手机号:{{ userInfo.mobile }}
+
+ 名词解释
+
+
+
+
+
+
+
+
+
+
+
+ 可提现余额
+
+ {{ userInfo.available }}
+ 元
+
+
+
+ 立即提现
+
+
+
+
+
+ { 0 }}
+ 元
+
+ 剩余提现额度
+
+
+
+
+
+ {{ 0 }}
+ 元
+
+ 累计收益
+
+
+
+
+
+ {{ userInfo.total_withdraw }}
+ 元
+
+ 累计提现
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+ 提现{{ item.status == 1 ? '成功' : item.status == 2 ? '处理中' : '失败' }}
+
+ {{ item.create_time }}
+
+
+
+ {{ is_withdraw ? '-' : '+' }}{{ tabIndex == 3 ? item.real_money : item.money }}
+
+
+
+ 仅显示近一年内的收支记录
+
+
+
+
+
+
+
+
+
+
diff --git a/pages2/setting/bind-mobile/bind-mobile.vue b/pages2/setting/bind-mobile/bind-mobile.vue
new file mode 100644
index 0000000..6ccb152
--- /dev/null
+++ b/pages2/setting/bind-mobile/bind-mobile.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages2/setting/cutImage.vue b/pages2/setting/cutImage.vue
new file mode 100644
index 0000000..52e8e60
--- /dev/null
+++ b/pages2/setting/cutImage.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages2/setting/limeClipper/README.md b/pages2/setting/limeClipper/README.md
new file mode 100644
index 0000000..9219f81
--- /dev/null
+++ b/pages2/setting/limeClipper/README.md
@@ -0,0 +1,227 @@
+> 插件来源:[https://ext.dcloud.net.cn/plugin?id=3594](https://ext.dcloud.net.cn/plugin?id=3594)
+##### 以下是作者写的插件介绍:
+
+# Clipper 图片裁剪
+> uniapp 图片裁剪,可用于图片头像等裁剪处理
+> [查看更多](http://liangei.gitee.io/limeui/#/clipper)
+> Q群:458377637
+
+
+## 平台兼容
+
+| H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App |
+| --- | ---------- | ------------ | ---------- | ---------- | --------- | --- |
+| √ | √ | √ | 未测 | √ | √ | √ |
+
+
+## 代码演示
+### 基本用法
+`@success` 事件点击 👉 **确定** 后会返回生成的图片信息,包含 `url`、`width`、`height`
+
+```html
+
+
+
+```
+
+```js
+// 非uni_modules引入
+import lClipper from '@/components/lime-clipper/'
+// uni_modules引入
+import lClipper from '@/uni_modules/lime-clipper/components/lime-clipper/'
+export default {
+ components: {lClipper},
+ data() {
+ return {
+ show: false,
+ url: '',
+ }
+ }
+}
+```
+
+
+### 传入图片
+`image-url`可传入**相对路径**、**临时路径**、**本地路径**、**网络图片**
+
+* **当为网络地址时**
+* H5:👉 需要解决跨域问题。
+* 小程序:👉 需要配置 downloadFile 域名
+
+
+```html
+
+
+
+```
+
+```js
+export default {
+ components: {lClipper},
+ data() {
+ return {
+ imageUrl: 'https://img12.360buyimg.com/pop/s1180x940_jfs/t1/97205/26/1142/87801/5dbac55aEf795d962/48a4d7a63ff80b8b.jpg',
+ show: false,
+ url: '',
+ }
+ }
+}
+```
+
+
+### 确定按钮颜色
+样式变量名:`--l-clipper-confirm-color`
+可放到全局样式的 `page` 里或节点的 `style`
+```html
+
+```
+```css
+// css 中为组件设置 CSS 变量
+.clipper {
+ --l-clipper-confirm-color: linear-gradient(to right, #ff6034, #ee0a24)
+}
+// 全局
+page {
+ --l-clipper-confirm-color: linear-gradient(to right, #ff6034, #ee0a24)
+}
+```
+
+
+### 使用插槽
+共五个插槽 `cancel` 取消按钮、 `photo` 选择图片按钮、 `rotate` 旋转按钮、 `confirm` 确定按钮和默认插槽。
+
+```html
+
+
+
+ 取消
+ 选择图片
+ 旋转
+ 确定
+
+
+ 显示取消按钮
+
+
+ 显示选择图片按钮
+
+
+ 显示旋转按钮
+
+
+ 显示确定按钮
+
+
+ 锁定裁剪框宽度
+
+
+ 锁定裁剪框高度
+
+
+ 锁定裁剪框比例
+
+
+ 限制移动范围
+
+
+ 禁止缩放
+
+
+ 禁止旋转
+
+
+
+
+
+```
+
+```js
+export default {
+ components: {lClipper},
+ data() {
+ return {
+ show: false,
+ url: '',
+ isLockWidth: false,
+ isLockHeight: false,
+ isLockRatio: true,
+ isLimitMove: false,
+ isDisableScale: false,
+ isDisableRotate: false,
+ isShowCancelBtn: true,
+ isShowPhotoBtn: true,
+ isShowRotateBtn: true,
+ isShowConfirmBtn: true
+ }
+ }
+}
+```
+
+
+## API
+
+### Props
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ------------- | ------------ | ---------------- | ------------ |
+| image-url | 图片路径 | string | |
+| quality | 图片的质量,取值范围为 [0, 1],不在范围内时当作1处理 | number | `1` |
+| source | `{album: '从相册中选择'}`key为图片来源类型,value为选项说明 | Object | |
+| width | 裁剪框宽度,单位为 `rpx` | number | `400` |
+| height | 裁剪框高度 | number | `400` |
+| min-width | 裁剪框最小宽度 | number | `200` |
+| min-height |裁剪框最小高度 | number | `200` |
+| max-width | 裁剪框最大宽度 | number | `600` |
+| max-height | 裁剪框最大宽度 | number | `600` |
+| min-ratio | 图片最小缩放比 | number | `0.5` |
+| max-ratio | 图片最大缩放比 | number | `2` |
+| rotate-angle | 旋转按钮每次旋转的角度 | number | `90` |
+| scale-ratio | 生成图片相对于裁剪框的比例, **比例越高生成图片越清晰** | number | `1` |
+| is-lock-width | 是否锁定裁剪框宽度 | boolean | `false` |
+| is-lock-height | 是否锁定裁剪框高度上 | boolean | `false` |
+| is-lock-ratio | 是否锁定裁剪框比例 | boolean | `true` |
+| is-disable-scale | 是否禁止缩放 | boolean | `false` |
+| is-disable-rotate | 是否禁止旋转 | boolean | `false` |
+| is-limit-move | 是否限制移动范围 | boolean | `false` |
+| is-show-photo-btn | 是否显示选择图片按钮 | boolean | `true` |
+| is-show-rotate-btn | 是否显示转按钮 | boolean | `true` |
+| is-show-confirm-btn | 是否显示确定按钮 | boolean | `true` |
+| is-show-cancel-btn | 是否显示关闭按钮 | boolean | `true` |
+
+
+
+### 事件 Events
+
+| 事件名 | 说明 | 回调 |
+| ------- | ------------ | -------------- |
+| success | 生成图片成功 | {`width`, `height`, `url`} |
+| fail | 生成图片失败 | `error` |
+| cancel | 关闭 | `false` |
+| ready | 图片加载完成 | {`width`, `height`, `path`, `orientation`, `type`} |
+| change | 图片大小改变时触发 | {`width`, `height`} |
+| rotate | 图片旋转时触发 | `angle` |
+
+## 常见问题
+> 1、H5端使用网络图片需要解决跨域问题。
+> 2、小程序使用网络图片需要去公众平台增加下载白名单!二级域名也需要配!
+> 3、H5端生成图片是base64,有时显示只有一半可以使用原生标签`
`
+> 4、IOS APP 请勿使用HBX2.9.3.20201014的版本!这个版本无法生成图片。
+> 5、APP端无成功反馈、也无失败反馈时,请更新基座和HBX。
+
+
+## 打赏
+如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
+
\ No newline at end of file
diff --git a/pages2/setting/limeClipper/images/photo.svg b/pages2/setting/limeClipper/images/photo.svg
new file mode 100644
index 0000000..7b4b590
--- /dev/null
+++ b/pages2/setting/limeClipper/images/photo.svg
@@ -0,0 +1,19 @@
+
+
+
diff --git a/pages2/setting/limeClipper/images/rotate.svg b/pages2/setting/limeClipper/images/rotate.svg
new file mode 100644
index 0000000..0143706
--- /dev/null
+++ b/pages2/setting/limeClipper/images/rotate.svg
@@ -0,0 +1,15 @@
+
+
+
diff --git a/pages2/setting/limeClipper/index.css b/pages2/setting/limeClipper/index.css
new file mode 100644
index 0000000..ce542bf
--- /dev/null
+++ b/pages2/setting/limeClipper/index.css
@@ -0,0 +1,160 @@
+.flex-auto {
+ flex: auto;
+}
+.bg-transparent {
+ background-color: rgba(0,0,0,0.9);
+ transition-duration: 0.35s;
+}
+.l-clipper {
+ width: 100vw;
+ height: calc(100vh - var(--window-top));
+ background-color: rgba(0,0,0,0.9);
+ position: fixed;
+ top: var(--window-top);
+ left: 0;
+ z-index: 1;
+}
+.l-clipper-mask {
+ position: relative;
+ z-index: 2;
+ pointer-events: none;
+}
+.l-clipper__content {
+ pointer-events: none;
+ position: absolute;
+ border: 1rpx solid rgba(255,255,255,0.3);
+ box-sizing: border-box;
+ box-shadow: rgba(0,0,0,0.5) 0 0 0 80vh;
+ background: transparent;
+}
+.l-clipper__content::before,
+.l-clipper__content::after {
+ content: '';
+ position: absolute;
+ border: 1rpx dashed rgba(255,255,255,0.3);
+}
+.l-clipper__content::before {
+ width: 100%;
+ top: 33.33%;
+ height: 33.33%;
+ border-left: none;
+ border-right: none;
+}
+.l-clipper__content::after {
+ width: 33.33%;
+ left: 33.33%;
+ height: 100%;
+ border-top: none;
+ border-bottom: none;
+}
+.l-clipper__edge {
+ position: absolute;
+ width: 34rpx;
+ height: 34rpx;
+ border: 6rpx solid #fff;
+ pointer-events: auto;
+}
+.l-clipper__edge::before {
+ content: '';
+ position: absolute;
+ width: 40rpx;
+ height: 40rpx;
+ background-color: transparent;
+}
+.l-clipper__edge:nth-child(1) {
+ left: -6rpx;
+ top: -6rpx;
+ border-bottom-width: 0 !important;
+ border-right-width: 0 !important;
+}
+.l-clipper__edge:nth-child(1):before {
+ top: -50%;
+ left: -50%;
+}
+.l-clipper__edge:nth-child(2) {
+ right: -6rpx;
+ top: -6rpx;
+ border-bottom-width: 0 !important;
+ border-left-width: 0 !important;
+}
+.l-clipper__edge:nth-child(2):before {
+ top: -50%;
+ left: 50%;
+}
+.l-clipper__edge:nth-child(3) {
+ left: -6rpx;
+ bottom: -6rpx;
+ border-top-width: 0 !important;
+ border-right-width: 0 !important;
+}
+.l-clipper__edge:nth-child(3):before {
+ bottom: -50%;
+ left: -50%;
+}
+.l-clipper__edge:nth-child(4) {
+ right: -6rpx;
+ bottom: -6rpx;
+ border-top-width: 0 !important;
+ border-left-width: 0 !important;
+}
+.l-clipper__edge:nth-child(4):before {
+ bottom: -50%;
+ left: 50%;
+}
+.l-clipper-image {
+ width: 100%;
+ border-style: none;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ transform-origin: center;
+}
+.l-clipper-canvas {
+ position: fixed;
+ z-index: 10;
+ left: -200vw;
+ top: -200vw;
+ pointer-events: none;
+}
+.l-clipper-tools {
+ position: fixed;
+ left: 0;
+ bottom: 10px;
+ width: 100%;
+ z-index: 99;
+ color: #fff;
+}
+.l-clipper-tools__btns {
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ padding: 20rpx 40rpx;
+ box-sizing: border-box;
+}
+.l-clipper-tools__btns .cancel {
+ width: 112rpx;
+ height: 60rpx;
+ text-align: center;
+ line-height: 60rpx;
+}
+.l-clipper-tools__btns .confirm {
+ width: 112rpx;
+ height: 60rpx;
+ line-height: 60rpx;
+ background-color: #07c160;
+ border-radius: 6rpx;
+ text-align: center;
+}
+.l-clipper-tools__btns image {
+ display: block;
+ width: 60rpx;
+ height: 60rpx;
+}
+.l-clipper-tools__btns {
+ flex-direction: row;
+}
diff --git a/pages2/setting/limeClipper/limeClipper.vue b/pages2/setting/limeClipper/limeClipper.vue
new file mode 100644
index 0000000..96cccf9
--- /dev/null
+++ b/pages2/setting/limeClipper/limeClipper.vue
@@ -0,0 +1,816 @@
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+
+
+
+
+
+
+
+
+
+
+ 确定
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages2/setting/limeClipper/utils.js b/pages2/setting/limeClipper/utils.js
new file mode 100644
index 0000000..980c439
--- /dev/null
+++ b/pages2/setting/limeClipper/utils.js
@@ -0,0 +1,244 @@
+/**
+ * 判断手指触摸位置
+ */
+export function determineDirection(clipX, clipY, clipWidth, clipHeight, currentX, currentY) {
+ /*
+ * (右下>>1 右上>>2 左上>>3 左下>>4)
+ */
+ let corner;
+ /**
+ * 思路:(利用直角坐标系)
+ * 1.找出裁剪框中心点
+ * 2.如点击坐标在上方点与左方点区域内,则点击为左上角
+ * 3.如点击坐标在下方点与右方点区域内,则点击为右下角
+ * 4.其他角同理
+ */
+ const mainPoint = [clipX + clipWidth / 2, clipY + clipHeight / 2]; // 中心点
+ const currentPoint = [currentX, currentY]; // 触摸点
+
+ if (currentPoint[0] <= mainPoint[0] && currentPoint[1] <= mainPoint[1]) {
+ corner = 3; // 左上
+ } else if (currentPoint[0] >= mainPoint[0] && currentPoint[1] <= mainPoint[1]) {
+ corner = 2; // 右上
+ } else if (currentPoint[0] <= mainPoint[0] && currentPoint[1] >= mainPoint[1]) {
+ corner = 4; // 左下
+ } else if (currentPoint[0] >= mainPoint[0] && currentPoint[1] >= mainPoint[1]) {
+ corner = 1; // 右下
+ }
+
+ return corner;
+}
+
+/**
+ * 图片边缘检测检测时,计算图片偏移量
+ */
+export function calcImageOffset(data, scale) {
+ let left = data.imageLeft;
+ let top = data.imageTop;
+ scale = scale || data.scale;
+
+ let imageWidth = data.imageWidth;
+ let imageHeight = data.imageHeight;
+ if ((data.angle / 90) % 2) {
+ imageWidth = data.imageHeight;
+ imageHeight = data.imageWidth;
+ }
+ const {
+ clipX,
+ clipWidth,
+ clipY,
+ clipHeight
+ } = data;
+
+ // 当前图片宽度/高度
+ const currentImageSize = (size) => (size * scale) / 2;
+ const currentImageWidth = currentImageSize(imageWidth);
+ const currentImageHeight = currentImageSize(imageHeight);
+
+ left = clipX + currentImageWidth >= left ? left : clipX + currentImageWidth;
+ left = clipX + clipWidth - currentImageWidth <= left ? left : clipX + clipWidth - currentImageWidth;
+ top = clipY + currentImageHeight >= top ? top : clipY + currentImageHeight;
+ top = clipY + clipHeight - currentImageHeight <= top ? top : clipY + clipHeight - currentImageHeight;
+ return {
+ left,
+ top,
+ scale
+ };
+}
+
+/**
+ * 图片边缘检测时,计算图片缩放比例
+ */
+export function calcImageScale(data, scale) {
+ scale = scale || data.scale;
+ let {
+ imageWidth,
+ imageHeight,
+ clipWidth,
+ clipHeight,
+ angle
+ } = data
+ if ((angle / 90) % 2) {
+ imageWidth = imageHeight;
+ imageHeight = imageWidth;
+ }
+ if (imageWidth * scale < clipWidth) {
+ scale = clipWidth / imageWidth;
+ }
+ if (imageHeight * scale < clipHeight) {
+ scale = Math.max(scale, clipHeight / imageHeight);
+ }
+ return scale;
+}
+
+/**
+ * 计算图片尺寸
+ */
+export function calcImageSize(width, height, data) {
+ let imageWidth = width,
+ imageHeight = height;
+ let {
+ clipWidth,
+ clipHeight,
+ sysinfo,
+ width: originWidth,
+ height: originHeight
+ } = data
+ if (imageWidth && imageHeight) {
+ if (imageWidth / imageHeight > (clipWidth || originWidth) / (clipWidth || originHeight)) {
+ imageHeight = clipHeight || originHeight;
+ imageWidth = (width / height) * imageHeight;
+ } else {
+ imageWidth = clipWidth || originWidth;
+ imageHeight = (height / width) * imageWidth;
+ }
+ } else {
+ let sys = sysinfo || uni.getSystemInfoSync();
+ imageWidth = sys.windowWidth;
+ imageHeight = 0;
+ }
+ return {
+ imageWidth,
+ imageHeight
+ };
+}
+
+/**
+ * 勾股定理求斜边
+ */
+export function calcPythagoreanTheorem(width, height) {
+ return Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+}
+
+/**
+ * 拖动裁剪框时计算
+ */
+export function clipTouchMoveOfCalculate(data, event) {
+ const clientX = event.touches[0].clientX;
+ const clientY = event.touches[0].clientY;
+
+ let {
+ clipWidth,
+ clipHeight,
+ clipY: oldClipY,
+ clipX: oldClipX,
+ clipStart,
+ isLockRatio,
+ maxWidth,
+ minWidth,
+ maxHeight,
+ minHeight
+ } = data;
+ maxWidth = maxWidth / 2;
+ minWidth = minWidth / 2;
+ minHeight = minHeight / 2;
+ maxHeight = maxHeight / 2;
+
+ let width = clipWidth,
+ height = clipHeight,
+ clipY = oldClipY,
+ clipX = oldClipX,
+ // 获取裁剪框实际宽度/高度
+ // 如果大于最大值则使用最大值
+ // 如果小于最小值则使用最小值
+ sizecorrect = () => {
+ width = width <= maxWidth ? (width >= minWidth ? width : minWidth) : maxWidth;
+ height = height <= maxHeight ? (height >= minHeight ? height : minHeight) : maxHeight;
+ },
+ sizeinspect = () => {
+ sizecorrect();
+ if ((width > maxWidth || width < minWidth || height > maxHeight || height < minHeight) && isLockRatio) {
+ return false;
+ } else {
+ return true;
+ }
+ };
+ //if (clipStart.corner) {
+ height = clipStart.height + (clipStart.corner > 1 && clipStart.corner < 4 ? 1 : -1) * (clipStart.y - clientY);
+ //}
+ switch (clipStart.corner) {
+ case 1:
+ width = clipStart.width - clipStart.x + clientX;
+ if (isLockRatio) {
+ height = width / (clipWidth / clipHeight);
+ }
+ if (!sizeinspect()) return;
+ break;
+ case 2:
+ width = clipStart.width - clipStart.x + clientX;
+ if (isLockRatio) {
+ height = width / (clipWidth / clipHeight);
+ }
+ if (!sizeinspect()) {
+ return;
+ } else {
+ clipY = clipStart.clipY - (height - clipStart.height);
+ }
+
+ break;
+ case 3:
+ width = clipStart.width + clipStart.x - clientX;
+ if (isLockRatio) {
+ height = width / (clipWidth / clipHeight);
+ }
+ if (!sizeinspect()) {
+ return;
+ } else {
+ clipY = clipStart.clipY - (height - clipStart.height);
+ clipX = clipStart.clipX - (width - clipStart.width);
+ }
+
+ break;
+ case 4:
+ width = clipStart.width + clipStart.x - clientX;
+ if (isLockRatio) {
+ height = width / (clipWidth / clipHeight);
+ }
+ if (!sizeinspect()) {
+ return;
+ } else {
+ clipX = clipStart.clipX - (width - clipStart.width);
+ }
+ break;
+ default:
+ break;
+ }
+ return {
+ width,
+ height,
+ clipX,
+ clipY
+ };
+}
+
+/**
+ * 单指拖动图片计算偏移
+ */
+export function imageTouchMoveOfCalcOffset(data, clientXForLeft, clientYForLeft) {
+ let left = clientXForLeft - data.touchRelative[0].x,
+ top = clientYForLeft - data.touchRelative[0].y;
+ return {
+ left,
+ top
+ };
+}
diff --git a/pages2/setting/setting.vue b/pages2/setting/setting.vue
new file mode 100644
index 0000000..f75ef82
--- /dev/null
+++ b/pages2/setting/setting.vue
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+ 请输入昵称
+
+
+
+ 男
+ 女
+ 保密
+
+ 立即提交
+
+
+
+
+
+
+
+
+
diff --git a/pages2/withdraw/withdraw.vue b/pages2/withdraw/withdraw.vue
new file mode 100644
index 0000000..69bc934
--- /dev/null
+++ b/pages2/withdraw/withdraw.vue
@@ -0,0 +1,343 @@
+
+
+
+
+ 到账渠道
+
+
+
+ 微信零钱
+
+ 仅支持整数,72小时内到账
+
+
+
+ 提现金额
+
+ ¥
+
+
+
+
+ 输入金额超过可提现余额,账户余额{{ pool }}元
+
+
+ 最低{{ lowest }}元起提现,账户余额{{ pool }}元
+
+
+ 当前可提现余额{{ pool }}元,
+ 全部提现
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/center/withdraw.png b/static/center/withdraw.png
new file mode 100644
index 0000000..3b3529a
Binary files /dev/null and b/static/center/withdraw.png differ
diff --git a/static/del.png b/static/del.png
new file mode 100644
index 0000000..a05fdeb
Binary files /dev/null and b/static/del.png differ
diff --git a/static/money.png b/static/money.png
new file mode 100644
index 0000000..4d8a887
Binary files /dev/null and b/static/money.png differ
diff --git a/uniCloud-alipay/cloudfunctions/gift_info/index.obj.js b/uniCloud-alipay/cloudfunctions/gift_info/index.obj.js
new file mode 100644
index 0000000..03fc4ac
--- /dev/null
+++ b/uniCloud-alipay/cloudfunctions/gift_info/index.obj.js
@@ -0,0 +1,24 @@
+const db = uniCloud.database();
+const _ = db.command;
+module.exports = {
+ _before: function () { // 通用预处理器
+
+ },
+ async getGiftList() {
+ try {
+ const res = await db.collection("gifts").get();
+ console.log(res.data);
+ return {
+ code: 200,
+ data: res.data
+ }
+ } catch(e) {
+ console.log(e.message);
+ return {
+ code: 500,
+ msg: e.message
+ }
+ }
+ },
+
+}
diff --git a/uniCloud-alipay/cloudfunctions/gift_info/package.json b/uniCloud-alipay/cloudfunctions/gift_info/package.json
new file mode 100644
index 0000000..1881fce
--- /dev/null
+++ b/uniCloud-alipay/cloudfunctions/gift_info/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gift_info",
+ "dependencies": {},
+ "extensions": {
+ "uni-cloud-jql": {}
+ }
+}
\ No newline at end of file
diff --git a/uniCloud-alipay/cloudfunctions/user-info/index.obj.js b/uniCloud-alipay/cloudfunctions/user-info/index.obj.js
new file mode 100644
index 0000000..4c46b01
--- /dev/null
+++ b/uniCloud-alipay/cloudfunctions/user-info/index.obj.js
@@ -0,0 +1,185 @@
+const db = uniCloud.database();
+const _ = db.command;
+
+let obj = {
+ isValidIP(ip) {
+ // ------------------------- IPv4 验证 -------------------------
+ if (ip.includes('.')) {
+ const ipv4Regex = /^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/;
+ return ipv4Regex.test(ip); // 直接通过正则匹配[1,5](@ref)
+ }
+
+ // ------------------------- IPv6 验证 -------------------------
+ if (ip.includes(':')) {
+ const parts = ip.split(':');
+ // 处理压缩的::符号(如::1或2001:db8::1)
+ const hasDoubleColon = ip.includes('::');
+ if (hasDoubleColon && ip.indexOf('::') !== ip.lastIndexOf('::')) return false; // 禁止多个::[6](@ref)
+
+ // 分割后的段数应在1到8之间(允许压缩)
+ if (parts.length < 3 || parts.length > 8) return false;
+
+ // 展开压缩段(如将::替换为填充段)
+ let expandedParts = [];
+ let fillZeros = 8 - parts.filter(p => p !== '').length;
+ for (let part of parts) {
+ if (part === '') {
+ while (fillZeros-- > 0) expandedParts.push('0');
+ } else {
+ expandedParts.push(part);
+ }
+ }
+ if (expandedParts.length !== 8) return false;
+
+ // 验证每段是否为1-4位十六进制字符
+ const hexRegex = /^[0-9a-fA-F]{1,4}$/;
+ return expandedParts.every(p => hexRegex.test(p)); // 每段必须符合规则[6,7](@ref)
+ }
+
+ return false;
+ },
+ isReservedOrLocalIP(ip) {
+ // ------------------------- IPv4 处理逻辑 -------------------------
+ if (ip.includes('.')) {
+ const parts = ip.split('.').map(Number);
+ // 格式验证
+ if (parts.length !== 4 || parts.some(n => n < 0 || n > 255)) return false;
+
+ // 1. 局域网地址(私有地址)
+ if (
+ parts[0] === 10 || // 10.0.0.0/8 [1,2,4](@ref)
+ (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) || // 172.16.0.0/12 [1,2,4](@ref)
+ (parts[0] === 192 && parts[1] === 168) // 192.168.0.0/16 [1,2,4](@ref)
+ ) return true;
+
+ // 2. 保留地址
+ return (
+ parts[0] === 127 || // 127.0.0.0/8(环回地址)[1,4](@ref)
+ (parts[0] === 169 && parts[1] === 254) || // 169.254.0.0/16(链路本地地址)[4,5](@ref)
+ (parts[0] >= 224 && parts[0] <= 239) || // 224.0.0.0/4(多播地址)[3,5](@ref)
+ ip === '0.0.0.0' || // 未指定地址 [1](@ref)
+ ip === '255.255.255.255' // 广播地址 [1](@ref)
+ );
+ }
+
+ // ------------------------- IPv6 处理逻辑 -------------------------
+ if (ip.includes(':')) {
+ // 规范化IPv6(展开缩写)
+ const normalized = ip.replace(/(^:|:$)/g, '::').replace(/::/g, ':0:').split(':')
+ .map(seg => seg.padStart(4, '0')).join(':').padStart(39, '0:');
+
+ if (normalized.startsWith('fc00:') || normalized.startsWith('fd00:')) return true;
+
+ // 2. 保留地址
+ return (
+ normalized === '0000:0000:0000:0000:0000:0000:0000:0001' ||
+ normalized.startsWith('fe80:') ||
+ normalized.startsWith('ff00:') ||
+ normalized.startsWith('2001:0db8:') ||
+ normalized === '0000:0000:0000:0000:0000:0000:0000:0000'
+ );
+ }
+
+ return false;
+ },
+ async getIPAddress(ip) {
+ if (!obj.isValidIP(ip)) return "未知";
+ if (obj.isReservedOrLocalIP(ip)) return "未知";
+
+ let address = "";
+
+ const res = await uniCloud.collection("ip").where({
+ ip: ip
+ })
+ .get();
+
+ console.log(res);
+
+ if (res.data.length > 0) {
+ const res = await uniCloud.collection("ip").where({
+ ip: ip
+ })
+ .field({
+ ip:true,
+ country: true,
+ economize: true,
+ market: true,
+ })
+ .get();
+ if (res.data[0].market === "") address = res.data[0].country + " " + res.data[0].economize;
+ else {
+ address = res.data[0].economize + " " + res.data[0].market;
+ }
+ return address;
+ }
+
+ let url= "https://62cccca0.api.cn/ipdata?token=7cec107b2f759a84211c74d9d9d6b4c4&datatype=json&ip=" + ip;
+ const response = await uniCloud.httpclient.request(url, {
+ method: 'GET',
+ timeout: 1000
+ });
+ console.log(response);
+ if (response.status === 200) {
+ await uniCloud.collection("ip").add({
+ ip: response.data.ip,
+ country: response.data.data[0]==="台湾"?"中国台湾":response.data.data[0],
+ economize: response.data.data[1],
+ market: response.data.data[2],
+ county: response.data.data[3],
+ operator: response.data.data[4],
+ postal_code: response.data.data[5],
+ area_code: response.data.data[6],
+ network: response.data.data[7]
+ });
+ if (response.data.data[2] === "" ) {
+ address = response.data.data[0] + " " + response.data.data[1];
+ }else {
+ address = response.data.data[1] + " " + response.data.data[2];
+ }
+
+ return address;
+ }
+ return address;
+
+ }
+}
+module.exports = {
+ _before: function () { // 通用预处理器
+
+ },
+
+ async get_user_info(query) {
+ try {
+ let uid = query.uid;
+ console.log(uid);
+ if (!uid) throw new Error("uid不存在");
+ console.log(uid);
+ let res = await db.collection("uni-id-users")
+ .doc(uid)
+ .field({
+ _id: true,
+ nickname: true,
+ avatar_file: true,
+ last_login_ip:true,
+ register_date: true,
+ last_login_date:true,
+ personal_profile: true,
+ gender: true
+ })
+ .get();
+ res.data[0].last_login_ip = await obj.getIPAddress(res.data[0].last_login_ip);
+ console.log(res)
+
+ return {
+ code: 200,
+ data: res.data[0]
+ }
+ } catch (e) {
+ console.log(e);
+ return {
+ code: 500,
+ msg: e.message
+ }
+ }
+ }
+}
diff --git a/uniCloud-alipay/cloudfunctions/user-info/package.json b/uniCloud-alipay/cloudfunctions/user-info/package.json
new file mode 100644
index 0000000..3315045
--- /dev/null
+++ b/uniCloud-alipay/cloudfunctions/user-info/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "user-info",
+ "dependencies": {},
+ "extensions": {
+ "uni-cloud-jql": {}
+ }
+}
\ No newline at end of file
diff --git a/uniCloud-alipay/database/gifts.schema.json b/uniCloud-alipay/database/gifts.schema.json
new file mode 100644
index 0000000..c952e73
--- /dev/null
+++ b/uniCloud-alipay/database/gifts.schema.json
@@ -0,0 +1,37 @@
+{
+ "bsonType": "object",
+ "required": ["price"], // 添加 price 为必填字段
+ "permission": {
+ "read": true,
+ "create": "'admin' in auth.role",
+ "update": "'admin' in auth.role",
+ "delete": "'admin' in auth.role"
+ },
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "url": {
+ "bsonType": "string",
+ "title": "资源地址",
+ "description": "带签名时效的静态资源 URL",
+ "trim": "both",
+ "pattern": "^https?://", // 基础 URL 格式校验
+ "errorMessage": {
+ "format": "URL 必须以 http/https 开头"
+ }
+ },
+ "price": {
+ "bsonType": "int",
+ "title": "商品价格",
+ "description": "单位:分(整数类型)",
+ "minimum": 0,
+ "maximum": 100000000,
+ "errorMessage": {
+ "type": "价格必须为整数类型",
+ "minimum": "价格不能为负数",
+ "maximum": "单件商品价格不得超过100万元"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uniCloud-alipay/database/users-give-gift.schema.json b/uniCloud-alipay/database/users-give-gift.schema.json
new file mode 100644
index 0000000..d758733
--- /dev/null
+++ b/uniCloud-alipay/database/users-give-gift.schema.json
@@ -0,0 +1,48 @@
+{
+ "bsonType": "object",
+ "required": ["user_id", "article_id", "months", "create_time"], // 必填字段
+ "permission": {
+ "read": true,
+ "create": "doc._id == auth.uid || 'admin' in auth.role",
+ "update": "doc._id == auth.uid || 'admin' in auth.role",
+ "delete": "doc._id == auth.uid || 'admin' in auth.role"
+ },
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "months": {
+ "bsonType": "int",
+ "title": "累计月数",
+ "defaultValue": 0,
+ "minimum": 0
+ },
+ "user_id": {
+ "bsonType": "string",
+ "title": "用户ID",
+ "foreignKey": "uni-id-users._id",
+ "trim": "both",
+ "errorMessage": "用户ID不能为空"
+ },
+ "article_id": {
+ "bsonType": "string",
+ "title": "文章ID",
+ "trim": "both",
+ "errorMessage": "文章ID不能为空"
+ },
+ "gift_value": {
+ "bsonType": "int",
+ "title": "礼物价值",
+ "minimum": 0,
+ "defaultValue": 0,
+ "errorMessage": "礼物价值不能小于1"
+ },
+ "create_time": {
+ "bsonType": "timestamp",
+ "title": "创建时间",
+ "defaultValue": {
+ "$env": "now" // 自动填充服务器时间[1](@ref)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-notice-bar/changelog.md b/uni_modules/uni-notice-bar/changelog.md
new file mode 100644
index 0000000..ce50674
--- /dev/null
+++ b/uni_modules/uni-notice-bar/changelog.md
@@ -0,0 +1,20 @@
+## 1.2.2(2023-12-20)
+- 修复动态绑定title时,滚动速度不一致的问题
+## 1.2.1(2022-09-05)
+- 新增 属性 fontSize,可修改文字大小。
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-notice-bar](https://uniapp.dcloud.io/component/uniui/uni-notice-bar)
+## 1.1.1(2021-11-09)
+- 新增 提供组件设计资源,组件样式调整
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.9(2021-05-12)
+- 新增 组件示例地址
+## 1.0.8(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.7(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.6(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue b/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
new file mode 100644
index 0000000..47fb9b3
--- /dev/null
+++ b/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
@@ -0,0 +1,431 @@
+
+
+
+
+
+ {{text}}
+
+
+
+ {{ moreText }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-notice-bar/package.json b/uni_modules/uni-notice-bar/package.json
new file mode 100644
index 0000000..1e9762c
--- /dev/null
+++ b/uni_modules/uni-notice-bar/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-notice-bar",
+ "displayName": "uni-notice-bar 通告栏",
+ "version": "1.2.2",
+ "description": "NoticeBar 通告栏组件,常用于展示公告信息,可设为滚动公告",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "通告栏",
+ "公告",
+ "跑马灯"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-notice-bar/readme.md b/uni_modules/uni-notice-bar/readme.md
new file mode 100644
index 0000000..fb2ede2
--- /dev/null
+++ b/uni_modules/uni-notice-bar/readme.md
@@ -0,0 +1,13 @@
+
+
+## NoticeBar 通告栏
+> **组件名:uni-notice-bar**
+> 代码块: `uNoticeBar`
+
+
+通告栏组件 。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-notice-bar)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+
+