Compare View
Commits (5)
-
结构调整
-
打卡模板创建
-
打卡功能简单版
Showing
92 changed files
Show diff stats
app.js
@@ -44,9 +44,10 @@ App({ | @@ -44,9 +44,10 @@ App({ | ||
44 | view.onShareAppMessage = function () { | 44 | view.onShareAppMessage = function () { |
45 | //你的分享配置 | 45 | //你的分享配置 |
46 | return { | 46 | return { |
47 | - title: name + '推荐大家都在用的升学大数据宝典', | 47 | + title: name + '推荐您 一起开始自主学习之旅', |
48 | path: '/pages/index/index', | 48 | path: '/pages/index/index', |
49 | - imageUrl: 'https://proxy.shunzhi.net:51315/mp_share2.jpg', | 49 | + // imageUrl: 'https://proxy.shunzhi.net:51315/mp_share2.jpg', |
50 | + imageUrl: 'https://szyundisk.oss-cn-hangzhou.aliyuncs.com/AdmissionsManageSys/37317060-9e67-41e1-9731-b722c83cff8a.jpg', | ||
50 | }; | 51 | }; |
51 | } | 52 | } |
52 | } | 53 | } |
app.json
1 | { | 1 | { |
2 | "pages": [ | 2 | "pages": [ |
3 | - "pages/index/index", | ||
4 | - "pages/index/rank/rank", | 3 | + "pages/login/loginNew/loginNew", |
4 | + "pages/login/codeLogin/codeLogin", | ||
5 | "pages/index/achievement/achievement", | 5 | "pages/index/achievement/achievement", |
6 | - "pages/index/punchDetail/punchDetail", | 6 | + "pages/index/rank/rank", |
7 | + "pages/index/index", | ||
7 | "pages/index/newPunch/newPunch", | 8 | "pages/index/newPunch/newPunch", |
8 | - "pages/login/codeLogin/codeLogin", | 9 | + "pages/mine/record/record", |
10 | + "pages/mine/index", | ||
11 | + "pages/index/punchDetail/punchDetail", | ||
9 | "pages/login/protocol/protocol", | 12 | "pages/login/protocol/protocol", |
10 | "pages/login/policy/policy", | 13 | "pages/login/policy/policy", |
11 | - "pages/mine/index", | ||
12 | - "pages/mine/record/record", | ||
13 | "pages/webview/webview" | 14 | "pages/webview/webview" |
14 | ], | 15 | ], |
15 | "window": { | 16 | "window": { |
16 | "backgroundTextStyle": "dark", | 17 | "backgroundTextStyle": "dark", |
17 | "navigationBarBackgroundColor": "#fff", | 18 | "navigationBarBackgroundColor": "#fff", |
18 | - "navigationBarTitleText": "计划管家", | 19 | + "navigationBarTitleText": "打卡管理", |
19 | "navigationBarTextStyle": "black" | 20 | "navigationBarTextStyle": "black" |
20 | }, | 21 | }, |
21 | "tabBar": { | 22 | "tabBar": { |
@@ -24,7 +25,7 @@ | @@ -24,7 +25,7 @@ | ||
24 | "borderStyle": "white", | 25 | "borderStyle": "white", |
25 | "list": [ | 26 | "list": [ |
26 | { | 27 | { |
27 | - "pagePath": "pages/index/index", | 28 | + "pagePath": "pages/index/rank/rank", |
28 | "text": "首页", | 29 | "text": "首页", |
29 | "iconPath": "./img/tab_home_normat.png", | 30 | "iconPath": "./img/tab_home_normat.png", |
30 | "selectedIconPath": "./img/tab_home_selected.png" | 31 | "selectedIconPath": "./img/tab_home_selected.png" |
app.wxss
1 | -/* @import "/miniprogram_npm/@vant/weapp/common/index.wxss"; */ | ||
2 | -page{ | 1 | +@import "/miniprogram_npm/@vant/weapp/common/index.wxss"; |
2 | +/* page{ | ||
3 | background: #fff; | 3 | background: #fff; |
4 | -} | 4 | +} */ |
5 | /* 二级页面顶部统一返回按钮,位置可能需要根据机型调整 */ | 5 | /* 二级页面顶部统一返回按钮,位置可能需要根据机型调整 */ |
6 | .navigation_back{ | 6 | .navigation_back{ |
7 | width: 80rpx; | 7 | width: 80rpx; |
@@ -0,0 +1,144 @@ | @@ -0,0 +1,144 @@ | ||
1 | +import { dateUtil, getCalendarConfig } from './utils/index' | ||
2 | + | ||
3 | +/** | ||
4 | + * 计算当前月份前后两月应占的格子 | ||
5 | + * @param {number} year 年份 | ||
6 | + * @param {number} month 月份 | ||
7 | + */ | ||
8 | +function calculateEmptyGrids(year, month, config) { | ||
9 | + const prevMonthGrids = calculatePrevMonthGrids(year, month, config) | ||
10 | + const nextMonthGrids = calculateNextMonthGrids(year, month, config) | ||
11 | + return { | ||
12 | + prevMonthGrids, | ||
13 | + nextMonthGrids | ||
14 | + } | ||
15 | +} | ||
16 | + | ||
17 | +/** | ||
18 | + * 计算上月应占的格子 | ||
19 | + * @param {number} year 年份 | ||
20 | + * @param {number} month 月份 | ||
21 | + */ | ||
22 | +function calculatePrevMonthGrids(year, month, config) { | ||
23 | + let emptyGrids = [] | ||
24 | + const prevMonthDays = dateUtil.getDatesCountOfMonth(year, month - 1) | ||
25 | + let firstDayOfWeek = dateUtil.firstDayOfWeek(year, month) | ||
26 | + if (config.firstDayOfWeek === 'Mon') { | ||
27 | + if (firstDayOfWeek === 0) { | ||
28 | + firstDayOfWeek = 6 | ||
29 | + } else { | ||
30 | + firstDayOfWeek -= 1 | ||
31 | + } | ||
32 | + } | ||
33 | + if (firstDayOfWeek > 0) { | ||
34 | + const len = prevMonthDays - firstDayOfWeek | ||
35 | + const { onlyShowCurrentMonth } = config | ||
36 | + const YMInfo = dateUtil.getPrevMonthInfo({ year, month }) | ||
37 | + for (let i = prevMonthDays; i > len; i--) { | ||
38 | + if (onlyShowCurrentMonth) { | ||
39 | + emptyGrids.push('') | ||
40 | + } else { | ||
41 | + const week = dateUtil.getDayOfWeek(+year, +month, i) | ||
42 | + emptyGrids.push({ | ||
43 | + ...YMInfo, | ||
44 | + date: i, | ||
45 | + week | ||
46 | + }) | ||
47 | + } | ||
48 | + } | ||
49 | + emptyGrids.reverse() | ||
50 | + } | ||
51 | + return emptyGrids | ||
52 | +} | ||
53 | +/** | ||
54 | + * 计算下一月日期是否需要多展示的日期 | ||
55 | + * 某些月份日期为5排,某些月份6排,统一为6排 | ||
56 | + * @param {number} year | ||
57 | + * @param {number} month | ||
58 | + * @param {object} config | ||
59 | + */ | ||
60 | +function calculateExtraEmptyDate(year, month, config) { | ||
61 | + let extDate = 0 | ||
62 | + if (+month === 2) { | ||
63 | + extDate += 7 | ||
64 | + let firstDayofMonth = dateUtil.getDayOfWeek(year, month, 1) | ||
65 | + if (config.firstDayOfWeek === 'Mon') { | ||
66 | + if (+firstDayofMonth === 1) extDate += 7 | ||
67 | + } else { | ||
68 | + if (+firstDayofMonth === 0) extDate += 7 | ||
69 | + } | ||
70 | + } else { | ||
71 | + let firstDayofMonth = dateUtil.getDayOfWeek(year, month, 1) | ||
72 | + if (config.firstDayOfWeek === 'Mon') { | ||
73 | + if (firstDayofMonth !== 0 && firstDayofMonth < 6) { | ||
74 | + extDate += 7 | ||
75 | + } | ||
76 | + } else { | ||
77 | + if (firstDayofMonth <= 5) { | ||
78 | + extDate += 7 | ||
79 | + } | ||
80 | + } | ||
81 | + } | ||
82 | + return extDate | ||
83 | +} | ||
84 | +/** | ||
85 | + * 计算下月应占的格子 | ||
86 | + * @param {number} year 年份 | ||
87 | + * @param {number} month 月份 | ||
88 | + */ | ||
89 | +function calculateNextMonthGrids(year, month, config) { | ||
90 | + let emptyGrids = [] | ||
91 | + const datesCount = dateUtil.getDatesCountOfMonth(year, month) | ||
92 | + let lastDayWeek = dateUtil.getDayOfWeek(year, month, datesCount) | ||
93 | + if (config.firstDayOfWeek === 'Mon') { | ||
94 | + if (lastDayWeek === 0) { | ||
95 | + lastDayWeek = 6 | ||
96 | + } else { | ||
97 | + lastDayWeek -= 1 | ||
98 | + } | ||
99 | + } | ||
100 | + let len = 7 - (lastDayWeek + 1) | ||
101 | + const { onlyShowCurrentMonth } = config | ||
102 | + if (!onlyShowCurrentMonth) { | ||
103 | + len = len + calculateExtraEmptyDate(year, month, config) | ||
104 | + } | ||
105 | + const YMInfo = dateUtil.getNextMonthInfo({ year, month }) | ||
106 | + for (let i = 1; i <= len; i++) { | ||
107 | + const week = dateUtil.getDayOfWeek(+year, +month, i) | ||
108 | + if (onlyShowCurrentMonth) { | ||
109 | + emptyGrids.push('') | ||
110 | + } else { | ||
111 | + emptyGrids.push({ | ||
112 | + id: i - 1, | ||
113 | + ...YMInfo, | ||
114 | + date: i, | ||
115 | + week: week || 7 | ||
116 | + }) | ||
117 | + } | ||
118 | + } | ||
119 | + return emptyGrids | ||
120 | +} | ||
121 | +/** | ||
122 | + * 设置日历面板数据 | ||
123 | + * @param {number} year 年份 | ||
124 | + * @param {number} month 月份 | ||
125 | + * @param {number} curDate 日期 | ||
126 | + */ | ||
127 | +function calculateCurrentMonthDates(year, month) { | ||
128 | + return dateUtil.calcDates(year, month) | ||
129 | +} | ||
130 | + | ||
131 | +export function calcJumpData({ dateInfo, config, component }) { | ||
132 | + dateInfo = dateInfo || dateUtil.todayFMD() | ||
133 | + const { year, month, date } = dateInfo | ||
134 | + const calendarConfig = config || getCalendarConfig(component) | ||
135 | + const emptyGrids = calculateEmptyGrids(year, month, calendarConfig) | ||
136 | + const calendar = { | ||
137 | + curYear: year, | ||
138 | + curMonth: month, | ||
139 | + curDate: date, | ||
140 | + dates: calculateCurrentMonthDates(year, month), | ||
141 | + ...emptyGrids | ||
142 | + } | ||
143 | + return calendar | ||
144 | +} |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +import { dateUtil } from './utils/index' | ||
2 | + | ||
3 | +export function calcTargetYMInfo() { | ||
4 | + return { | ||
5 | + right: dateUtil.getPrevMonthInfo, | ||
6 | + left: dateUtil.getNextMonthInfo, | ||
7 | + prev_month: dateUtil.getPrevMonthInfo, | ||
8 | + next_month: dateUtil.getNextMonthInfo, | ||
9 | + prev_year: dateUtil.getPrevYearInfo, | ||
10 | + next_year: dateUtil.getNextYearInfo | ||
11 | + } | ||
12 | +} |
@@ -0,0 +1,257 @@ | @@ -0,0 +1,257 @@ | ||
1 | +import plugins from './plugins/index' | ||
2 | +import { calcJumpData } from './core' | ||
3 | +import { renderCalendar } from './render' | ||
4 | +import { calcTargetYMInfo } from './helper' | ||
5 | +import { dateUtil, calendarGesture, logger } from './utils/index' | ||
6 | + | ||
7 | +Component({ | ||
8 | + options: { | ||
9 | + styleIsolation: 'apply-shared', | ||
10 | + multipleSlots: true // 在组件定义时的选项中启用多slot支持 | ||
11 | + }, | ||
12 | + properties: { | ||
13 | + config: { | ||
14 | + type: Object, | ||
15 | + value: {} | ||
16 | + } | ||
17 | + }, | ||
18 | + lifetimes: { | ||
19 | + attached: function() { | ||
20 | + this.initComp() | ||
21 | + } | ||
22 | + }, | ||
23 | + methods: { | ||
24 | + initComp() { | ||
25 | + const calendarConfig = this.setDefaultDisableDate() | ||
26 | + this.setConfig(calendarConfig) | ||
27 | + }, | ||
28 | + // 禁用某天日期配置默认为今天 | ||
29 | + setDefaultDisableDate() { | ||
30 | + const calendarConfig = this.properties.config || {} | ||
31 | + if (calendarConfig.disableMode && !calendarConfig.disableMode.date) { | ||
32 | + calendarConfig.disableMode.date = dateUtil.toTimeStr( | ||
33 | + dateUtil.todayFMD() | ||
34 | + ) | ||
35 | + } | ||
36 | + return calendarConfig | ||
37 | + }, | ||
38 | + initCalendar(config) { | ||
39 | + const { defaultDate } = config | ||
40 | + let date = dateUtil.todayFMD() | ||
41 | + if (defaultDate && typeof defaultDate === 'string') { | ||
42 | + const dateInfo = defaultDate.split('-') | ||
43 | + if (dateInfo.length < 3) { | ||
44 | + return logger.warn('defaultDate配置格式应为: 2018-4-2 或 2018-04-02') | ||
45 | + } else { | ||
46 | + date = { | ||
47 | + year: +dateInfo[0], | ||
48 | + month: +dateInfo[1], | ||
49 | + date: +dateInfo[2] | ||
50 | + } | ||
51 | + } | ||
52 | + } | ||
53 | + const waitRenderData = calcJumpData({ | ||
54 | + dateInfo: date, | ||
55 | + config | ||
56 | + }) | ||
57 | + const timestamp = dateUtil.todayTimestamp() | ||
58 | + if (config.autoChoosedWhenJump) { | ||
59 | + const target = waitRenderData.dates.filter( | ||
60 | + item => dateUtil.toTimeStr(item) === dateUtil.toTimeStr(date) | ||
61 | + ) | ||
62 | + if (target && target.length) { | ||
63 | + if (!waitRenderData.selectedDates) { | ||
64 | + waitRenderData.selectedDates = target | ||
65 | + } else { | ||
66 | + waitRenderData.selectedDates.push(target[0]) | ||
67 | + } | ||
68 | + } | ||
69 | + } | ||
70 | + return { | ||
71 | + ...waitRenderData, | ||
72 | + todayTimestamp: timestamp, | ||
73 | + weeksCh: dateUtil.getWeekHeader(config.firstDayOfWeek) | ||
74 | + } | ||
75 | + }, | ||
76 | + setConfig(config) { | ||
77 | + if (config.markToday && typeof config.markToday === 'string') { | ||
78 | + config.highlightToday = true | ||
79 | + } | ||
80 | + config.theme = config.theme || 'default' | ||
81 | + this.setData( | ||
82 | + { | ||
83 | + config | ||
84 | + }, | ||
85 | + () => { | ||
86 | + for (let plugin of plugins.installed) { | ||
87 | + const [, p] = plugin | ||
88 | + if (typeof p.install === 'function') { | ||
89 | + p.install(this) | ||
90 | + } | ||
91 | + if (typeof p.methods === 'function') { | ||
92 | + const methods = p.methods(this) | ||
93 | + for (let fnName in methods) { | ||
94 | + if (fnName.startsWith('__')) continue | ||
95 | + const fn = methods[fnName] | ||
96 | + if (typeof fn === 'function') { | ||
97 | + if (!this.calendar) this.calendar = {} | ||
98 | + this.calendar[fnName] = fn | ||
99 | + } | ||
100 | + } | ||
101 | + } | ||
102 | + } | ||
103 | + const initData = this.initCalendar(config) | ||
104 | + renderCalendar.call(this, initData, config) | ||
105 | + } | ||
106 | + ) | ||
107 | + }, | ||
108 | + tapDate(e) { | ||
109 | + const { info } = e.currentTarget.dataset | ||
110 | + const { date, disable } = info || {} | ||
111 | + if (disable || !date) return | ||
112 | + const { calendar, config } = this.data | ||
113 | + let calendarData = calendar | ||
114 | + let calendarConfig = config | ||
115 | + if (config.takeoverTap) { | ||
116 | + return this.triggerEvent('takeoverTap', info) | ||
117 | + } | ||
118 | + for (let plugin of plugins.installed) { | ||
119 | + const [, p] = plugin | ||
120 | + if (typeof p.onTapDate === 'function') { | ||
121 | + const { | ||
122 | + calendarData: __calendarData, | ||
123 | + calendarConfig: __calendarConfig | ||
124 | + } = p.onTapDate(info, calendarData, calendarConfig) | ||
125 | + calendarData = __calendarData | ||
126 | + calendarConfig = __calendarConfig | ||
127 | + } | ||
128 | + } | ||
129 | + renderCalendar.call(this, calendarData, calendarConfig).then(() => { | ||
130 | + this.triggerEvent('afterTapDate', info) | ||
131 | + }) | ||
132 | + }, | ||
133 | + /** | ||
134 | + * 日历滑动开始 | ||
135 | + * @param {object} e | ||
136 | + */ | ||
137 | + calendarTouchstart(e) { | ||
138 | + const t = e.touches[0] | ||
139 | + const startX = t.clientX | ||
140 | + const startY = t.clientY | ||
141 | + this.swipeLock = true | ||
142 | + this.setData({ | ||
143 | + 'gesture.startX': startX, | ||
144 | + 'gesture.startY': startY | ||
145 | + }) | ||
146 | + }, | ||
147 | + /** | ||
148 | + * 日历滑动中 | ||
149 | + * @param {object} e | ||
150 | + */ | ||
151 | + calendarTouchmove(e) { | ||
152 | + const { gesture } = this.data | ||
153 | + const { preventSwipe } = this.properties.config | ||
154 | + if (!this.swipeLock || preventSwipe) return | ||
155 | + if (calendarGesture.isLeft(gesture, e.touches[0])) { | ||
156 | + this.handleSwipe('left') | ||
157 | + this.swipeLock = false | ||
158 | + } | ||
159 | + if (calendarGesture.isRight(gesture, e.touches[0])) { | ||
160 | + this.handleSwipe('right') | ||
161 | + this.swipeLock = false | ||
162 | + } | ||
163 | + }, | ||
164 | + calendarTouchend(e) { | ||
165 | + this.setData({ | ||
166 | + 'calendar.leftSwipe': 0, | ||
167 | + 'calendar.rightSwipe': 0 | ||
168 | + }) | ||
169 | + }, | ||
170 | + handleSwipe(direction) { | ||
171 | + let swipeKey = 'calendar.leftSwipe' | ||
172 | + if (direction === 'right') { | ||
173 | + swipeKey = 'calendar.rightSwipe' | ||
174 | + } | ||
175 | + this.setData({ | ||
176 | + [swipeKey]: 1 | ||
177 | + }) | ||
178 | + const { calendar } = this.data | ||
179 | + let calendarData = calendar | ||
180 | + const { curYear, curMonth } = calendarData | ||
181 | + const getMonthInfo = calcTargetYMInfo()[direction] | ||
182 | + const target = getMonthInfo({ | ||
183 | + year: +curYear, | ||
184 | + month: +curMonth | ||
185 | + }) | ||
186 | + target.direction = direction | ||
187 | + this.renderCalendar(target) | ||
188 | + }, | ||
189 | + changeDate(e) { | ||
190 | + const { type } = e.currentTarget.dataset | ||
191 | + const { calendar: calendarData } = this.data | ||
192 | + const { curYear, curMonth } = calendarData | ||
193 | + const getMonthInfo = calcTargetYMInfo()[type] | ||
194 | + const target = getMonthInfo({ | ||
195 | + year: +curYear, | ||
196 | + month: +curMonth | ||
197 | + }) | ||
198 | + target.direction = type | ||
199 | + this.renderCalendar(target) | ||
200 | + }, | ||
201 | + renderCalendar(target) { | ||
202 | + let { calendar: calendarData, config } = this.data | ||
203 | + const { curYear, curMonth } = calendarData || {} | ||
204 | + for (let plugin of plugins.installed) { | ||
205 | + const [, p] = plugin | ||
206 | + if (typeof p.onSwitchCalendar === 'function') { | ||
207 | + calendarData = p.onSwitchCalendar(target, calendarData, this) | ||
208 | + } | ||
209 | + } | ||
210 | + return renderCalendar.call(this, calendarData, config).then(() => { | ||
211 | + let triggerEventName = 'whenChangeMonth' | ||
212 | + if (config.weekMode) { | ||
213 | + triggerEventName = 'whenChangeWeek' | ||
214 | + } | ||
215 | + this.triggerEvent(triggerEventName, { | ||
216 | + current: { | ||
217 | + year: +curYear, | ||
218 | + month: +curMonth | ||
219 | + }, | ||
220 | + next: target | ||
221 | + }) | ||
222 | + this.triggerEvent('onSwipe', { | ||
223 | + current: { | ||
224 | + year: +curYear, | ||
225 | + month: +curMonth | ||
226 | + }, | ||
227 | + next: target, | ||
228 | + type: triggerEventName | ||
229 | + }) | ||
230 | + }) | ||
231 | + }, | ||
232 | + doubleClickJumpToToday() { | ||
233 | + const { multi, weekMode } = this.calendar.getCalendarConfig() || {} | ||
234 | + if (multi || weekMode) return | ||
235 | + if (this.count === undefined) { | ||
236 | + this.count = 1 | ||
237 | + } else { | ||
238 | + this.count += 1 | ||
239 | + } | ||
240 | + if (this.lastClick) { | ||
241 | + const difference = new Date().getTime() - this.lastClick | ||
242 | + if ( | ||
243 | + difference < 500 && | ||
244 | + this.count >= 2 && | ||
245 | + typeof this.calendar.jump === 'function' | ||
246 | + ) { | ||
247 | + const today = dateUtil.todayFMD() | ||
248 | + this.calendar.jump(today) | ||
249 | + } | ||
250 | + this.count = undefined | ||
251 | + this.lastClick = undefined | ||
252 | + } else { | ||
253 | + this.lastClick = new Date().getTime() | ||
254 | + } | ||
255 | + } | ||
256 | + } | ||
257 | +}) |
@@ -0,0 +1,60 @@ | @@ -0,0 +1,60 @@ | ||
1 | +<view class="flex b tb ac" wx:if="{{calendar}}"> | ||
2 | + <view class="calendar b tb"> | ||
3 | + <!-- 头部操作栏 --> | ||
4 | + <view | ||
5 | + wx:if="{{!config.hideHeader}}" | ||
6 | + class="handle {{config.theme}}_handle-color fs28 b lr ac pc"> | ||
7 | + <view class="prev fs36" wx:if="{{!config.weekMode}}"> | ||
8 | + <text class="prev-handle iconfont icon-doubleleft" bindtap="changeDate" data-type="prev_year"></text> | ||
9 | + <text class="prev-handle iconfont icon-left" bindtap="changeDate" data-type="prev_month"></text> | ||
10 | + </view> | ||
11 | + <view class="flex date-in-handle b lr cc" bindtap="doubleClickJumpToToday">{{calendar.curYear || "--"}} 年 {{calendar.curMonth || "--"}} 月</view> | ||
12 | + <view class="next fs36" wx:if="{{!config.weekMode}}"> | ||
13 | + <text class="next-handle iconfont icon-right" bindtap="changeDate" data-type="next_month"></text> | ||
14 | + <text class="next-handle iconfont icon-doubleright" bindtap="changeDate" data-type="next_year"></text> | ||
15 | + </view> | ||
16 | + </view> | ||
17 | + <!-- 星期栏 --> | ||
18 | + <view class="weeks b lr ac {{config.theme}}_week-color"> | ||
19 | + <view class="week fs28" wx:for="{{calendar.weeksCh}}" wx:key="index" data-idx="{{index}}">{{item}}</view> | ||
20 | + </view> | ||
21 | + <!-- 日历面板主体 --> | ||
22 | + <view class="b lr wrap" bindtouchstart="calendarTouchstart" catchtouchmove="calendarTouchmove" catchtouchend="calendarTouchend"> | ||
23 | + <!-- 上月日期格子 --> | ||
24 | + <view class="grid b ac pc {{config.theme}}_prev-month-date" wx:for="{{calendar.prevMonthGrids}}" wx:key="index" data-idx="{{index}}"> | ||
25 | + <view class="date-wrap b cc"> | ||
26 | + <view class="date"> | ||
27 | + {{item.date}} | ||
28 | + </view> | ||
29 | + </view> | ||
30 | + </view> | ||
31 | + <!-- 本月日期格子 --> | ||
32 | + <view wx:for="{{calendar.dates}}" wx:key="index" data-idx="{{index}}" data-info="{{item}}" bindtap="tapDate" class="grid {{item.class ? item.class : ''}} {{config.theme}}_normal-date b ac pc"> | ||
33 | + <view class="date-wrap b cc {{config.emphasisWeek && (item.week === 0 || item.week === 6) ? config.theme + '_weekend-color' : ''}}"> | ||
34 | + <view class="date b ac pc {{item.class ? item.class : ''}} {{item.isToday && config.highlightToday ? config.theme + '_today' : ''}} {{item.choosed ? config.theme + '_choosed' : ''}} {{item.disable ? config.theme + '_date-disable' : ''}} {{config.chooseAreaMode ? 'date-area-mode' : ''}} {{calendar.todoLabelCircle && item.showTodoLabel && !item.choosed ? config.theme + '_todo-circle todo-circle' : '' }}"> | ||
35 | + {{config.markToday && item.isToday ? config.markToday : item.date}} | ||
36 | + <view | ||
37 | + wx:if="{{(config.showLunar && item.lunar && !item.showTodoLabel) || (item.showTodoLabel && calendar.todoLabelPos !== 'bottom') || config.showHolidays}}" | ||
38 | + class="date-desc {{config.theme}}_date-desc date-desc-bottom {{(item.choosed || item.isToday) ? 'date-desc-bottom-always' : ''}} {{item.disable ? config.theme + '_date-desc-disable' : ''}}"> | ||
39 | + <text class="{{config.showHolidays && !item.showTodoLabel && item.label && !item.choosed ? config.theme + '_date-desc-lunar' : ''}} {{item.type === 'festival' ? config.theme + '_festival' : ''}}">{{item.label || item.lunar.Term || item.lunar.IDayCn}}</text> | ||
40 | + </view> | ||
41 | + <view | ||
42 | + wx:if="{{item.showTodoLabel && !calendar.todoLabelCircle}}" | ||
43 | + class="{{item.todoText ? 'date-desc' : config.theme + '_todo-dot todo-dot'}} {{config.showLunar ? config.theme + '_date-desc-lunar' : ''}} {{calendar.todoLabelPos === 'bottom' ? 'date-desc-bottom todo-dot-bottom' : 'date-desc-top todo-dot-top'}} {{calendar.showLabelAlways && item.choosed && calendar.todoLabelPos === 'bottom' ? 'date-desc-bottom-always todo-dot-bottom-always' : ''}} {{calendar.showLabelAlways && item.choosed && calendar.todoLabelPos === 'top' ? 'date-desc-top-always todo-dot-top-always' : ''}}" | ||
44 | + style="background-color: {{item.todoText ? '' : item.color || calendar.todoLabelColor}}; color: {{item.color}}"> | ||
45 | + {{item.todoText}} | ||
46 | + </view> | ||
47 | + </view> | ||
48 | + </view> | ||
49 | + </view> | ||
50 | + <!-- 下月日期格子 --> | ||
51 | + <view class="grid b ac pc {{config.theme}}_next-month-date" wx:for="{{calendar.nextMonthGrids}}" wx:key="index" data-idx="{{index}}"> | ||
52 | + <view class="date-wrap b cc"> | ||
53 | + <view class="date"> | ||
54 | + {{item.date}} | ||
55 | + </view> | ||
56 | + </view> | ||
57 | + </view> | ||
58 | + </view> | ||
59 | + </view> | ||
60 | +</view> |
@@ -0,0 +1,214 @@ | @@ -0,0 +1,214 @@ | ||
1 | +@import './theme/iconfont.wxss'; | ||
2 | +@import './theme/theme-default.wxss'; | ||
3 | +@import './theme/theme-elegant.wxss'; | ||
4 | + | ||
5 | +.b { | ||
6 | + display: flex; | ||
7 | +} | ||
8 | + | ||
9 | +.lr { | ||
10 | + flex-direction: row; | ||
11 | +} | ||
12 | + | ||
13 | +.tb { | ||
14 | + flex-direction: column; | ||
15 | +} | ||
16 | + | ||
17 | +.pc { | ||
18 | + justify-content: center; | ||
19 | +} | ||
20 | + | ||
21 | +.ac { | ||
22 | + align-items: center; | ||
23 | +} | ||
24 | + | ||
25 | +.cc { | ||
26 | + align-items: center; | ||
27 | + justify-content: center; | ||
28 | +} | ||
29 | + | ||
30 | +.wrap { | ||
31 | + flex-wrap: wrap; | ||
32 | +} | ||
33 | + | ||
34 | +.flex { | ||
35 | + flex-grow: 1; | ||
36 | +} | ||
37 | + | ||
38 | +.bg { | ||
39 | + background-image: linear-gradient(to bottom, #faefe7, #ffcbd7); | ||
40 | + overflow: hidden; | ||
41 | +} | ||
42 | + | ||
43 | +.white-color { | ||
44 | + color: #fff; | ||
45 | +} | ||
46 | + | ||
47 | +.fs24 { | ||
48 | + font-size: 24rpx; | ||
49 | +} | ||
50 | + | ||
51 | +.fs28 { | ||
52 | + font-size: 28rpx; | ||
53 | +} | ||
54 | + | ||
55 | +.fs32 { | ||
56 | + font-size: 32rpx; | ||
57 | +} | ||
58 | + | ||
59 | +.fs36 { | ||
60 | + font-size: 36rpx; | ||
61 | +} | ||
62 | + | ||
63 | +.calendar { | ||
64 | + width: 100%; | ||
65 | + box-sizing: border-box; | ||
66 | +} | ||
67 | + | ||
68 | +/* 日历操作栏 */ | ||
69 | + | ||
70 | +.handle { | ||
71 | + height: 80rpx; | ||
72 | +} | ||
73 | + | ||
74 | +.prev-handle, | ||
75 | +.next-handle { | ||
76 | + padding: 20rpx; | ||
77 | +} | ||
78 | + | ||
79 | +.date-in-handle { | ||
80 | + height: 80rpx; | ||
81 | +} | ||
82 | + | ||
83 | +/* 星期栏 */ | ||
84 | + | ||
85 | +.weeks { | ||
86 | + height: 50rpx; | ||
87 | + line-height: 50rpx; | ||
88 | + opacity: 0.5; | ||
89 | +} | ||
90 | + | ||
91 | +.week { | ||
92 | + text-align: center; | ||
93 | +} | ||
94 | + | ||
95 | +.grid, | ||
96 | +.week { | ||
97 | + width: 14.286014285714286%; | ||
98 | +} | ||
99 | + | ||
100 | +.date-wrap { | ||
101 | + width: 100%; | ||
102 | + height: 80rpx; | ||
103 | + position: relative; | ||
104 | + left: 0; | ||
105 | + top: 0; | ||
106 | +} | ||
107 | + | ||
108 | +.date { | ||
109 | + position: relative; | ||
110 | + left: 0; | ||
111 | + top: 0; | ||
112 | + width: 55rpx; | ||
113 | + height: 55rpx; | ||
114 | + text-align: center; | ||
115 | + line-height: 55rpx; | ||
116 | + font-size: 26rpx; | ||
117 | + font-weight: 200; | ||
118 | + border-radius: 50%; | ||
119 | + transition: all 0.3s; | ||
120 | + animation-name: choosed; | ||
121 | + animation-duration: 0.5s; | ||
122 | + animation-timing-function: linear; | ||
123 | + animation-iteration-count: 1; | ||
124 | +} | ||
125 | + | ||
126 | +.date-area-mode { | ||
127 | + width: 100%; | ||
128 | + border-radius: 0; | ||
129 | +} | ||
130 | + | ||
131 | +.date-desc { | ||
132 | + width: 150%; | ||
133 | + height: 32rpx; | ||
134 | + font-size: 20rpx; | ||
135 | + line-height: 32rpx; | ||
136 | + position: absolute; | ||
137 | + left: 50%; | ||
138 | + transform: translateX(-50%); | ||
139 | + overflow: hidden; | ||
140 | + word-break: break-all; | ||
141 | + text-overflow: ellipsis; | ||
142 | + white-space: nowrap; | ||
143 | + -webkit-line-clamp: 1; | ||
144 | + text-align: center; | ||
145 | +} | ||
146 | + | ||
147 | +@keyframes choosed { | ||
148 | + from { | ||
149 | + transform: scale(1); | ||
150 | + } | ||
151 | + | ||
152 | + 50% { | ||
153 | + transform: scale(0.9); | ||
154 | + } | ||
155 | + | ||
156 | + to { | ||
157 | + transform: scale(1); | ||
158 | + } | ||
159 | +} | ||
160 | + | ||
161 | +/* 日期圆圈标记 */ | ||
162 | +.todo-circle { | ||
163 | + border-width: 1rpx; | ||
164 | + border-style: solid; | ||
165 | + box-sizing: border-box; | ||
166 | +} | ||
167 | + | ||
168 | +/* 待办点标记相关样式 */ | ||
169 | +.todo-dot { | ||
170 | + width: 10rpx; | ||
171 | + height: 10rpx; | ||
172 | + border-radius: 50%; | ||
173 | + position: absolute; | ||
174 | + left: 50%; | ||
175 | + transform: translateX(-50%); | ||
176 | +} | ||
177 | + | ||
178 | +.todo-dot-top { | ||
179 | + top: 3rpx; | ||
180 | +} | ||
181 | + | ||
182 | +.todo-dot.todo-dot-top-always { | ||
183 | + top: -8rpx; | ||
184 | +} | ||
185 | + | ||
186 | +.todo-dot.todo-dot-bottom { | ||
187 | + bottom: 0; | ||
188 | +} | ||
189 | + | ||
190 | +.todo-dot.todo-dot-bottom-always { | ||
191 | + bottom: -10rpx; | ||
192 | +} | ||
193 | + | ||
194 | +/* 日期描述文字(待办文字/农历)相关样式 */ | ||
195 | + | ||
196 | +.date-desc.date-desc-top { | ||
197 | + top: -6rpx; | ||
198 | +} | ||
199 | + | ||
200 | +.date-desc.date-desc-top-always { | ||
201 | + top: -20rpx; | ||
202 | +} | ||
203 | + | ||
204 | +.date-desc.date-desc-bottom { | ||
205 | + bottom: -14rpx; | ||
206 | +} | ||
207 | + | ||
208 | +.todo-circle .date-desc.date-desc-bottom { | ||
209 | + bottom: -30rpx; | ||
210 | +} | ||
211 | + | ||
212 | +.date-desc.date-desc-bottom-always { | ||
213 | + bottom: -28rpx; | ||
214 | +} |
@@ -0,0 +1,212 @@ | @@ -0,0 +1,212 @@ | ||
1 | +/* * | ||
2 | + @Author: drfu* | ||
3 | + @Description: 数据来源于国务院办公厅关于2020年部分节假日安排的通知(国办发明电〔2019〕16号)_政府信息公开专栏,http://www.gov.cn/zhengce/content/2019-11/21/content_5454164.htm | ||
4 | + @Date: 2020-10-12 14:29:45* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-16 17:38:08 | ||
7 | +*/ | ||
8 | + | ||
9 | +// 节日列表 | ||
10 | +export const festival = { | ||
11 | + // 农历固定日期节日 | ||
12 | + lunar: { | ||
13 | + 1: { | ||
14 | + 1: { | ||
15 | + type: 'festival', | ||
16 | + name: '春节', | ||
17 | + label: '春节' | ||
18 | + }, | ||
19 | + 8: { | ||
20 | + type: 'festival', | ||
21 | + name: '腊八节', | ||
22 | + label: '腊八' | ||
23 | + }, | ||
24 | + 15: { | ||
25 | + type: 'festival', | ||
26 | + name: '元宵节', | ||
27 | + label: '元宵' | ||
28 | + } | ||
29 | + }, | ||
30 | + 7: { | ||
31 | + 7: { | ||
32 | + type: 'festival', | ||
33 | + name: '七夕节', | ||
34 | + label: '七夕' | ||
35 | + }, | ||
36 | + 15: { | ||
37 | + type: 'festival', | ||
38 | + name: '中元节', | ||
39 | + label: '中元节' | ||
40 | + } | ||
41 | + }, | ||
42 | + 9: { | ||
43 | + 9: { | ||
44 | + type: 'festival', | ||
45 | + name: '重阳节', | ||
46 | + label: '重阳节' | ||
47 | + } | ||
48 | + } | ||
49 | + }, | ||
50 | + // 阳历固定日期节日 | ||
51 | + solar: { | ||
52 | + 2: { | ||
53 | + 14: { | ||
54 | + type: 'festival', | ||
55 | + name: '情人节', | ||
56 | + label: '情人节' | ||
57 | + } | ||
58 | + }, | ||
59 | + 3: { | ||
60 | + 12: { | ||
61 | + type: 'festival', | ||
62 | + name: '植树节', | ||
63 | + label: '植树节' | ||
64 | + } | ||
65 | + }, | ||
66 | + 4: { | ||
67 | + 1: { | ||
68 | + type: 'festival', | ||
69 | + name: '愚人节', | ||
70 | + label: '愚人节' | ||
71 | + }, | ||
72 | + 5: { | ||
73 | + type: 'festival', | ||
74 | + name: '清明节', | ||
75 | + label: '清明节' | ||
76 | + } | ||
77 | + }, | ||
78 | + 5: { | ||
79 | + 1: { | ||
80 | + type: 'festival', | ||
81 | + name: '劳动节', | ||
82 | + label: '劳动节' | ||
83 | + } | ||
84 | + }, | ||
85 | + 6: { | ||
86 | + 1: { | ||
87 | + type: 'festival', | ||
88 | + name: '儿童节', | ||
89 | + label: '儿童节' | ||
90 | + } | ||
91 | + }, | ||
92 | + 7: { | ||
93 | + 1: { | ||
94 | + type: 'festival', | ||
95 | + name: '建党节', | ||
96 | + label: '建党节' | ||
97 | + } | ||
98 | + }, | ||
99 | + 8: { | ||
100 | + 1: { | ||
101 | + type: 'festival', | ||
102 | + name: '建军节', | ||
103 | + label: '建军节' | ||
104 | + } | ||
105 | + }, | ||
106 | + 9: { | ||
107 | + 10: { | ||
108 | + type: 'festival', | ||
109 | + name: '教师节', | ||
110 | + label: '教师节' | ||
111 | + } | ||
112 | + }, | ||
113 | + 10: { | ||
114 | + 1: { | ||
115 | + type: 'festival', | ||
116 | + name: '国庆节', | ||
117 | + label: '国庆节' | ||
118 | + } | ||
119 | + }, | ||
120 | + 12: { | ||
121 | + 25: { | ||
122 | + type: 'festival', | ||
123 | + name: '圣诞节', | ||
124 | + label: '圣诞节' | ||
125 | + } | ||
126 | + } | ||
127 | + } | ||
128 | +} | ||
129 | + | ||
130 | +export const holidays = { | ||
131 | + 2020: { | ||
132 | + 1: { | ||
133 | + 1: { | ||
134 | + type: 'holiday', | ||
135 | + name: '元旦', | ||
136 | + label: '休' | ||
137 | + }, | ||
138 | + 19: { | ||
139 | + type: 'work', | ||
140 | + name: '调班', | ||
141 | + label: '班' | ||
142 | + }, | ||
143 | + '24-30': { | ||
144 | + type: 'holiday', | ||
145 | + name: '春节', | ||
146 | + label: '休' | ||
147 | + } | ||
148 | + }, | ||
149 | + 2: { | ||
150 | + 1: { | ||
151 | + type: 'work', | ||
152 | + name: '调班', | ||
153 | + label: '班' | ||
154 | + } | ||
155 | + }, | ||
156 | + 4: { | ||
157 | + '4-6': { | ||
158 | + type: 'holiday', | ||
159 | + name: '清明节', | ||
160 | + label: '休' | ||
161 | + }, | ||
162 | + 26: { | ||
163 | + type: 'work', | ||
164 | + name: '调班', | ||
165 | + label: '班' | ||
166 | + } | ||
167 | + }, | ||
168 | + 5: { | ||
169 | + '1-5': { | ||
170 | + type: 'holiday', | ||
171 | + name: '劳动节', | ||
172 | + label: '休' | ||
173 | + }, | ||
174 | + 9: { | ||
175 | + type: 'work', | ||
176 | + name: '调班', | ||
177 | + label: '班' | ||
178 | + } | ||
179 | + }, | ||
180 | + 6: { | ||
181 | + '25-27': { | ||
182 | + type: 'holiday', | ||
183 | + name: '端午节', | ||
184 | + label: '休' | ||
185 | + }, | ||
186 | + 28: { | ||
187 | + type: 'work', | ||
188 | + name: '调班', | ||
189 | + label: '班' | ||
190 | + } | ||
191 | + }, | ||
192 | + 9: { | ||
193 | + 27: { | ||
194 | + type: 'work', | ||
195 | + name: '调班', | ||
196 | + label: '班' | ||
197 | + } | ||
198 | + }, | ||
199 | + 10: { | ||
200 | + '1-8': { | ||
201 | + type: 'holiday', | ||
202 | + name: '国庆节/中秋节', | ||
203 | + label: '休' | ||
204 | + }, | ||
205 | + 10: { | ||
206 | + type: 'work', | ||
207 | + name: '调班', | ||
208 | + label: '班' | ||
209 | + } | ||
210 | + } | ||
211 | + } | ||
212 | +} |
@@ -0,0 +1,201 @@ | @@ -0,0 +1,201 @@ | ||
1 | +/* * | ||
2 | + @Author: drfu* | ||
3 | + @Description: 显示法定节假日班/休情况 | ||
4 | + @Date: 2020-10-12 14:29:45* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-16 17:34:13 | ||
7 | +*/ | ||
8 | + | ||
9 | +import { holidays, festival } from './holidays-map' | ||
10 | +import { dateUtil, getCalendarData, logger } from '../../utils/index' | ||
11 | + | ||
12 | +/** | ||
13 | + * 当前是否在休假期内 | ||
14 | + * @param {object} { year, month } | ||
15 | + * @param {object} { start, end, current } | ||
16 | + * @returns | ||
17 | + */ | ||
18 | +function inHolidays({ year, month }, { start, end, current }) { | ||
19 | + const getTimeStamp = dateUtil.getTimeStamp | ||
20 | + const startTimestamp = getTimeStamp({ | ||
21 | + year, | ||
22 | + month, | ||
23 | + date: start | ||
24 | + }) | ||
25 | + const endTimestamp = getTimeStamp({ | ||
26 | + year, | ||
27 | + month, | ||
28 | + date: end | ||
29 | + }) | ||
30 | + const currentDateTimestamp = getTimeStamp({ | ||
31 | + year, | ||
32 | + month, | ||
33 | + date: current | ||
34 | + }) | ||
35 | + if ( | ||
36 | + currentDateTimestamp >= startTimestamp && | ||
37 | + currentDateTimestamp <= endTimestamp | ||
38 | + ) { | ||
39 | + return true | ||
40 | + } | ||
41 | + return false | ||
42 | +} | ||
43 | + | ||
44 | +function addSpecialFestival(date, component) { | ||
45 | + const { convertlLunar2Solar, convertSolarLunar } = component.calendar || {} | ||
46 | + const lunarDateInfo = convertSolarLunar(date) | ||
47 | + const { lYear, lMonth } = lunarDateInfo || {} | ||
48 | + // 春节 | ||
49 | + const info = { | ||
50 | + type: 'festival', | ||
51 | + name: '除夕', | ||
52 | + label: '除夕' | ||
53 | + } | ||
54 | + if (lMonth === 12) { | ||
55 | + if (!festival.lunar['12']) festival.lunar['12'] = {} | ||
56 | + if (convertlLunar2Solar(`${lYear}-12-30`) === -1) { | ||
57 | + festival.lunar['12']['29'] = info | ||
58 | + } else { | ||
59 | + festival.lunar['12']['30'] = info | ||
60 | + } | ||
61 | + } | ||
62 | +} | ||
63 | + | ||
64 | +/** | ||
65 | + * 是否匹配到节日 | ||
66 | + * @param {object} [dateInfo={}] | ||
67 | + * @param {object} [component={}] | ||
68 | + * @returns {object|boolean} 匹配到的节日数据或者false | ||
69 | + */ | ||
70 | +function hasFestivalDate(dateInfo = {}, component = {}) { | ||
71 | + const { month, date } = dateInfo | ||
72 | + let festivalDate = festival.solar[month] && festival.solar[month][date] | ||
73 | + if (!festivalDate) { | ||
74 | + const { convertSolarLunar } = component.calendar || {} | ||
75 | + const lunarDateInfo = convertSolarLunar(dateInfo) | ||
76 | + const { lMonth, lDay } = lunarDateInfo | ||
77 | + festivalDate = festival.lunar[lMonth] && festival.lunar[lMonth][lDay] | ||
78 | + if (!festivalDate) { | ||
79 | + const festivalOfMonth = festival.lunar[lMonth] || {} | ||
80 | + const festivalDateKey = Object.keys(festivalOfMonth).find(item => | ||
81 | + item.match(new RegExp(`\\b${lDay}\\b`)) | ||
82 | + ) | ||
83 | + if (!festivalDateKey) { | ||
84 | + festivalDate = false | ||
85 | + } else { | ||
86 | + const festivalInfo = festival.lunar[lMonth][festivalDateKey] | ||
87 | + if (!festivalInfo) { | ||
88 | + festivalDate = false | ||
89 | + } else { | ||
90 | + const { condition } = festivalInfo | ||
91 | + if (typeof condition === 'function') { | ||
92 | + festivalDate = condition(lunarDateInfo) | ||
93 | + } else { | ||
94 | + festivalDate = false | ||
95 | + } | ||
96 | + } | ||
97 | + } | ||
98 | + } | ||
99 | + } | ||
100 | + return festivalDate | ||
101 | +} | ||
102 | + | ||
103 | +export default () => { | ||
104 | + return { | ||
105 | + name: 'holidays', | ||
106 | + beforeRender(calendarData = {}, calendarConfig = {}, component) { | ||
107 | + let { dates = [] } = calendarData | ||
108 | + if (calendarConfig.showHolidays || calendarConfig.showFestival) { | ||
109 | + dates = dates.map(d => { | ||
110 | + let item = { ...d } | ||
111 | + const { year, month, date } = item | ||
112 | + const holidaysOfMonth = | ||
113 | + (holidays[year] && holidays[year][month]) || {} | ||
114 | + const holidayDate = holidaysOfMonth[date] | ||
115 | + if (holidayDate) { | ||
116 | + item = { | ||
117 | + ...item, | ||
118 | + ...holidayDate | ||
119 | + } | ||
120 | + } else { | ||
121 | + const holidayKeys = Object.keys(holidaysOfMonth).filter(item => | ||
122 | + item.includes('-') | ||
123 | + ) | ||
124 | + let target = '' | ||
125 | + for (let v of holidayKeys) { | ||
126 | + const [start, end] = v.split('-') | ||
127 | + if (+d.date >= +start && +d.date <= +end) { | ||
128 | + target = v | ||
129 | + break | ||
130 | + } | ||
131 | + } | ||
132 | + const [start, end] = target.split('-') | ||
133 | + const isInHolidays = inHolidays( | ||
134 | + { | ||
135 | + year, | ||
136 | + month | ||
137 | + }, | ||
138 | + { | ||
139 | + start, | ||
140 | + end, | ||
141 | + current: date | ||
142 | + } | ||
143 | + ) | ||
144 | + if (isInHolidays) { | ||
145 | + item = { | ||
146 | + ...item, | ||
147 | + ...holidaysOfMonth[target] | ||
148 | + } | ||
149 | + } else if (calendarConfig.showFestival) { | ||
150 | + const { convertSolarLunar, convertlLunar2Solar } = | ||
151 | + component.calendar || {} | ||
152 | + if ( | ||
153 | + typeof convertSolarLunar !== 'function' || | ||
154 | + typeof convertlLunar2Solar !== 'function' | ||
155 | + ) { | ||
156 | + return logger.warn( | ||
157 | + '农历节日显示需要引入农历插件(/component/v2/plugins/solarLunar)' | ||
158 | + ) | ||
159 | + } | ||
160 | + addSpecialFestival(item, component) | ||
161 | + const festivalDate = hasFestivalDate(item, component) | ||
162 | + if (festivalDate) { | ||
163 | + item = { | ||
164 | + ...item, | ||
165 | + ...festivalDate | ||
166 | + } | ||
167 | + } | ||
168 | + } | ||
169 | + } | ||
170 | + return item | ||
171 | + }) | ||
172 | + } | ||
173 | + return { | ||
174 | + calendarData: { | ||
175 | + ...calendarData, | ||
176 | + dates: dates | ||
177 | + }, | ||
178 | + calendarConfig | ||
179 | + } | ||
180 | + }, | ||
181 | + methods(component) { | ||
182 | + return { | ||
183 | + getHolidaysOfCurrentYear() { | ||
184 | + const calendar = getCalendarData('calendar', component) | ||
185 | + const { curYear } = calendar | ||
186 | + return this.methods(component).getHolidaysOfYear(curYear) | ||
187 | + }, | ||
188 | + getHolidaysOfYear(year) { | ||
189 | + if (!year) return logger.warn('getHolidaysOfCurrentYear() 入参错误') | ||
190 | + if (!holidays[year]) { | ||
191 | + logger.warn('未匹配到当前年份节假日信息,请自行补充') | ||
192 | + return { | ||
193 | + err: 'not match' | ||
194 | + } | ||
195 | + } | ||
196 | + return holidays[year] | ||
197 | + } | ||
198 | + } | ||
199 | + } | ||
200 | + } | ||
201 | +} |
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +import preset from './preset/index' | ||
2 | + | ||
3 | +export default { | ||
4 | + installed: [...preset], | ||
5 | + use(plugin) { | ||
6 | + if (typeof plugin !== 'function') return | ||
7 | + const info = plugin() || {} | ||
8 | + const { name } = info | ||
9 | + if ( | ||
10 | + name && | ||
11 | + name !== 'methods' && | ||
12 | + !this.installed.some(p => p[0] === name) | ||
13 | + ) { | ||
14 | + this.installed.unshift([name, info]) | ||
15 | + } | ||
16 | + return this | ||
17 | + } | ||
18 | +} |
@@ -0,0 +1,277 @@ | @@ -0,0 +1,277 @@ | ||
1 | +/** | ||
2 | + * @Author: drfu* | ||
3 | + * @Description: 基础功能 | ||
4 | + * @Date: 2020-10-08 21:22:09* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-11 13:28:52 | ||
7 | + * */ | ||
8 | + | ||
9 | +import { calcJumpData } from '../../core' | ||
10 | +import { renderCalendar } from '../../render' | ||
11 | +import { | ||
12 | + dateUtil, | ||
13 | + getCalendarData, | ||
14 | + setCalendarData, | ||
15 | + getCalendarConfig | ||
16 | +} from '../../utils/index' | ||
17 | + | ||
18 | +export default () => { | ||
19 | + return { | ||
20 | + name: 'base', | ||
21 | + beforeRender(calendarData = {}, calendarConfig) { | ||
22 | + const calendar = calendarData | ||
23 | + const { selectedDates = [], dates } = calendar | ||
24 | + let _dates = [...dates] | ||
25 | + if (selectedDates.length) { | ||
26 | + const selectedDatesStr = selectedDates.map(date => | ||
27 | + dateUtil.toTimeStr(date) | ||
28 | + ) | ||
29 | + _dates.forEach(date => { | ||
30 | + const dateStr = dateUtil.toTimeStr(date) | ||
31 | + if (selectedDatesStr.includes(dateStr)) { | ||
32 | + date.choosed = true | ||
33 | + } | ||
34 | + }) | ||
35 | + } | ||
36 | + return { | ||
37 | + calendarData: { | ||
38 | + ...calendarData, | ||
39 | + dates: _dates | ||
40 | + }, | ||
41 | + calendarConfig | ||
42 | + } | ||
43 | + }, | ||
44 | + onTapDate(tapedDate, calendarData = {}, calendarConfig = {}) { | ||
45 | + const calendar = { | ||
46 | + ...calendarData | ||
47 | + } | ||
48 | + const dateIndex = dateUtil.findDateIndexInArray( | ||
49 | + tapedDate, | ||
50 | + calendarData.dates | ||
51 | + ) | ||
52 | + const { multi, inverse } = calendarConfig | ||
53 | + let dates = [...calendar.dates] | ||
54 | + const { selectedDates = [] } = calendar | ||
55 | + if (!multi) { | ||
56 | + let preSelectedDate = {} | ||
57 | + if (selectedDates.length) { | ||
58 | + preSelectedDate = [...selectedDates].pop() || {} | ||
59 | + } | ||
60 | + const timeStr = dateUtil.toTimeStr | ||
61 | + if (!inverse && timeStr(preSelectedDate) === timeStr(tapedDate)) { | ||
62 | + return calendar | ||
63 | + } | ||
64 | + let _tapedDate = { ...tapedDate, choosed: !tapedDate.choosed } | ||
65 | + | ||
66 | + dates[dateIndex] = _tapedDate | ||
67 | + if (preSelectedDate.date) { | ||
68 | + const idx = dateUtil.findDateIndexInArray(preSelectedDate, dates) | ||
69 | + const date = dates[idx] | ||
70 | + if (date) { | ||
71 | + date.choosed = false | ||
72 | + } | ||
73 | + } | ||
74 | + if (dates[dateIndex].choosed) { | ||
75 | + calendar.selectedDates = [dates[dateIndex]] | ||
76 | + } else { | ||
77 | + calendar.selectedDates = [] | ||
78 | + } | ||
79 | + } else { | ||
80 | + dates[dateIndex] = { | ||
81 | + ...dates[dateIndex], | ||
82 | + choosed: !dates[dateIndex].choosed | ||
83 | + } | ||
84 | + if (!calendar.selectedDates) { | ||
85 | + calendar.selectedDates = [] | ||
86 | + } | ||
87 | + if (dates[dateIndex].choosed) { | ||
88 | + calendar.selectedDates.push(dates[dateIndex]) | ||
89 | + } else { | ||
90 | + calendar.selectedDates = calendar.selectedDates.filter( | ||
91 | + date => | ||
92 | + dateUtil.toTimeStr(date) !== dateUtil.toTimeStr(dates[dateIndex]) | ||
93 | + ) | ||
94 | + } | ||
95 | + } | ||
96 | + return { | ||
97 | + calendarData: { | ||
98 | + ...calendar, | ||
99 | + dates | ||
100 | + }, | ||
101 | + calendarConfig | ||
102 | + } | ||
103 | + }, | ||
104 | + onSwitchCalendar(date, calendarData = {}, component) { | ||
105 | + const calendarConfig = getCalendarConfig(component) | ||
106 | + if (calendarConfig.weekMode) { | ||
107 | + return calendarData | ||
108 | + } | ||
109 | + const updatedRenderData = calcJumpData({ | ||
110 | + dateInfo: date, | ||
111 | + config: calendarConfig | ||
112 | + }) | ||
113 | + return { | ||
114 | + ...calendarData, | ||
115 | + ...updatedRenderData | ||
116 | + } | ||
117 | + }, | ||
118 | + methods(component) { | ||
119 | + return { | ||
120 | + jump: dateInfo => { | ||
121 | + if (Object.prototype.toString.call(dateInfo) !== '[object Object]') | ||
122 | + return | ||
123 | + const updatedRenderData = calcJumpData({ | ||
124 | + dateInfo, | ||
125 | + component | ||
126 | + }) | ||
127 | + const existCalendarData = getCalendarData('calendar', component) | ||
128 | + const config = getCalendarConfig(component) | ||
129 | + if (config.autoChoosedWhenJump) { | ||
130 | + const target = updatedRenderData.dates[dateInfo.date - 1] | ||
131 | + if (!updatedRenderData.selectedDates) { | ||
132 | + updatedRenderData.selectedDates = [target] | ||
133 | + } else { | ||
134 | + updatedRenderData.selectedDates.push(target) | ||
135 | + } | ||
136 | + } | ||
137 | + return renderCalendar.call(component, { | ||
138 | + ...existCalendarData, | ||
139 | + ...updatedRenderData | ||
140 | + }) | ||
141 | + }, | ||
142 | + getCalendarConfig() { | ||
143 | + return getCalendarConfig(component) | ||
144 | + }, | ||
145 | + setCalendarConfig(config) { | ||
146 | + return new Promise((resolve, reject) => { | ||
147 | + if (!component || !component.data.config) { | ||
148 | + reject('异常:未找到组件配置信息') | ||
149 | + return | ||
150 | + } | ||
151 | + let conf = { ...component.data.config, ...config } | ||
152 | + component.data.config = conf | ||
153 | + setCalendarData({ config: conf }, component) | ||
154 | + .then(resolve) | ||
155 | + .catch(reject) | ||
156 | + }) | ||
157 | + }, | ||
158 | + cancelSelectedDates(cancelDates = []) { | ||
159 | + const existCalendarData = getCalendarData('calendar', component) || {} | ||
160 | + const { dates = [], selectedDates = [] } = existCalendarData | ||
161 | + let updatedRenderData = {} | ||
162 | + const config = getCalendarConfig(component) | ||
163 | + let chooseAreaData = {} | ||
164 | + if (config.chooseAreaMode) { | ||
165 | + chooseAreaData = { | ||
166 | + chooseAreaTimestamp: [], | ||
167 | + tempChooseAreaTimestamp: [] | ||
168 | + } | ||
169 | + } | ||
170 | + if (!cancelDates.length) { | ||
171 | + dates.forEach(item => { | ||
172 | + item.choosed = false | ||
173 | + }) | ||
174 | + updatedRenderData = { | ||
175 | + dates, | ||
176 | + selectedDates: [] | ||
177 | + } | ||
178 | + } else { | ||
179 | + const cancelDatesStr = cancelDates.map(date => | ||
180 | + dateUtil.toTimeStr(date) | ||
181 | + ) | ||
182 | + const filterSelectedDates = selectedDates.filter( | ||
183 | + date => !cancelDatesStr.includes(dateUtil.toTimeStr(date)) | ||
184 | + ) | ||
185 | + dates.forEach(date => { | ||
186 | + if (cancelDatesStr.includes(dateUtil.toTimeStr(date))) { | ||
187 | + date.choosed = false | ||
188 | + } | ||
189 | + }) | ||
190 | + updatedRenderData = { | ||
191 | + dates, | ||
192 | + selectedDates: filterSelectedDates | ||
193 | + } | ||
194 | + } | ||
195 | + | ||
196 | + return renderCalendar.call(component, { | ||
197 | + ...existCalendarData, | ||
198 | + ...updatedRenderData, | ||
199 | + ...chooseAreaData | ||
200 | + }) | ||
201 | + }, | ||
202 | + setSelectedDates: targetDates => { | ||
203 | + const existCalendarData = getCalendarData('calendar', component) | ||
204 | + let { dates, selectedDates = [] } = existCalendarData || {} | ||
205 | + let __selectedDates = [] | ||
206 | + let __dates = dates | ||
207 | + if (!targetDates) { | ||
208 | + __dates = dates.map(item => { | ||
209 | + const date = { ...item } | ||
210 | + date.choosed = true | ||
211 | + if (existCalendarData.showLabelAlways && date.showTodoLabel) { | ||
212 | + date.showTodoLabel = true | ||
213 | + } else { | ||
214 | + date.showTodoLabel = false | ||
215 | + } | ||
216 | + return date | ||
217 | + }) | ||
218 | + __selectedDates = dates | ||
219 | + } else if (targetDates && targetDates.length) { | ||
220 | + const allSelected = dateUtil.uniqueArrayByDate( | ||
221 | + selectedDates.concat(targetDates) | ||
222 | + ) | ||
223 | + const allSelectedDateStr = allSelected.map(d => | ||
224 | + dateUtil.toTimeStr(d) | ||
225 | + ) | ||
226 | + __dates = dates.map(item => { | ||
227 | + const date = { ...item } | ||
228 | + if (allSelectedDateStr.includes(dateUtil.toTimeStr(date))) { | ||
229 | + date.choosed = true | ||
230 | + __selectedDates.push(date) | ||
231 | + } | ||
232 | + if (existCalendarData.showLabelAlways && date.showTodoLabel) { | ||
233 | + date.showTodoLabel = true | ||
234 | + } else { | ||
235 | + date.showTodoLabel = false | ||
236 | + } | ||
237 | + return date | ||
238 | + }) | ||
239 | + } | ||
240 | + return renderCalendar.call(component, { | ||
241 | + ...existCalendarData, | ||
242 | + dates: __dates, | ||
243 | + selectedDates: __selectedDates | ||
244 | + }) | ||
245 | + }, | ||
246 | + setDateStyle: toSetDates => { | ||
247 | + if (!Array.isArray(toSetDates)) return Promise.reject() | ||
248 | + const existCalendarData = getCalendarData('calendar', component) | ||
249 | + const { dates = [], specialStyleDates } = existCalendarData || {} | ||
250 | + if (Array.isArray(specialStyleDates)) { | ||
251 | + toSetDates = dateUtil.uniqueArrayByDate([ | ||
252 | + ...specialStyleDates, | ||
253 | + ...toSetDates | ||
254 | + ]) | ||
255 | + } | ||
256 | + const toSetDatesStr = toSetDates.map(item => dateUtil.toTimeStr(item)) | ||
257 | + const _dates = dates.map(item => { | ||
258 | + const idx = toSetDatesStr.indexOf(dateUtil.toTimeStr(item)) | ||
259 | + if (idx > -1) { | ||
260 | + return { | ||
261 | + ...item, | ||
262 | + class: toSetDates[idx].class | ||
263 | + } | ||
264 | + } else { | ||
265 | + return item | ||
266 | + } | ||
267 | + }) | ||
268 | + return renderCalendar.call(component, { | ||
269 | + ...existCalendarData, | ||
270 | + dates: _dates, | ||
271 | + specialStyleDates: toSetDates | ||
272 | + }) | ||
273 | + } | ||
274 | + } | ||
275 | + } | ||
276 | + } | ||
277 | +} |
@@ -0,0 +1,69 @@ | @@ -0,0 +1,69 @@ | ||
1 | +/** | ||
2 | + * @Author: drfu* | ||
3 | + * @Description: 获取日历数据 | ||
4 | + * @Date: 2020-10-08 21:22:09* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-11 13:42:37 | ||
7 | + * */ | ||
8 | + | ||
9 | +import { getCalendarData, logger, getCalendarConfig } from '../../utils/index' | ||
10 | + | ||
11 | +function wrapDateWithLunar(dates = [], convertFn) { | ||
12 | + const datesWithLunar = JSON.parse(JSON.stringify(dates)).map(date => ({ | ||
13 | + ...date, | ||
14 | + lunar: convertFn(date) | ||
15 | + })) | ||
16 | + return datesWithLunar | ||
17 | +} | ||
18 | + | ||
19 | +export default () => { | ||
20 | + return { | ||
21 | + name: 'getData', | ||
22 | + methods(component) { | ||
23 | + return { | ||
24 | + getCurrentYM: () => { | ||
25 | + const { curYear, curMonth } = getCalendarData('calendar', component) | ||
26 | + return { | ||
27 | + year: curYear, | ||
28 | + month: curMonth | ||
29 | + } | ||
30 | + }, | ||
31 | + getSelectedDates: (options = {}) => { | ||
32 | + const dates = | ||
33 | + getCalendarData('calendar.selectedDates', component) || [] | ||
34 | + const config = getCalendarConfig(component) || {} | ||
35 | + if (options.lunar && !config.showLunar) { | ||
36 | + const injectedFns = component.calendar || {} | ||
37 | + if (typeof injectedFns.convertSolarLunar === 'function') { | ||
38 | + return wrapDateWithLunar(dates, injectedFns.convertSolarLunar) | ||
39 | + } else { | ||
40 | + logger.warn('获取农历信息需引入农历插件') | ||
41 | + } | ||
42 | + } else { | ||
43 | + return dates | ||
44 | + } | ||
45 | + }, | ||
46 | + getCalendarDates: (options = {}) => { | ||
47 | + const config = getCalendarConfig(component) || {} | ||
48 | + const dates = getCalendarData('calendar.dates', component) | ||
49 | + if (options.lunar && !config.showLunar) { | ||
50 | + const injectedFns = component.calendar || {} | ||
51 | + if (typeof injectedFns.convertSolarLunar === 'function') { | ||
52 | + return wrapDateWithLunar(dates, injectedFns.convertSolarLunar) | ||
53 | + } else { | ||
54 | + logger.warn('获取农历信息需引入农历插件') | ||
55 | + } | ||
56 | + } else { | ||
57 | + return dates | ||
58 | + } | ||
59 | + }, | ||
60 | + getCalendarAllData: () => { | ||
61 | + return { | ||
62 | + data: getCalendarData('calendar', component) || {}, | ||
63 | + config: getCalendarConfig(component) || {} | ||
64 | + } | ||
65 | + } | ||
66 | + } | ||
67 | + } | ||
68 | + } | ||
69 | +} |
@@ -0,0 +1,219 @@ | @@ -0,0 +1,219 @@ | ||
1 | +/** | ||
2 | + * @Author: drfu* | ||
3 | + * @Description: 禁用、启用日期选择 | ||
4 | + * @Date: 2020-10-08 21:22:09* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-08 21:25:00 | ||
7 | + * */ | ||
8 | + | ||
9 | +import { getCalendarData, dateUtil, logger } from '../utils/index' | ||
10 | +import { renderCalendar } from '../render' | ||
11 | + | ||
12 | +function convertEnableAreaToTimestamp(timearea = []) { | ||
13 | + const start = timearea[0].split('-') | ||
14 | + const end = timearea[1].split('-') | ||
15 | + if (start.length !== 3 || end.length !== 3) { | ||
16 | + logger.warn('enableArea() 参数格式为: ["2018-2-1", "2018-3-1"]') | ||
17 | + return {} | ||
18 | + } | ||
19 | + const startTimestamp = dateUtil | ||
20 | + .newDate(start[0], start[1], start[2]) | ||
21 | + .getTime() | ||
22 | + const endTimestamp = dateUtil.newDate(end[0], end[1], end[2]).getTime() | ||
23 | + return { | ||
24 | + start, | ||
25 | + end, | ||
26 | + startTimestamp, | ||
27 | + endTimestamp | ||
28 | + } | ||
29 | +} | ||
30 | + | ||
31 | +function isValiditeOfDateArea(dateArea) { | ||
32 | + const { | ||
33 | + start, | ||
34 | + end, | ||
35 | + startTimestamp, | ||
36 | + endTimestamp | ||
37 | + } = convertEnableAreaToTimestamp(dateArea) | ||
38 | + if (!start || !end) return | ||
39 | + const datesCountOfStart = dateUtil.getDatesCountOfMonth(start[0], start[1]) | ||
40 | + const datesCountOfEnd = dateUtil.getDatesCountOfMonth(end[0], end[1]) | ||
41 | + if (start[2] > datesCountOfStart || start[2] < 1) { | ||
42 | + logger.warn('enableArea() 开始日期错误,指定日期不在指定月份天数范围内') | ||
43 | + return false | ||
44 | + } else if (start[1] > 12 || start[1] < 1) { | ||
45 | + logger.warn('enableArea() 开始日期错误,月份超出1-12月份') | ||
46 | + return false | ||
47 | + } else if (end[2] > datesCountOfEnd || end[2] < 1) { | ||
48 | + logger.warn('enableArea() 截止日期错误,指定日期不在指定月份天数范围内') | ||
49 | + return false | ||
50 | + } else if (end[1] > 12 || end[1] < 1) { | ||
51 | + logger.warn('enableArea() 截止日期错误,月份超出1-12月份') | ||
52 | + return false | ||
53 | + } else if (startTimestamp > endTimestamp) { | ||
54 | + logger.warn('enableArea()参数最小日期大于了最大日期') | ||
55 | + return false | ||
56 | + } else { | ||
57 | + return true | ||
58 | + } | ||
59 | +} | ||
60 | + | ||
61 | +function handleDisableMode(calendarConfig) { | ||
62 | + const { disableMode } = calendarConfig | ||
63 | + if (!disableMode) return {} | ||
64 | + const disableBound = | ||
65 | + dateUtil.getTimeStamp(disableMode.date) || dateUtil.todayTimestamp() | ||
66 | + return { | ||
67 | + disableBound, | ||
68 | + disableType: disableMode.type | ||
69 | + } | ||
70 | +} | ||
71 | + | ||
72 | +function disabledByConfig(dateInfo, currentDate, calendarConfig) { | ||
73 | + const date = { ...dateInfo } | ||
74 | + const { disableType, disableBound } = handleDisableMode(calendarConfig) | ||
75 | + if ( | ||
76 | + (disableType === 'before' && disableBound && currentDate < disableBound) || | ||
77 | + (disableType === 'after' && disableBound && currentDate > disableBound) | ||
78 | + ) { | ||
79 | + date.disable = true | ||
80 | + } else { | ||
81 | + date.disable = false | ||
82 | + } | ||
83 | + return date | ||
84 | +} | ||
85 | + | ||
86 | +export default () => { | ||
87 | + return { | ||
88 | + name: 'enable', | ||
89 | + beforeRender(calendarData = {}, calendarConfig = {}) { | ||
90 | + const { | ||
91 | + dates, | ||
92 | + enableArea, | ||
93 | + enableDates, | ||
94 | + disableDates, | ||
95 | + renderCausedBy | ||
96 | + } = calendarData | ||
97 | + const _dates = [...dates].map(date => { | ||
98 | + let item = { ...date } | ||
99 | + const timeStr = dateUtil.toTimeStr(date) | ||
100 | + const timestamp = +dateUtil.getTimeStamp(item) | ||
101 | + if (renderCausedBy === 'enableDates') { | ||
102 | + if (enableDates && enableDates.length) { | ||
103 | + if (enableDates.includes(timeStr)) { | ||
104 | + item.disable = false | ||
105 | + } else { | ||
106 | + item.disable = true | ||
107 | + } | ||
108 | + return item | ||
109 | + } | ||
110 | + } else if (renderCausedBy === 'enableArea') { | ||
111 | + if (enableArea && enableArea.length) { | ||
112 | + const [startTimestamp, endTimestamp] = enableArea || [] | ||
113 | + const ifOutofArea = | ||
114 | + +startTimestamp > timestamp || timestamp > +endTimestamp | ||
115 | + item.disable = ifOutofArea | ||
116 | + return item | ||
117 | + } | ||
118 | + } else if (renderCausedBy === 'disableDates') { | ||
119 | + if (disableDates && disableDates.length) { | ||
120 | + if (disableDates && disableDates.includes(timeStr)) { | ||
121 | + item.disable = true | ||
122 | + } | ||
123 | + return item | ||
124 | + } | ||
125 | + } | ||
126 | + return disabledByConfig(item, timestamp, calendarConfig) | ||
127 | + }) | ||
128 | + | ||
129 | + return { | ||
130 | + calendarData: { | ||
131 | + ...calendarData, | ||
132 | + dates: _dates | ||
133 | + }, | ||
134 | + calendarConfig | ||
135 | + } | ||
136 | + }, | ||
137 | + methods(component) { | ||
138 | + return { | ||
139 | + enableArea: (dateArea = []) => { | ||
140 | + if (dateArea.length === 2) { | ||
141 | + const validate = isValiditeOfDateArea(dateArea) | ||
142 | + if (validate) { | ||
143 | + const existCalendarData = getCalendarData('calendar', component) | ||
144 | + const { | ||
145 | + startTimestamp, | ||
146 | + endTimestamp | ||
147 | + } = convertEnableAreaToTimestamp(dateArea) | ||
148 | + | ||
149 | + return renderCalendar.call(component, { | ||
150 | + ...existCalendarData, | ||
151 | + renderCausedBy: 'enableArea', | ||
152 | + enableArea: [startTimestamp, endTimestamp] | ||
153 | + }) | ||
154 | + } | ||
155 | + } else { | ||
156 | + return Promise.inject( | ||
157 | + 'enableArea()参数需为时间范围数组,形如:["2018-8-4" , "2018-8-24"]' | ||
158 | + ) | ||
159 | + } | ||
160 | + }, | ||
161 | + enableDates: (toSet = []) => { | ||
162 | + if (!toSet.length) return | ||
163 | + const existCalendarData = getCalendarData('calendar', component) | ||
164 | + const { enableDates = [] } = existCalendarData || {} | ||
165 | + let toSetDates = toSet.map(item => { | ||
166 | + if (typeof item === 'string') { | ||
167 | + return dateUtil.transformDateRow2Dict(item) | ||
168 | + } | ||
169 | + return item | ||
170 | + }) | ||
171 | + if (enableDates.length) { | ||
172 | + toSetDates = dateUtil.uniqueArrayByDate([ | ||
173 | + ...toSetDates, | ||
174 | + ...enableDates.map(d => dateUtil.transformDateRow2Dict(d)) | ||
175 | + ]) | ||
176 | + } | ||
177 | + return renderCalendar.call(component, { | ||
178 | + ...existCalendarData, | ||
179 | + renderCausedBy: 'enableDates', | ||
180 | + enableDates: toSetDates.map(date => { | ||
181 | + if (typeof date !== 'string') { | ||
182 | + return dateUtil.toTimeStr(date) | ||
183 | + } | ||
184 | + return date | ||
185 | + }) | ||
186 | + }) | ||
187 | + }, | ||
188 | + disableDates: toSet => { | ||
189 | + const existCalendarData = getCalendarData('calendar', component) | ||
190 | + const { disableDates = [], dates = [] } = existCalendarData || {} | ||
191 | + let toSetDates = toSet.map(item => { | ||
192 | + let date = { ...item } | ||
193 | + if (typeof date === 'string') { | ||
194 | + return dateUtil.transformDateRow2Dict(item) | ||
195 | + } | ||
196 | + return item | ||
197 | + }) | ||
198 | + if (disableDates && disableDates.length) { | ||
199 | + toSetDates = dateUtil.uniqueArrayByDate([ | ||
200 | + ...toSetDates, | ||
201 | + ...disableDates.map(d => dateUtil.transformDateRow2Dict(d)) | ||
202 | + ]) | ||
203 | + } | ||
204 | + return renderCalendar.call(component, { | ||
205 | + ...existCalendarData, | ||
206 | + renderCausedBy: 'disableDates', | ||
207 | + dates, | ||
208 | + disableDates: toSetDates.map(date => { | ||
209 | + if (typeof date !== 'string') { | ||
210 | + return dateUtil.toTimeStr(date) | ||
211 | + } | ||
212 | + return date | ||
213 | + }) | ||
214 | + }) | ||
215 | + } | ||
216 | + } | ||
217 | + } | ||
218 | + } | ||
219 | +} |
@@ -0,0 +1,1036 @@ | @@ -0,0 +1,1036 @@ | ||
1 | +/** | ||
2 | + * @1900-2100区间内的公历、农历互转 | ||
3 | + * @Version 1.0.3 | ||
4 | + * @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0] | ||
5 | + * @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0] | ||
6 | + */ | ||
7 | +/* 公历年月日转农历数据 返回json */ | ||
8 | +// calendar.solar2lunar(1987,11,01); | ||
9 | +/** 农历年月日转公历年月日 **/ | ||
10 | +// calendar.lunar2solar(1987,9,10); | ||
11 | +// 调用以上方法后返回类似如下object(json)具体以上就不需要解释了吧! | ||
12 | +// c开头的是公历各属性值 l开头的自然就是农历咯 gz开头的就是天干地支纪年的数据啦~ | ||
13 | +// { | ||
14 | +// Animal: "兔", | ||
15 | +// IDayCn: "初十", | ||
16 | +// IMonthCn: "九月", | ||
17 | +// Term: null, | ||
18 | +// astro: "天蝎座", | ||
19 | +// cDay: 1, | ||
20 | +// cMonth: 11, | ||
21 | +// cYear: 1987, | ||
22 | +// gzDay: "甲寅", | ||
23 | +// gzMonth: "庚戌", | ||
24 | +// gzYear: "丁卯", | ||
25 | +// isLeap: false, | ||
26 | +// isTerm: false, | ||
27 | +// isToday: false, | ||
28 | +// lDay: 10, | ||
29 | +// lMonth: 9, | ||
30 | +// lYear: 1987, | ||
31 | +// nWeek: 7, | ||
32 | +// ncWeek: "星期日" | ||
33 | +// } | ||
34 | +// 该代码还有其他可以调用的方法,请自己查看代码中的详细注释 | ||
35 | +const calendar = { | ||
36 | + /** | ||
37 | + * 农历1900-2100的润大小信息表 | ||
38 | + * @Array Of Property | ||
39 | + * @return Hex | ||
40 | + */ | ||
41 | + lunarInfo: [ | ||
42 | + 0x04bd8, | ||
43 | + 0x04ae0, | ||
44 | + 0x0a570, | ||
45 | + 0x054d5, | ||
46 | + 0x0d260, | ||
47 | + 0x0d950, | ||
48 | + 0x16554, | ||
49 | + 0x056a0, | ||
50 | + 0x09ad0, | ||
51 | + 0x055d2, // 1900-1909 | ||
52 | + 0x04ae0, | ||
53 | + 0x0a5b6, | ||
54 | + 0x0a4d0, | ||
55 | + 0x0d250, | ||
56 | + 0x1d255, | ||
57 | + 0x0b540, | ||
58 | + 0x0d6a0, | ||
59 | + 0x0ada2, | ||
60 | + 0x095b0, | ||
61 | + 0x14977, // 1910-1919 | ||
62 | + 0x04970, | ||
63 | + 0x0a4b0, | ||
64 | + 0x0b4b5, | ||
65 | + 0x06a50, | ||
66 | + 0x06d40, | ||
67 | + 0x1ab54, | ||
68 | + 0x02b60, | ||
69 | + 0x09570, | ||
70 | + 0x052f2, | ||
71 | + 0x04970, // 1920-1929 | ||
72 | + 0x06566, | ||
73 | + 0x0d4a0, | ||
74 | + 0x0ea50, | ||
75 | + 0x06e95, | ||
76 | + 0x05ad0, | ||
77 | + 0x02b60, | ||
78 | + 0x186e3, | ||
79 | + 0x092e0, | ||
80 | + 0x1c8d7, | ||
81 | + 0x0c950, // 1930-1939 | ||
82 | + 0x0d4a0, | ||
83 | + 0x1d8a6, | ||
84 | + 0x0b550, | ||
85 | + 0x056a0, | ||
86 | + 0x1a5b4, | ||
87 | + 0x025d0, | ||
88 | + 0x092d0, | ||
89 | + 0x0d2b2, | ||
90 | + 0x0a950, | ||
91 | + 0x0b557, // 1940-1949 | ||
92 | + 0x06ca0, | ||
93 | + 0x0b550, | ||
94 | + 0x15355, | ||
95 | + 0x04da0, | ||
96 | + 0x0a5b0, | ||
97 | + 0x14573, | ||
98 | + 0x052b0, | ||
99 | + 0x0a9a8, | ||
100 | + 0x0e950, | ||
101 | + 0x06aa0, // 1950-1959 | ||
102 | + 0x0aea6, | ||
103 | + 0x0ab50, | ||
104 | + 0x04b60, | ||
105 | + 0x0aae4, | ||
106 | + 0x0a570, | ||
107 | + 0x05260, | ||
108 | + 0x0f263, | ||
109 | + 0x0d950, | ||
110 | + 0x05b57, | ||
111 | + 0x056a0, // 1960-1969 | ||
112 | + 0x096d0, | ||
113 | + 0x04dd5, | ||
114 | + 0x04ad0, | ||
115 | + 0x0a4d0, | ||
116 | + 0x0d4d4, | ||
117 | + 0x0d250, | ||
118 | + 0x0d558, | ||
119 | + 0x0b540, | ||
120 | + 0x0b6a0, | ||
121 | + 0x195a6, // 1970-1979 | ||
122 | + 0x095b0, | ||
123 | + 0x049b0, | ||
124 | + 0x0a974, | ||
125 | + 0x0a4b0, | ||
126 | + 0x0b27a, | ||
127 | + 0x06a50, | ||
128 | + 0x06d40, | ||
129 | + 0x0af46, | ||
130 | + 0x0ab60, | ||
131 | + 0x09570, // 1980-1989 | ||
132 | + 0x04af5, | ||
133 | + 0x04970, | ||
134 | + 0x064b0, | ||
135 | + 0x074a3, | ||
136 | + 0x0ea50, | ||
137 | + 0x06b58, | ||
138 | + 0x055c0, | ||
139 | + 0x0ab60, | ||
140 | + 0x096d5, | ||
141 | + 0x092e0, // 1990-1999 | ||
142 | + 0x0c960, | ||
143 | + 0x0d954, | ||
144 | + 0x0d4a0, | ||
145 | + 0x0da50, | ||
146 | + 0x07552, | ||
147 | + 0x056a0, | ||
148 | + 0x0abb7, | ||
149 | + 0x025d0, | ||
150 | + 0x092d0, | ||
151 | + 0x0cab5, // 2000-2009 | ||
152 | + 0x0a950, | ||
153 | + 0x0b4a0, | ||
154 | + 0x0baa4, | ||
155 | + 0x0ad50, | ||
156 | + 0x055d9, | ||
157 | + 0x04ba0, | ||
158 | + 0x0a5b0, | ||
159 | + 0x15176, | ||
160 | + 0x052b0, | ||
161 | + 0x0a930, // 2010-2019 | ||
162 | + 0x07954, | ||
163 | + 0x06aa0, | ||
164 | + 0x0ad50, | ||
165 | + 0x05b52, | ||
166 | + 0x04b60, | ||
167 | + 0x0a6e6, | ||
168 | + 0x0a4e0, | ||
169 | + 0x0d260, | ||
170 | + 0x0ea65, | ||
171 | + 0x0d530, // 2020-2029 | ||
172 | + 0x05aa0, | ||
173 | + 0x076a3, | ||
174 | + 0x096d0, | ||
175 | + 0x04afb, | ||
176 | + 0x04ad0, | ||
177 | + 0x0a4d0, | ||
178 | + 0x1d0b6, | ||
179 | + 0x0d250, | ||
180 | + 0x0d520, | ||
181 | + 0x0dd45, // 2030-2039 | ||
182 | + 0x0b5a0, | ||
183 | + 0x056d0, | ||
184 | + 0x055b2, | ||
185 | + 0x049b0, | ||
186 | + 0x0a577, | ||
187 | + 0x0a4b0, | ||
188 | + 0x0aa50, | ||
189 | + 0x1b255, | ||
190 | + 0x06d20, | ||
191 | + 0x0ada0, // 2040-2049 | ||
192 | + /** Add By JJonline@JJonline.Cn **/ | ||
193 | + 0x14b63, | ||
194 | + 0x09370, | ||
195 | + 0x049f8, | ||
196 | + 0x04970, | ||
197 | + 0x064b0, | ||
198 | + 0x168a6, | ||
199 | + 0x0ea50, | ||
200 | + 0x06b20, | ||
201 | + 0x1a6c4, | ||
202 | + 0x0aae0, // 2050-2059 | ||
203 | + 0x0a2e0, | ||
204 | + 0x0d2e3, | ||
205 | + 0x0c960, | ||
206 | + 0x0d557, | ||
207 | + 0x0d4a0, | ||
208 | + 0x0da50, | ||
209 | + 0x05d55, | ||
210 | + 0x056a0, | ||
211 | + 0x0a6d0, | ||
212 | + 0x055d4, // 2060-2069 | ||
213 | + 0x052d0, | ||
214 | + 0x0a9b8, | ||
215 | + 0x0a950, | ||
216 | + 0x0b4a0, | ||
217 | + 0x0b6a6, | ||
218 | + 0x0ad50, | ||
219 | + 0x055a0, | ||
220 | + 0x0aba4, | ||
221 | + 0x0a5b0, | ||
222 | + 0x052b0, // 2070-2079 | ||
223 | + 0x0b273, | ||
224 | + 0x06930, | ||
225 | + 0x07337, | ||
226 | + 0x06aa0, | ||
227 | + 0x0ad50, | ||
228 | + 0x14b55, | ||
229 | + 0x04b60, | ||
230 | + 0x0a570, | ||
231 | + 0x054e4, | ||
232 | + 0x0d160, // 2080-2089 | ||
233 | + 0x0e968, | ||
234 | + 0x0d520, | ||
235 | + 0x0daa0, | ||
236 | + 0x16aa6, | ||
237 | + 0x056d0, | ||
238 | + 0x04ae0, | ||
239 | + 0x0a9d4, | ||
240 | + 0x0a2d0, | ||
241 | + 0x0d150, | ||
242 | + 0x0f252, // 2090-2099 | ||
243 | + 0x0d520 | ||
244 | + ], // 2100 | ||
245 | + | ||
246 | + /** | ||
247 | + * 公历每个月份的天数普通表 | ||
248 | + * @Array Of Property | ||
249 | + * @return Number | ||
250 | + */ | ||
251 | + solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], | ||
252 | + | ||
253 | + /** | ||
254 | + * 天干地支之天干速查表 | ||
255 | + * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"] | ||
256 | + * @return Cn string | ||
257 | + */ | ||
258 | + Gan: [ | ||
259 | + '\u7532', | ||
260 | + '\u4e59', | ||
261 | + '\u4e19', | ||
262 | + '\u4e01', | ||
263 | + '\u620a', | ||
264 | + '\u5df1', | ||
265 | + '\u5e9a', | ||
266 | + '\u8f9b', | ||
267 | + '\u58ec', | ||
268 | + '\u7678' | ||
269 | + ], | ||
270 | + | ||
271 | + /** | ||
272 | + * 天干地支之地支速查表 | ||
273 | + * @Array Of Property | ||
274 | + * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"] | ||
275 | + * @return Cn string | ||
276 | + */ | ||
277 | + Zhi: [ | ||
278 | + '\u5b50', | ||
279 | + '\u4e11', | ||
280 | + '\u5bc5', | ||
281 | + '\u536f', | ||
282 | + '\u8fb0', | ||
283 | + '\u5df3', | ||
284 | + '\u5348', | ||
285 | + '\u672a', | ||
286 | + '\u7533', | ||
287 | + '\u9149', | ||
288 | + '\u620c', | ||
289 | + '\u4ea5' | ||
290 | + ], | ||
291 | + | ||
292 | + /** | ||
293 | + * 天干地支之地支速查表<=>生肖 | ||
294 | + * @Array Of Property | ||
295 | + * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"] | ||
296 | + * @return Cn string | ||
297 | + */ | ||
298 | + Animals: [ | ||
299 | + '\u9f20', | ||
300 | + '\u725b', | ||
301 | + '\u864e', | ||
302 | + '\u5154', | ||
303 | + '\u9f99', | ||
304 | + '\u86c7', | ||
305 | + '\u9a6c', | ||
306 | + '\u7f8a', | ||
307 | + '\u7334', | ||
308 | + '\u9e21', | ||
309 | + '\u72d7', | ||
310 | + '\u732a' | ||
311 | + ], | ||
312 | + | ||
313 | + /** | ||
314 | + * 24节气速查表 | ||
315 | + * @Array Of Property | ||
316 | + * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"] | ||
317 | + * @return Cn string | ||
318 | + */ | ||
319 | + solarTerm: [ | ||
320 | + '\u5c0f\u5bd2', | ||
321 | + '\u5927\u5bd2', | ||
322 | + '\u7acb\u6625', | ||
323 | + '\u96e8\u6c34', | ||
324 | + '\u60ca\u86f0', | ||
325 | + '\u6625\u5206', | ||
326 | + '\u6e05\u660e', | ||
327 | + '\u8c37\u96e8', | ||
328 | + '\u7acb\u590f', | ||
329 | + '\u5c0f\u6ee1', | ||
330 | + '\u8292\u79cd', | ||
331 | + '\u590f\u81f3', | ||
332 | + '\u5c0f\u6691', | ||
333 | + '\u5927\u6691', | ||
334 | + '\u7acb\u79cb', | ||
335 | + '\u5904\u6691', | ||
336 | + '\u767d\u9732', | ||
337 | + '\u79cb\u5206', | ||
338 | + '\u5bd2\u9732', | ||
339 | + '\u971c\u964d', | ||
340 | + '\u7acb\u51ac', | ||
341 | + '\u5c0f\u96ea', | ||
342 | + '\u5927\u96ea', | ||
343 | + '\u51ac\u81f3' | ||
344 | + ], | ||
345 | + | ||
346 | + /** | ||
347 | + * 1900-2100各年的24节气日期速查表 | ||
348 | + * @Array Of Property | ||
349 | + * @return 0x string For splice | ||
350 | + */ | ||
351 | + sTermInfo: [ | ||
352 | + '9778397bd097c36b0b6fc9274c91aa', | ||
353 | + '97b6b97bd19801ec9210c965cc920e', | ||
354 | + '97bcf97c3598082c95f8c965cc920f', | ||
355 | + '97bd0b06bdb0722c965ce1cfcc920f', | ||
356 | + 'b027097bd097c36b0b6fc9274c91aa', | ||
357 | + '97b6b97bd19801ec9210c965cc920e', | ||
358 | + '97bcf97c359801ec95f8c965cc920f', | ||
359 | + '97bd0b06bdb0722c965ce1cfcc920f', | ||
360 | + 'b027097bd097c36b0b6fc9274c91aa', | ||
361 | + '97b6b97bd19801ec9210c965cc920e', | ||
362 | + '97bcf97c359801ec95f8c965cc920f', | ||
363 | + '97bd0b06bdb0722c965ce1cfcc920f', | ||
364 | + 'b027097bd097c36b0b6fc9274c91aa', | ||
365 | + '9778397bd19801ec9210c965cc920e', | ||
366 | + '97b6b97bd19801ec95f8c965cc920f', | ||
367 | + '97bd09801d98082c95f8e1cfcc920f', | ||
368 | + '97bd097bd097c36b0b6fc9210c8dc2', | ||
369 | + '9778397bd197c36c9210c9274c91aa', | ||
370 | + '97b6b97bd19801ec95f8c965cc920e', | ||
371 | + '97bd09801d98082c95f8e1cfcc920f', | ||
372 | + '97bd097bd097c36b0b6fc9210c8dc2', | ||
373 | + '9778397bd097c36c9210c9274c91aa', | ||
374 | + '97b6b97bd19801ec95f8c965cc920e', | ||
375 | + '97bcf97c3598082c95f8e1cfcc920f', | ||
376 | + '97bd097bd097c36b0b6fc9210c8dc2', | ||
377 | + '9778397bd097c36c9210c9274c91aa', | ||
378 | + '97b6b97bd19801ec9210c965cc920e', | ||
379 | + '97bcf97c3598082c95f8c965cc920f', | ||
380 | + '97bd097bd097c35b0b6fc920fb0722', | ||
381 | + '9778397bd097c36b0b6fc9274c91aa', | ||
382 | + '97b6b97bd19801ec9210c965cc920e', | ||
383 | + '97bcf97c3598082c95f8c965cc920f', | ||
384 | + '97bd097bd097c35b0b6fc920fb0722', | ||
385 | + '9778397bd097c36b0b6fc9274c91aa', | ||
386 | + '97b6b97bd19801ec9210c965cc920e', | ||
387 | + '97bcf97c359801ec95f8c965cc920f', | ||
388 | + '97bd097bd097c35b0b6fc920fb0722', | ||
389 | + '9778397bd097c36b0b6fc9274c91aa', | ||
390 | + '97b6b97bd19801ec9210c965cc920e', | ||
391 | + '97bcf97c359801ec95f8c965cc920f', | ||
392 | + '97bd097bd097c35b0b6fc920fb0722', | ||
393 | + '9778397bd097c36b0b6fc9274c91aa', | ||
394 | + '97b6b97bd19801ec9210c965cc920e', | ||
395 | + '97bcf97c359801ec95f8c965cc920f', | ||
396 | + '97bd097bd07f595b0b6fc920fb0722', | ||
397 | + '9778397bd097c36b0b6fc9210c8dc2', | ||
398 | + '9778397bd19801ec9210c9274c920e', | ||
399 | + '97b6b97bd19801ec95f8c965cc920f', | ||
400 | + '97bd07f5307f595b0b0bc920fb0722', | ||
401 | + '7f0e397bd097c36b0b6fc9210c8dc2', | ||
402 | + '9778397bd097c36c9210c9274c920e', | ||
403 | + '97b6b97bd19801ec95f8c965cc920f', | ||
404 | + '97bd07f5307f595b0b0bc920fb0722', | ||
405 | + '7f0e397bd097c36b0b6fc9210c8dc2', | ||
406 | + '9778397bd097c36c9210c9274c91aa', | ||
407 | + '97b6b97bd19801ec9210c965cc920e', | ||
408 | + '97bd07f1487f595b0b0bc920fb0722', | ||
409 | + '7f0e397bd097c36b0b6fc9210c8dc2', | ||
410 | + '9778397bd097c36b0b6fc9274c91aa', | ||
411 | + '97b6b97bd19801ec9210c965cc920e', | ||
412 | + '97bcf7f1487f595b0b0bb0b6fb0722', | ||
413 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
414 | + '9778397bd097c36b0b6fc9274c91aa', | ||
415 | + '97b6b97bd19801ec9210c965cc920e', | ||
416 | + '97bcf7f1487f595b0b0bb0b6fb0722', | ||
417 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
418 | + '9778397bd097c36b0b6fc9274c91aa', | ||
419 | + '97b6b97bd19801ec9210c965cc920e', | ||
420 | + '97bcf7f1487f531b0b0bb0b6fb0722', | ||
421 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
422 | + '9778397bd097c36b0b6fc9274c91aa', | ||
423 | + '97b6b97bd19801ec9210c965cc920e', | ||
424 | + '97bcf7f1487f531b0b0bb0b6fb0722', | ||
425 | + '7f0e397bd07f595b0b6fc920fb0722', | ||
426 | + '9778397bd097c36b0b6fc9274c91aa', | ||
427 | + '97b6b97bd19801ec9210c9274c920e', | ||
428 | + '97bcf7f0e47f531b0b0bb0b6fb0722', | ||
429 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
430 | + '9778397bd097c36b0b6fc9210c91aa', | ||
431 | + '97b6b97bd197c36c9210c9274c920e', | ||
432 | + '97bcf7f0e47f531b0b0bb0b6fb0722', | ||
433 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
434 | + '9778397bd097c36b0b6fc9210c8dc2', | ||
435 | + '9778397bd097c36c9210c9274c920e', | ||
436 | + '97b6b7f0e47f531b0723b0b6fb0722', | ||
437 | + '7f0e37f5307f595b0b0bc920fb0722', | ||
438 | + '7f0e397bd097c36b0b6fc9210c8dc2', | ||
439 | + '9778397bd097c36b0b70c9274c91aa', | ||
440 | + '97b6b7f0e47f531b0723b0b6fb0721', | ||
441 | + '7f0e37f1487f595b0b0bb0b6fb0722', | ||
442 | + '7f0e397bd097c35b0b6fc9210c8dc2', | ||
443 | + '9778397bd097c36b0b6fc9274c91aa', | ||
444 | + '97b6b7f0e47f531b0723b0b6fb0721', | ||
445 | + '7f0e27f1487f595b0b0bb0b6fb0722', | ||
446 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
447 | + '9778397bd097c36b0b6fc9274c91aa', | ||
448 | + '97b6b7f0e47f531b0723b0b6fb0721', | ||
449 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
450 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
451 | + '9778397bd097c36b0b6fc9274c91aa', | ||
452 | + '97b6b7f0e47f531b0723b0b6fb0721', | ||
453 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
454 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
455 | + '9778397bd097c36b0b6fc9274c91aa', | ||
456 | + '97b6b7f0e47f531b0723b0b6fb0721', | ||
457 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
458 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
459 | + '9778397bd097c36b0b6fc9274c91aa', | ||
460 | + '97b6b7f0e47f531b0723b0787b0721', | ||
461 | + '7f0e27f0e47f531b0b0bb0b6fb0722', | ||
462 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
463 | + '9778397bd097c36b0b6fc9210c91aa', | ||
464 | + '97b6b7f0e47f149b0723b0787b0721', | ||
465 | + '7f0e27f0e47f531b0723b0b6fb0722', | ||
466 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
467 | + '9778397bd097c36b0b6fc9210c8dc2', | ||
468 | + '977837f0e37f149b0723b0787b0721', | ||
469 | + '7f07e7f0e47f531b0723b0b6fb0722', | ||
470 | + '7f0e37f5307f595b0b0bc920fb0722', | ||
471 | + '7f0e397bd097c35b0b6fc9210c8dc2', | ||
472 | + '977837f0e37f14998082b0787b0721', | ||
473 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
474 | + '7f0e37f1487f595b0b0bb0b6fb0722', | ||
475 | + '7f0e397bd097c35b0b6fc9210c8dc2', | ||
476 | + '977837f0e37f14998082b0787b06bd', | ||
477 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
478 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
479 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
480 | + '977837f0e37f14998082b0787b06bd', | ||
481 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
482 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
483 | + '7f0e397bd097c35b0b6fc920fb0722', | ||
484 | + '977837f0e37f14998082b0787b06bd', | ||
485 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
486 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
487 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
488 | + '977837f0e37f14998082b0787b06bd', | ||
489 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
490 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
491 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
492 | + '977837f0e37f14998082b0787b06bd', | ||
493 | + '7f07e7f0e47f149b0723b0787b0721', | ||
494 | + '7f0e27f0e47f531b0b0bb0b6fb0722', | ||
495 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
496 | + '977837f0e37f14998082b0723b06bd', | ||
497 | + '7f07e7f0e37f149b0723b0787b0721', | ||
498 | + '7f0e27f0e47f531b0723b0b6fb0722', | ||
499 | + '7f0e397bd07f595b0b0bc920fb0722', | ||
500 | + '977837f0e37f14898082b0723b02d5', | ||
501 | + '7ec967f0e37f14998082b0787b0721', | ||
502 | + '7f07e7f0e47f531b0723b0b6fb0722', | ||
503 | + '7f0e37f1487f595b0b0bb0b6fb0722', | ||
504 | + '7f0e37f0e37f14898082b0723b02d5', | ||
505 | + '7ec967f0e37f14998082b0787b0721', | ||
506 | + '7f07e7f0e47f531b0723b0b6fb0722', | ||
507 | + '7f0e37f1487f531b0b0bb0b6fb0722', | ||
508 | + '7f0e37f0e37f14898082b0723b02d5', | ||
509 | + '7ec967f0e37f14998082b0787b06bd', | ||
510 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
511 | + '7f0e37f1487f531b0b0bb0b6fb0722', | ||
512 | + '7f0e37f0e37f14898082b072297c35', | ||
513 | + '7ec967f0e37f14998082b0787b06bd', | ||
514 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
515 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
516 | + '7f0e37f0e37f14898082b072297c35', | ||
517 | + '7ec967f0e37f14998082b0787b06bd', | ||
518 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
519 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
520 | + '7f0e37f0e366aa89801eb072297c35', | ||
521 | + '7ec967f0e37f14998082b0787b06bd', | ||
522 | + '7f07e7f0e47f149b0723b0787b0721', | ||
523 | + '7f0e27f1487f531b0b0bb0b6fb0722', | ||
524 | + '7f0e37f0e366aa89801eb072297c35', | ||
525 | + '7ec967f0e37f14998082b0723b06bd', | ||
526 | + '7f07e7f0e47f149b0723b0787b0721', | ||
527 | + '7f0e27f0e47f531b0723b0b6fb0722', | ||
528 | + '7f0e37f0e366aa89801eb072297c35', | ||
529 | + '7ec967f0e37f14998082b0723b06bd', | ||
530 | + '7f07e7f0e37f14998083b0787b0721', | ||
531 | + '7f0e27f0e47f531b0723b0b6fb0722', | ||
532 | + '7f0e37f0e366aa89801eb072297c35', | ||
533 | + '7ec967f0e37f14898082b0723b02d5', | ||
534 | + '7f07e7f0e37f14998082b0787b0721', | ||
535 | + '7f07e7f0e47f531b0723b0b6fb0722', | ||
536 | + '7f0e36665b66aa89801e9808297c35', | ||
537 | + '665f67f0e37f14898082b0723b02d5', | ||
538 | + '7ec967f0e37f14998082b0787b0721', | ||
539 | + '7f07e7f0e47f531b0723b0b6fb0722', | ||
540 | + '7f0e36665b66a449801e9808297c35', | ||
541 | + '665f67f0e37f14898082b0723b02d5', | ||
542 | + '7ec967f0e37f14998082b0787b06bd', | ||
543 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
544 | + '7f0e36665b66a449801e9808297c35', | ||
545 | + '665f67f0e37f14898082b072297c35', | ||
546 | + '7ec967f0e37f14998082b0787b06bd', | ||
547 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
548 | + '7f0e26665b66a449801e9808297c35', | ||
549 | + '665f67f0e37f1489801eb072297c35', | ||
550 | + '7ec967f0e37f14998082b0787b06bd', | ||
551 | + '7f07e7f0e47f531b0723b0b6fb0721', | ||
552 | + '7f0e27f1487f531b0b0bb0b6fb0722' | ||
553 | + ], | ||
554 | + | ||
555 | + /** | ||
556 | + * 数字转中文速查表 | ||
557 | + * @Array Of Property | ||
558 | + * @trans ['日','一','二','三','四','五','六','七','八','九','十'] | ||
559 | + * @return Cn string | ||
560 | + */ | ||
561 | + nStr1: [ | ||
562 | + '\u65e5', | ||
563 | + '\u4e00', | ||
564 | + '\u4e8c', | ||
565 | + '\u4e09', | ||
566 | + '\u56db', | ||
567 | + '\u4e94', | ||
568 | + '\u516d', | ||
569 | + '\u4e03', | ||
570 | + '\u516b', | ||
571 | + '\u4e5d', | ||
572 | + '\u5341' | ||
573 | + ], | ||
574 | + | ||
575 | + /** | ||
576 | + * 日期转农历称呼速查表 | ||
577 | + * @Array Of Property | ||
578 | + * @trans ['初','十','廿','卅'] | ||
579 | + * @return Cn string | ||
580 | + */ | ||
581 | + nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'], | ||
582 | + | ||
583 | + /** | ||
584 | + * 月份转农历称呼速查表 | ||
585 | + * @Array Of Property | ||
586 | + * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊'] | ||
587 | + * @return Cn string | ||
588 | + */ | ||
589 | + nStr3: [ | ||
590 | + '\u6b63', | ||
591 | + '\u4e8c', | ||
592 | + '\u4e09', | ||
593 | + '\u56db', | ||
594 | + '\u4e94', | ||
595 | + '\u516d', | ||
596 | + '\u4e03', | ||
597 | + '\u516b', | ||
598 | + '\u4e5d', | ||
599 | + '\u5341', | ||
600 | + '\u51ac', | ||
601 | + '\u814a' | ||
602 | + ], | ||
603 | + | ||
604 | + /** | ||
605 | + * 返回农历y年一整年的总天数 | ||
606 | + * @param lunar Year | ||
607 | + * @return Number | ||
608 | + * @eg:var count = calendar.lYearDays(1987) ;//count=387 | ||
609 | + */ | ||
610 | + lYearDays: function(y) { | ||
611 | + let i | ||
612 | + let sum = 348 | ||
613 | + for (i = 0x8000; i > 0x8; i >>= 1) { | ||
614 | + sum += calendar.lunarInfo[y - 1900] & i ? 1 : 0 | ||
615 | + } | ||
616 | + return sum + calendar.leapDays(y) | ||
617 | + }, | ||
618 | + | ||
619 | + /** | ||
620 | + * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0 | ||
621 | + * @param lunar Year | ||
622 | + * @return Number (0-12) | ||
623 | + * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6 | ||
624 | + */ | ||
625 | + leapMonth: function(y) { | ||
626 | + // 闰字编码 \u95f0 | ||
627 | + return calendar.lunarInfo[y - 1900] & 0xf | ||
628 | + }, | ||
629 | + | ||
630 | + /** | ||
631 | + * 返回农历y年闰月的天数 若该年没有闰月则返回0 | ||
632 | + * @param lunar Year | ||
633 | + * @return Number (0、29、30) | ||
634 | + * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29 | ||
635 | + */ | ||
636 | + leapDays: function(y) { | ||
637 | + if (calendar.leapMonth(y)) { | ||
638 | + return calendar.lunarInfo[y - 1900] & 0x10000 ? 30 : 29 | ||
639 | + } | ||
640 | + return 0 | ||
641 | + }, | ||
642 | + | ||
643 | + /** | ||
644 | + * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法 | ||
645 | + * @param lunar Year | ||
646 | + * @return Number (-1、29、30) | ||
647 | + * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29 | ||
648 | + */ | ||
649 | + monthDays: function(y, m) { | ||
650 | + if (m > 12 || m < 1) return -1 // 月份参数从1至12,参数错误返回-1 | ||
651 | + return calendar.lunarInfo[y - 1900] & (0x10000 >> m) ? 30 : 29 | ||
652 | + }, | ||
653 | + | ||
654 | + /** | ||
655 | + * 返回公历(!)y年m月的天数 | ||
656 | + * @param solar Year | ||
657 | + * @return Number (-1、28、29、30、31) | ||
658 | + * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30 | ||
659 | + */ | ||
660 | + solarDays: function(y, m) { | ||
661 | + if (m > 12 || m < 1) return -1 // 若参数错误 返回-1 | ||
662 | + const ms = m - 1 | ||
663 | + if (+ms === 1) { | ||
664 | + // 2月份的闰平规律测算后确认返回28或29 | ||
665 | + return (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0 ? 29 : 28 | ||
666 | + } else { | ||
667 | + return calendar.solarMonth[ms] | ||
668 | + } | ||
669 | + }, | ||
670 | + | ||
671 | + /** | ||
672 | + * 农历年份转换为干支纪年 | ||
673 | + * @param lYear 农历年的年份数 | ||
674 | + * @return Cn string | ||
675 | + */ | ||
676 | + toGanZhiYear: function(lYear) { | ||
677 | + let ganKey = (lYear - 3) % 10 | ||
678 | + let zhiKey = (lYear - 3) % 12 | ||
679 | + if (+ganKey === 0) ganKey = 10 // 如果余数为0则为最后一个天干 | ||
680 | + if (+zhiKey === 0) zhiKey = 12 // 如果余数为0则为最后一个地支 | ||
681 | + return calendar.Gan[ganKey - 1] + calendar.Zhi[zhiKey - 1] | ||
682 | + }, | ||
683 | + | ||
684 | + /** | ||
685 | + * 公历月、日判断所属星座 | ||
686 | + * @param cMonth [description] | ||
687 | + * @param cDay [description] | ||
688 | + * @return Cn string | ||
689 | + */ | ||
690 | + toAstro: function(cMonth, cDay) { | ||
691 | + const s = | ||
692 | + '\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' | ||
693 | + const arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22] | ||
694 | + return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7' // 座 | ||
695 | + }, | ||
696 | + | ||
697 | + /** | ||
698 | + * 传入offset偏移量返回干支 | ||
699 | + * @param offset 相对甲子的偏移量 | ||
700 | + * @return Cn string | ||
701 | + */ | ||
702 | + toGanZhi: function(offset) { | ||
703 | + return calendar.Gan[offset % 10] + calendar.Zhi[offset % 12] | ||
704 | + }, | ||
705 | + | ||
706 | + /** | ||
707 | + * 传入公历(!)y年获得该年第n个节气的公历日期 | ||
708 | + * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起 | ||
709 | + * @return day Number | ||
710 | + * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春 | ||
711 | + */ | ||
712 | + getTerm: function(y, n) { | ||
713 | + if (y < 1900 || y > 2100) return -1 | ||
714 | + if (n < 1 || n > 24) return -1 | ||
715 | + const _table = calendar.sTermInfo[y - 1900] | ||
716 | + const _info = [ | ||
717 | + parseInt('0x' + _table.substr(0, 5)).toString(), | ||
718 | + parseInt('0x' + _table.substr(5, 5)).toString(), | ||
719 | + parseInt('0x' + _table.substr(10, 5)).toString(), | ||
720 | + parseInt('0x' + _table.substr(15, 5)).toString(), | ||
721 | + parseInt('0x' + _table.substr(20, 5)).toString(), | ||
722 | + parseInt('0x' + _table.substr(25, 5)).toString() | ||
723 | + ] | ||
724 | + const _calday = [ | ||
725 | + _info[0].substr(0, 1), | ||
726 | + _info[0].substr(1, 2), | ||
727 | + _info[0].substr(3, 1), | ||
728 | + _info[0].substr(4, 2), | ||
729 | + | ||
730 | + _info[1].substr(0, 1), | ||
731 | + _info[1].substr(1, 2), | ||
732 | + _info[1].substr(3, 1), | ||
733 | + _info[1].substr(4, 2), | ||
734 | + | ||
735 | + _info[2].substr(0, 1), | ||
736 | + _info[2].substr(1, 2), | ||
737 | + _info[2].substr(3, 1), | ||
738 | + _info[2].substr(4, 2), | ||
739 | + | ||
740 | + _info[3].substr(0, 1), | ||
741 | + _info[3].substr(1, 2), | ||
742 | + _info[3].substr(3, 1), | ||
743 | + _info[3].substr(4, 2), | ||
744 | + | ||
745 | + _info[4].substr(0, 1), | ||
746 | + _info[4].substr(1, 2), | ||
747 | + _info[4].substr(3, 1), | ||
748 | + _info[4].substr(4, 2), | ||
749 | + | ||
750 | + _info[5].substr(0, 1), | ||
751 | + _info[5].substr(1, 2), | ||
752 | + _info[5].substr(3, 1), | ||
753 | + _info[5].substr(4, 2) | ||
754 | + ] | ||
755 | + return parseInt(_calday[n - 1]) | ||
756 | + }, | ||
757 | + | ||
758 | + /** | ||
759 | + * 传入农历数字月份返回汉语通俗表示法 | ||
760 | + * @param lunar month | ||
761 | + * @return Cn string | ||
762 | + * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月' | ||
763 | + */ | ||
764 | + toChinaMonth: function(m) { | ||
765 | + // 月 => \u6708 | ||
766 | + if (m > 12 || m < 1) return -1 // 若参数错误 返回-1 | ||
767 | + let s = calendar.nStr3[m - 1] | ||
768 | + s += '\u6708' // 加上月字 | ||
769 | + return s | ||
770 | + }, | ||
771 | + | ||
772 | + /** | ||
773 | + * 传入农历日期数字返回汉字表示法 | ||
774 | + * @param lunar day | ||
775 | + * @return Cn string | ||
776 | + * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一' | ||
777 | + */ | ||
778 | + toChinaDay: function(d) { | ||
779 | + // 日 => \u65e5 | ||
780 | + let s | ||
781 | + switch (d) { | ||
782 | + case 10: | ||
783 | + s = '\u521d\u5341' | ||
784 | + break | ||
785 | + case 20: | ||
786 | + s = '\u4e8c\u5341' | ||
787 | + break | ||
788 | + case 30: | ||
789 | + s = '\u4e09\u5341' | ||
790 | + break | ||
791 | + default: | ||
792 | + s = calendar.nStr2[Math.floor(d / 10)] | ||
793 | + s += calendar.nStr1[d % 10] | ||
794 | + } | ||
795 | + return s | ||
796 | + }, | ||
797 | + | ||
798 | + /** | ||
799 | + * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春” | ||
800 | + * @param y year | ||
801 | + * @return Cn string | ||
802 | + * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔' | ||
803 | + */ | ||
804 | + getAnimal: function(y) { | ||
805 | + return calendar.Animals[(y - 4) % 12] | ||
806 | + }, | ||
807 | + | ||
808 | + /** | ||
809 | + * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON | ||
810 | + * @param y solar year | ||
811 | + * @param m solar month | ||
812 | + * @param d solar day | ||
813 | + * @return JSON object | ||
814 | + * @eg:console.log(calendar.solar2lunar(1987,11,01)); | ||
815 | + */ | ||
816 | + solar2lunar: function(y, m, d) { | ||
817 | + // 参数区间1900.1.31~2100.12.31 | ||
818 | + // 年份限定、上限 | ||
819 | + if (y < 1900 || y > 2100) { | ||
820 | + return -1 // undefined转换为数字变为NaN | ||
821 | + } | ||
822 | + // 公历传参最下限 | ||
823 | + if (+y === 1900 && +m === 1 && +d < 31) { | ||
824 | + return -1 | ||
825 | + } | ||
826 | + // 未传参 获得当天 | ||
827 | + let objDate | ||
828 | + if (!y) { | ||
829 | + objDate = new Date() | ||
830 | + } else { | ||
831 | + objDate = new Date(y, parseInt(m) - 1, d) | ||
832 | + } | ||
833 | + let i | ||
834 | + let leap = 0 | ||
835 | + let temp = 0 | ||
836 | + // 修正ymd参数 | ||
837 | + y = objDate.getFullYear() | ||
838 | + m = objDate.getMonth() + 1 | ||
839 | + d = objDate.getDate() | ||
840 | + let offset = | ||
841 | + (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - | ||
842 | + Date.UTC(1900, 0, 31)) / | ||
843 | + 86400000 | ||
844 | + for (i = 1900; i < 2101 && offset > 0; i++) { | ||
845 | + temp = calendar.lYearDays(i) | ||
846 | + offset -= temp | ||
847 | + } | ||
848 | + if (offset < 0) { | ||
849 | + offset += temp | ||
850 | + i-- | ||
851 | + } | ||
852 | + | ||
853 | + // 是否今天 | ||
854 | + const isTodayObj = new Date() | ||
855 | + let isToday = false | ||
856 | + if ( | ||
857 | + isTodayObj.getFullYear() === +y && | ||
858 | + isTodayObj.getMonth() + 1 === +m && | ||
859 | + isTodayObj.getDate() === +d | ||
860 | + ) { | ||
861 | + isToday = true | ||
862 | + } | ||
863 | + // 星期几 | ||
864 | + let nWeek = objDate.getDay() | ||
865 | + const cWeek = calendar.nStr1[nWeek] | ||
866 | + // 数字表示周几顺应天朝周一开始的惯例 | ||
867 | + if (+nWeek === 0) { | ||
868 | + nWeek = 7 | ||
869 | + } | ||
870 | + // 农历年 | ||
871 | + const year = i | ||
872 | + leap = calendar.leapMonth(i) // 闰哪个月 | ||
873 | + let isLeap = false | ||
874 | + | ||
875 | + // 效验闰月 | ||
876 | + for (i = 1; i < 13 && offset > 0; i++) { | ||
877 | + // 闰月 | ||
878 | + if (leap > 0 && i === leap + 1 && isLeap === false) { | ||
879 | + --i | ||
880 | + isLeap = true | ||
881 | + temp = calendar.leapDays(year) // 计算农历闰月天数 | ||
882 | + } else { | ||
883 | + temp = calendar.monthDays(year, i) // 计算农历普通月天数 | ||
884 | + } | ||
885 | + // 解除闰月 | ||
886 | + if (isLeap === true && i === leap + 1) isLeap = false | ||
887 | + offset -= temp | ||
888 | + } | ||
889 | + // 闰月导致数组下标重叠取反 | ||
890 | + if (offset === 0 && leap > 0 && i === leap + 1) { | ||
891 | + if (isLeap) { | ||
892 | + isLeap = false | ||
893 | + } else { | ||
894 | + isLeap = true | ||
895 | + --i | ||
896 | + } | ||
897 | + } | ||
898 | + if (offset < 0) { | ||
899 | + offset += temp | ||
900 | + --i | ||
901 | + } | ||
902 | + // 农历月 | ||
903 | + const month = i | ||
904 | + // 农历日 | ||
905 | + const day = offset + 1 | ||
906 | + // 天干地支处理 | ||
907 | + const sm = m - 1 | ||
908 | + const gzY = calendar.toGanZhiYear(year) | ||
909 | + | ||
910 | + // 当月的两个节气 | ||
911 | + // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year` | ||
912 | + const firstNode = calendar.getTerm(y, m * 2 - 1) // 返回当月「节」为几日开始 | ||
913 | + const secondNode = calendar.getTerm(y, m * 2) // 返回当月「节」为几日开始 | ||
914 | + | ||
915 | + // 依据12节气修正干支月 | ||
916 | + let gzM = calendar.toGanZhi((y - 1900) * 12 + m + 11) | ||
917 | + if (d >= firstNode) { | ||
918 | + gzM = calendar.toGanZhi((y - 1900) * 12 + m + 12) | ||
919 | + } | ||
920 | + | ||
921 | + // 传入的日期的节气与否 | ||
922 | + let isTerm = false | ||
923 | + let Term = null | ||
924 | + if (+firstNode === d) { | ||
925 | + isTerm = true | ||
926 | + Term = calendar.solarTerm[m * 2 - 2] | ||
927 | + } | ||
928 | + if (+secondNode === d) { | ||
929 | + isTerm = true | ||
930 | + Term = calendar.solarTerm[m * 2 - 1] | ||
931 | + } | ||
932 | + // 日柱 当月一日与 1900/1/1 相差天数 | ||
933 | + const dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10 | ||
934 | + const gzD = calendar.toGanZhi(dayCyclical + d - 1) | ||
935 | + // 该日期所属的星座 | ||
936 | + const astro = calendar.toAstro(m, d) | ||
937 | + | ||
938 | + return { | ||
939 | + lYear: year, | ||
940 | + lMonth: month, | ||
941 | + lDay: day, | ||
942 | + Animal: calendar.getAnimal(year), | ||
943 | + IMonthCn: (isLeap ? '\u95f0' : '') + calendar.toChinaMonth(month), | ||
944 | + IDayCn: calendar.toChinaDay(day), | ||
945 | + cYear: y, | ||
946 | + cMonth: m, | ||
947 | + cDay: d, | ||
948 | + gzYear: gzY, | ||
949 | + gzMonth: gzM, | ||
950 | + gzDay: gzD, | ||
951 | + isToday: isToday, | ||
952 | + isLeap: isLeap, | ||
953 | + nWeek: nWeek, | ||
954 | + ncWeek: '\u661f\u671f' + cWeek, | ||
955 | + isTerm: isTerm, | ||
956 | + Term: Term, | ||
957 | + astro: astro | ||
958 | + } | ||
959 | + }, | ||
960 | + | ||
961 | + /** | ||
962 | + * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON | ||
963 | + * @param y lunar year | ||
964 | + * @param m lunar month | ||
965 | + * @param d lunar day | ||
966 | + * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可] | ||
967 | + * @return JSON object | ||
968 | + * @eg:console.log(calendar.lunar2solar(1987,9,10)); | ||
969 | + */ | ||
970 | + lunar2solar: function(y, m, d, isLeapMonth) { | ||
971 | + // 参数区间1900.1.31~2100.12.1 | ||
972 | + isLeapMonth = !!isLeapMonth | ||
973 | + // let leapOffset = 0; | ||
974 | + const leapMonth = calendar.leapMonth(y) | ||
975 | + // let leapDay = calendar.leapDays(y); | ||
976 | + if (isLeapMonth && leapMonth !== m) return -1 // 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同 | ||
977 | + if ( | ||
978 | + (+y === 2100 && +m === 12 && +d > 1) || | ||
979 | + (+y === 1900 && +m === 1 && +d < 31) | ||
980 | + ) | ||
981 | + return -1 // 超出了最大极限值 | ||
982 | + const day = calendar.monthDays(y, m) | ||
983 | + let _day = day | ||
984 | + // bugFix 2016-9-25 | ||
985 | + // if month is leap, _day use leapDays method | ||
986 | + if (isLeapMonth) { | ||
987 | + _day = calendar.leapDays(y, m) | ||
988 | + } | ||
989 | + if (y < 1900 || y > 2100 || d > _day) return -1 // 参数合法性效验 | ||
990 | + | ||
991 | + // 计算农历的时间差 | ||
992 | + let offset = 0 | ||
993 | + for (let i = 1900; i < y; i++) { | ||
994 | + offset += calendar.lYearDays(i) | ||
995 | + } | ||
996 | + let leap = 0 | ||
997 | + let isAdd = false | ||
998 | + for (let i = 1; i < m; i++) { | ||
999 | + leap = calendar.leapMonth(y) | ||
1000 | + if (!isAdd) { | ||
1001 | + // 处理闰月 | ||
1002 | + if (leap <= i && leap > 0) { | ||
1003 | + offset += calendar.leapDays(y) | ||
1004 | + isAdd = true | ||
1005 | + } | ||
1006 | + } | ||
1007 | + offset += calendar.monthDays(y, i) | ||
1008 | + } | ||
1009 | + // 转换闰月农历 需补充该年闰月的前一个月的时差 | ||
1010 | + if (isLeapMonth) offset += day | ||
1011 | + // 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点) | ||
1012 | + const stmap = Date.UTC(1900, 1, 30, 0, 0, 0) | ||
1013 | + const calObj = new Date((offset + d - 31) * 86400000 + stmap) | ||
1014 | + const cY = calObj.getUTCFullYear() | ||
1015 | + const cM = calObj.getUTCMonth() + 1 | ||
1016 | + const cD = calObj.getUTCDate() | ||
1017 | + | ||
1018 | + return calendar.solar2lunar(cY, cM, cD) | ||
1019 | + } | ||
1020 | +} | ||
1021 | + | ||
1022 | +const { | ||
1023 | + Gan, | ||
1024 | + Zhi, | ||
1025 | + nStr1, | ||
1026 | + nStr2, | ||
1027 | + nStr3, | ||
1028 | + Animals, | ||
1029 | + solarTerm, | ||
1030 | + lunarInfo, | ||
1031 | + sTermInfo, | ||
1032 | + solarMonth, | ||
1033 | + ...rest | ||
1034 | +} = calendar | ||
1035 | + | ||
1036 | +export default rest |
@@ -0,0 +1,59 @@ | @@ -0,0 +1,59 @@ | ||
1 | +import { dateUtil } from '../../utils/index' | ||
2 | +import convertSolarLunar from './convertSolarLunar' | ||
3 | + | ||
4 | +function getDateRow2Dict(dateInfo) { | ||
5 | + if (!dateInfo) return dateInfo | ||
6 | + if (typeof dateInfo === 'string' && dateInfo.includes('-')) { | ||
7 | + dateInfo = dateUtil.transformDateRow2Dict(dateInfo) | ||
8 | + } | ||
9 | + return dateInfo | ||
10 | +} | ||
11 | + | ||
12 | +export default () => { | ||
13 | + return { | ||
14 | + name: 'convertSolarLunar', | ||
15 | + beforeRender(calendarData = {}, calendarConfig = {}) { | ||
16 | + let { dates = [], selectedDates = [] } = calendarData | ||
17 | + if (calendarConfig.showLunar) { | ||
18 | + dates = dates.map(dataInfo => { | ||
19 | + const { year, month, date } = dataInfo | ||
20 | + return { | ||
21 | + ...dataInfo, | ||
22 | + lunar: convertSolarLunar.solar2lunar(year, month, date) | ||
23 | + } | ||
24 | + }) | ||
25 | + selectedDates = selectedDates.map(dataInfo => { | ||
26 | + const { year, month, date } = dataInfo | ||
27 | + return { | ||
28 | + ...dataInfo, | ||
29 | + lunar: convertSolarLunar.solar2lunar(year, month, date) | ||
30 | + } | ||
31 | + }) | ||
32 | + } | ||
33 | + return { | ||
34 | + calendarData: { | ||
35 | + ...calendarData, | ||
36 | + dates: dates, | ||
37 | + selectedDates: selectedDates | ||
38 | + }, | ||
39 | + calendarConfig | ||
40 | + } | ||
41 | + }, | ||
42 | + methods() { | ||
43 | + return { | ||
44 | + convertSolarLunar: dateInfo => { | ||
45 | + dateInfo = getDateRow2Dict(dateInfo) | ||
46 | + if (!dateInfo) return dateInfo | ||
47 | + const { year, month, date } = dateInfo | ||
48 | + return convertSolarLunar.solar2lunar(year, month, date) | ||
49 | + }, | ||
50 | + convertlLunar2Solar: (dateInfo, isLeapMonth) => { | ||
51 | + dateInfo = getDateRow2Dict(dateInfo) | ||
52 | + if (!dateInfo) return dateInfo | ||
53 | + const { year, month, date } = dateInfo | ||
54 | + return convertSolarLunar.lunar2solar(year, month, date, isLeapMonth) | ||
55 | + } | ||
56 | + } | ||
57 | + } | ||
58 | + } | ||
59 | +} |
@@ -0,0 +1,309 @@ | @@ -0,0 +1,309 @@ | ||
1 | +/** | ||
2 | + * @Author: drfu* | ||
3 | + * @Description: 时间区域选择 | ||
4 | + * @Date: 2020-10-08 21:22:09* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-11 13:56:32 | ||
7 | + * */ | ||
8 | + | ||
9 | +import { renderCalendar } from '../render' | ||
10 | +import { | ||
11 | + logger, | ||
12 | + dateUtil, | ||
13 | + getCalendarConfig, | ||
14 | + getCalendarData | ||
15 | +} from '../utils/index' | ||
16 | + | ||
17 | +function pusheNextMonthDateArea( | ||
18 | + dateInfo = {}, | ||
19 | + startTimestamp, | ||
20 | + endTimestamp, | ||
21 | + selectedDates = [] | ||
22 | +) { | ||
23 | + let tempOfSelectedDate = [...selectedDates] | ||
24 | + const dates = dateUtil.calcDates(dateInfo.year, dateInfo.month) | ||
25 | + let datesLen = dates.length | ||
26 | + for (let i = 0; i < datesLen; i++) { | ||
27 | + const date = dates[i] | ||
28 | + const timeStamp = dateUtil.getTimeStamp(date) | ||
29 | + if (timeStamp <= endTimestamp && timeStamp >= startTimestamp) { | ||
30 | + tempOfSelectedDate.push({ | ||
31 | + ...date, | ||
32 | + choosed: true | ||
33 | + }) | ||
34 | + } | ||
35 | + if (i === datesLen - 1 && timeStamp < endTimestamp) { | ||
36 | + tempOfSelectedDate = pusheNextMonthDateArea( | ||
37 | + dateUtil.getNextMonthInfo(date), | ||
38 | + startTimestamp, | ||
39 | + endTimestamp, | ||
40 | + tempOfSelectedDate | ||
41 | + ) | ||
42 | + } | ||
43 | + } | ||
44 | + return tempOfSelectedDate | ||
45 | +} | ||
46 | +function pushPrevMonthDateArea( | ||
47 | + dateInfo = {}, | ||
48 | + startTimestamp, | ||
49 | + endTimestamp, | ||
50 | + selectedDates = [] | ||
51 | +) { | ||
52 | + let tempOfSelectedDate = [...selectedDates] | ||
53 | + const dates = dateUtil.sortDatesByTime( | ||
54 | + dateUtil.calcDates(dateInfo.year, dateInfo.month), | ||
55 | + 'desc' | ||
56 | + ) | ||
57 | + let datesLen = dates.length | ||
58 | + let firstDate = dateUtil.getTimeStamp(dates[0]) | ||
59 | + for (let i = 0; i < datesLen; i++) { | ||
60 | + const date = dates[i] | ||
61 | + const timeStamp = dateUtil.getTimeStamp(date) | ||
62 | + if (timeStamp >= startTimestamp && timeStamp <= endTimestamp) { | ||
63 | + tempOfSelectedDate.push({ | ||
64 | + ...date, | ||
65 | + choosed: true | ||
66 | + }) | ||
67 | + } | ||
68 | + if (i === datesLen - 1 && firstDate > startTimestamp) { | ||
69 | + tempOfSelectedDate = pushPrevMonthDateArea( | ||
70 | + dateUtil.getPrevMonthInfo(date), | ||
71 | + startTimestamp, | ||
72 | + endTimestamp, | ||
73 | + tempOfSelectedDate | ||
74 | + ) | ||
75 | + } | ||
76 | + } | ||
77 | + return tempOfSelectedDate | ||
78 | +} | ||
79 | +/** | ||
80 | + * 当设置日期区域非当前时保存其他月份的日期至已选日期数组 | ||
81 | + * @param {object} info | ||
82 | + */ | ||
83 | +function calcDateWhenNotInOneMonth(info) { | ||
84 | + const { firstDate, lastDate, startTimestamp, endTimestamp } = info | ||
85 | + let { selectedDate } = info | ||
86 | + if (dateUtil.getTimeStamp(firstDate) > startTimestamp) { | ||
87 | + selectedDate = pushPrevMonthDateArea( | ||
88 | + dateUtil.getPrevMonthInfo(firstDate), | ||
89 | + startTimestamp, | ||
90 | + endTimestamp, | ||
91 | + selectedDate | ||
92 | + ) | ||
93 | + } | ||
94 | + if (dateUtil.getTimeStamp(lastDate) < endTimestamp) { | ||
95 | + selectedDate = pusheNextMonthDateArea( | ||
96 | + dateUtil.getNextMonthInfo(lastDate), | ||
97 | + startTimestamp, | ||
98 | + endTimestamp, | ||
99 | + selectedDate | ||
100 | + ) | ||
101 | + } | ||
102 | + return [...selectedDate] | ||
103 | +} | ||
104 | + | ||
105 | +/** | ||
106 | + * 指定日期区域转时间戳 | ||
107 | + * @param {array} timearea 时间区域 | ||
108 | + */ | ||
109 | +export function convertTimeRangeToTimestamp(timearea = []) { | ||
110 | + const start = timearea[0].split('-') | ||
111 | + const end = timearea[1].split('-') | ||
112 | + if (start.length !== 3 || end.length !== 3) { | ||
113 | + logger.warn('enableArea() 参数格式为: ["2018-2-1", "2018-3-1"]') | ||
114 | + return {} | ||
115 | + } | ||
116 | + const startTimestamp = dateUtil | ||
117 | + .newDate(start[0], start[1], start[2]) | ||
118 | + .getTime() | ||
119 | + const endTimestamp = dateUtil.newDate(end[0], end[1], end[2]).getTime() | ||
120 | + return { | ||
121 | + start, | ||
122 | + end, | ||
123 | + startTimestamp, | ||
124 | + endTimestamp | ||
125 | + } | ||
126 | +} | ||
127 | + | ||
128 | +/** | ||
129 | + * 校验时间区域是否合法 | ||
130 | + * @param {array} dateArea 时间区域 | ||
131 | + */ | ||
132 | +function validateTimeRange(dateArea) { | ||
133 | + const { | ||
134 | + start, | ||
135 | + end, | ||
136 | + startTimestamp, | ||
137 | + endTimestamp | ||
138 | + } = convertTimeRangeToTimestamp(dateArea) | ||
139 | + if (!start || !end) return | ||
140 | + const startMonthDays = dateUtil.getDatesCountOfMonth(start[0], start[1]) | ||
141 | + const endMonthDays = dateUtil.getDatesCountOfMonth(end[0], end[1]) | ||
142 | + if (start[2] > startMonthDays || start[2] < 1) { | ||
143 | + logger.warn('enableArea() 开始日期错误,指定日期不在当前月份天数范围内') | ||
144 | + return false | ||
145 | + } else if (start[1] > 12 || start[1] < 1) { | ||
146 | + logger.warn('enableArea() 开始日期错误,月份超出1-12月份') | ||
147 | + return false | ||
148 | + } else if (end[2] > endMonthDays || end[2] < 1) { | ||
149 | + logger.warn('enableArea() 截止日期错误,指定日期不在当前月份天数范围内') | ||
150 | + return false | ||
151 | + } else if (end[1] > 12 || end[1] < 1) { | ||
152 | + logger.warn('enableArea() 截止日期错误,月份超出1-12月份') | ||
153 | + return false | ||
154 | + } else if (startTimestamp > endTimestamp) { | ||
155 | + logger.warn('enableArea()参数最小日期大于了最大日期') | ||
156 | + return false | ||
157 | + } else { | ||
158 | + return true | ||
159 | + } | ||
160 | +} | ||
161 | + | ||
162 | +export default () => { | ||
163 | + return { | ||
164 | + name: 'timeRange', | ||
165 | + beforeRender(calendarData = {}, calendarConfig = {}) { | ||
166 | + const { | ||
167 | + chooseAreaTimestamp = [], | ||
168 | + dates = [], | ||
169 | + selectedDates = [] | ||
170 | + } = calendarData | ||
171 | + let __dates = dates | ||
172 | + let __selectedDates = selectedDates | ||
173 | + const [startDateTimestamp, endDateTimestamp] = chooseAreaTimestamp | ||
174 | + if (chooseAreaTimestamp.length === 2) { | ||
175 | + __selectedDates = [] | ||
176 | + __dates = dates.map(d => { | ||
177 | + const date = { ...d } | ||
178 | + const dateTimeStamp = dateUtil.getTimeStamp(date) | ||
179 | + if ( | ||
180 | + dateTimeStamp >= startDateTimestamp && | ||
181 | + endDateTimestamp >= dateTimeStamp | ||
182 | + ) { | ||
183 | + date.choosed = true | ||
184 | + __selectedDates.push(date) | ||
185 | + } else { | ||
186 | + date.choosed = false | ||
187 | + __selectedDates = __selectedDates.filter( | ||
188 | + item => dateUtil.getTimeStamp(item) !== dateTimeStamp | ||
189 | + ) | ||
190 | + } | ||
191 | + return date | ||
192 | + }) | ||
193 | + const { year: startYear, month: startMonth } = dateUtil.formatTimestamp( | ||
194 | + startDateTimestamp | ||
195 | + ) | ||
196 | + const { year: endYear, month: endMonth } = dateUtil.formatTimestamp( | ||
197 | + endDateTimestamp | ||
198 | + ) | ||
199 | + if (startMonth !== endMonth || startYear !== endYear) { | ||
200 | + __selectedDates = calcDateWhenNotInOneMonth({ | ||
201 | + firstDate: __dates[0], | ||
202 | + lastDate: __dates[__dates.length - 1], | ||
203 | + startTimestamp: startDateTimestamp, | ||
204 | + endTimestamp: endDateTimestamp, | ||
205 | + selectedDate: __selectedDates | ||
206 | + }) | ||
207 | + } | ||
208 | + } | ||
209 | + return { | ||
210 | + calendarData: { | ||
211 | + ...calendarData, | ||
212 | + dates: __dates, | ||
213 | + selectedDates: dateUtil.sortDatesByTime( | ||
214 | + dateUtil.uniqueArrayByDate(__selectedDates) | ||
215 | + ) | ||
216 | + }, | ||
217 | + calendarConfig | ||
218 | + } | ||
219 | + }, | ||
220 | + onTapDate(tapedDate, calendarData = {}, calendarConfig = {}) { | ||
221 | + if (!calendarConfig.chooseAreaMode) { | ||
222 | + return { | ||
223 | + calendarData, | ||
224 | + calendarConfig | ||
225 | + } | ||
226 | + } | ||
227 | + let { | ||
228 | + tempChooseAreaTimestamp = [], | ||
229 | + chooseAreaTimestamp: existChooseAreaTimestamp = [], | ||
230 | + selectedDates = [], | ||
231 | + dates = [] | ||
232 | + } = calendarData | ||
233 | + const timestamp = dateUtil.getTimeStamp(tapedDate) | ||
234 | + let __dates = [...dates] | ||
235 | + let __selectedDates = [...selectedDates] | ||
236 | + if ( | ||
237 | + tempChooseAreaTimestamp.length === 2 || | ||
238 | + existChooseAreaTimestamp.length === 2 | ||
239 | + ) { | ||
240 | + tempChooseAreaTimestamp = [tapedDate] | ||
241 | + __selectedDates = [] | ||
242 | + __dates.forEach(d => (d.choosed = false)) | ||
243 | + } else if (tempChooseAreaTimestamp.length === 1) { | ||
244 | + const preChoosedDate = tempChooseAreaTimestamp[0] | ||
245 | + const preTimestamp = dateUtil.getTimeStamp(preChoosedDate) | ||
246 | + if (preTimestamp <= timestamp) { | ||
247 | + tempChooseAreaTimestamp.push(tapedDate) | ||
248 | + } else if (preTimestamp > timestamp) { | ||
249 | + tempChooseAreaTimestamp.unshift(tapedDate) | ||
250 | + } | ||
251 | + } else { | ||
252 | + tempChooseAreaTimestamp = [tapedDate] | ||
253 | + } | ||
254 | + let chooseAreaTimestamp = [] | ||
255 | + if (tempChooseAreaTimestamp.length === 2) { | ||
256 | + const [startDate, endDate] = tempChooseAreaTimestamp | ||
257 | + const startDateTimestamp = dateUtil.getTimeStamp(startDate) | ||
258 | + const endDateTimestamp = dateUtil.getTimeStamp(endDate) | ||
259 | + chooseAreaTimestamp = [startDateTimestamp, endDateTimestamp] | ||
260 | + } | ||
261 | + return { | ||
262 | + calendarData: { | ||
263 | + ...calendarData, | ||
264 | + chooseAreaTimestamp, | ||
265 | + tempChooseAreaTimestamp, | ||
266 | + dates: __dates, | ||
267 | + selectedDates: __selectedDates | ||
268 | + }, | ||
269 | + calendarConfig: { | ||
270 | + ...calendarConfig, | ||
271 | + multi: true | ||
272 | + } | ||
273 | + } | ||
274 | + }, | ||
275 | + methods(component) { | ||
276 | + return { | ||
277 | + /** | ||
278 | + * 设置连续日期选择区域 | ||
279 | + * @param {array} dateArea 区域开始结束日期数组 | ||
280 | + */ | ||
281 | + chooseDateArea: (dateArea = []) => { | ||
282 | + if (dateArea.length === 1) { | ||
283 | + dateArea = dateArea.concat(dateArea) | ||
284 | + } | ||
285 | + if (dateArea.length !== 2) return | ||
286 | + const isRight = validateTimeRange(dateArea) | ||
287 | + if (!isRight) return | ||
288 | + const config = getCalendarConfig(component) || {} | ||
289 | + const { startTimestamp, endTimestamp } = convertTimeRangeToTimestamp( | ||
290 | + dateArea | ||
291 | + ) | ||
292 | + const existCalendarData = getCalendarData('calendar', component) | ||
293 | + return renderCalendar.call( | ||
294 | + component, | ||
295 | + { | ||
296 | + ...existCalendarData, | ||
297 | + chooseAreaTimestamp: [startTimestamp, endTimestamp] | ||
298 | + }, | ||
299 | + { | ||
300 | + ...config, | ||
301 | + multi: true, | ||
302 | + chooseAreaMode: true | ||
303 | + } | ||
304 | + ) | ||
305 | + } | ||
306 | + } | ||
307 | + } | ||
308 | + } | ||
309 | +} |
@@ -0,0 +1,135 @@ | @@ -0,0 +1,135 @@ | ||
1 | +/** | ||
2 | + * @Author: drfu* | ||
3 | + * @Description: 代办事项 | ||
4 | + * @Date: 2020-10-08 21:22:09* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-11 14:23:02 | ||
7 | + * */ | ||
8 | + | ||
9 | +import { getCalendarData, dateUtil } from '../utils/index' | ||
10 | +import { renderCalendar } from '../render' | ||
11 | + | ||
12 | +function updateDatePropertyOfTodoLabel(todos, dates, showLabelAlways) { | ||
13 | + const datesInfo = [...dates] | ||
14 | + for (let todo of todos) { | ||
15 | + let targetIdx = datesInfo.findIndex( | ||
16 | + item => dateUtil.toTimeStr(item) === dateUtil.toTimeStr(todo) | ||
17 | + ) | ||
18 | + let target = datesInfo[targetIdx] | ||
19 | + if (!target) continue | ||
20 | + if (showLabelAlways) { | ||
21 | + target.showTodoLabel = true | ||
22 | + } else { | ||
23 | + target.showTodoLabel = !target.choosed | ||
24 | + } | ||
25 | + if (target.showTodoLabel) { | ||
26 | + target.todoText = todo.todoText | ||
27 | + } | ||
28 | + target.color = todo.color | ||
29 | + } | ||
30 | + return datesInfo | ||
31 | +} | ||
32 | + | ||
33 | +export default () => { | ||
34 | + return { | ||
35 | + name: 'todo', | ||
36 | + beforeRender(calendarData = {}, calendarConfig = {}, component) { | ||
37 | + const { todos = [], dates = [], showLabelAlways } = calendarData | ||
38 | + const dateWithTodoInfo = updateDatePropertyOfTodoLabel( | ||
39 | + todos, | ||
40 | + dates, | ||
41 | + showLabelAlways | ||
42 | + ) | ||
43 | + return { | ||
44 | + calendarData: { | ||
45 | + ...calendarData, | ||
46 | + dates: dateWithTodoInfo | ||
47 | + }, | ||
48 | + calendarConfig | ||
49 | + } | ||
50 | + }, | ||
51 | + methods(component) { | ||
52 | + return { | ||
53 | + setTodos: (options = {}) => { | ||
54 | + const calendar = getCalendarData('calendar', component) | ||
55 | + if (!calendar || !calendar.dates) { | ||
56 | + return Promise.reject('请等待日历初始化完成后再调用该方法') | ||
57 | + } | ||
58 | + const { | ||
59 | + circle, | ||
60 | + dotColor = '', | ||
61 | + pos = 'bottom', | ||
62 | + showLabelAlways, | ||
63 | + dates: todoDates = [] | ||
64 | + } = options | ||
65 | + const { todos = [] } = calendar | ||
66 | + const tranformStr2NumOfTodo = todoDates.map(date => | ||
67 | + dateUtil.tranformStr2NumOfDate(date) | ||
68 | + ) | ||
69 | + const calendarData = { | ||
70 | + dates: calendar.dates, | ||
71 | + todos: dateUtil.uniqueArrayByDate( | ||
72 | + todos.concat(tranformStr2NumOfTodo) | ||
73 | + ) | ||
74 | + } | ||
75 | + if (!circle) { | ||
76 | + calendarData.todoLabelPos = pos | ||
77 | + calendarData.todoLabelColor = dotColor | ||
78 | + } | ||
79 | + calendarData.todoLabelCircle = circle || false | ||
80 | + calendarData.showLabelAlways = showLabelAlways || false | ||
81 | + const existCalendarData = getCalendarData('calendar', component) | ||
82 | + return renderCalendar.call(component, { | ||
83 | + ...existCalendarData, | ||
84 | + ...calendarData | ||
85 | + }) | ||
86 | + }, | ||
87 | + deleteTodos(todos = []) { | ||
88 | + if (!(todos instanceof Array) || !todos.length) | ||
89 | + return Promise.reject('deleteTodos()应为入参为非空数组') | ||
90 | + const existCalendarData = getCalendarData('calendar', component) | ||
91 | + const allTodos = existCalendarData.todos || [] | ||
92 | + const toDeleteTodos = todos.map(item => dateUtil.toTimeStr(item)) | ||
93 | + const remainTodos = allTodos.filter( | ||
94 | + item => !toDeleteTodos.includes(dateUtil.toTimeStr(item)) | ||
95 | + ) | ||
96 | + const { dates, curYear, curMonth } = existCalendarData | ||
97 | + const _dates = [...dates] | ||
98 | + const currentMonthTodos = dateUtil.filterDatesByYM( | ||
99 | + { | ||
100 | + year: curYear, | ||
101 | + month: curMonth | ||
102 | + }, | ||
103 | + remainTodos | ||
104 | + ) | ||
105 | + _dates.forEach(item => { | ||
106 | + item.showTodoLabel = false | ||
107 | + }) | ||
108 | + currentMonthTodos.forEach(item => { | ||
109 | + _dates[item.date - 1].showTodoLabel = !_dates[item.date - 1].choosed | ||
110 | + }) | ||
111 | + return renderCalendar.call(component, { | ||
112 | + ...existCalendarData, | ||
113 | + dates: _dates, | ||
114 | + todos: remainTodos | ||
115 | + }) | ||
116 | + }, | ||
117 | + clearTodos() { | ||
118 | + const existCalendarData = getCalendarData('calendar', component) | ||
119 | + const _dates = [...existCalendarData.dates] | ||
120 | + _dates.forEach(item => { | ||
121 | + item.showTodoLabel = false | ||
122 | + }) | ||
123 | + return renderCalendar.call(component, { | ||
124 | + ...existCalendarData, | ||
125 | + dates: _dates, | ||
126 | + todos: [] | ||
127 | + }) | ||
128 | + }, | ||
129 | + getTodos() { | ||
130 | + return getCalendarData('calendar.todos', component) || [] | ||
131 | + } | ||
132 | + } | ||
133 | + } | ||
134 | + } | ||
135 | +} |
@@ -0,0 +1,432 @@ | @@ -0,0 +1,432 @@ | ||
1 | +/** | ||
2 | + * @Author: drfu* | ||
3 | + * @Description: 周视图 | ||
4 | + * @Date: 2020-10-08 21:22:09* | ||
5 | + * @Last Modified by: drfu | ||
6 | + * @Last Modified time: 2020-10-12 14:39:45 | ||
7 | + * */ | ||
8 | + | ||
9 | +import { renderCalendar } from '../render' | ||
10 | +import { | ||
11 | + getCalendarConfig, | ||
12 | + getCalendarData, | ||
13 | + logger, | ||
14 | + dateUtil | ||
15 | +} from '../utils/index' | ||
16 | +import { calcJumpData } from '../core' | ||
17 | + | ||
18 | +/** | ||
19 | + * 当月第一周所有日期 | ||
20 | + */ | ||
21 | +function firstWeekInMonth( | ||
22 | + target = {}, | ||
23 | + calendarDates = [], | ||
24 | + calendarConfig = {} | ||
25 | +) { | ||
26 | + const { firstDayOfWeek } = calendarConfig | ||
27 | + const firstDayOfWeekIsMon = firstDayOfWeek === 'Mon' | ||
28 | + const { year, month } = target | ||
29 | + let firstDay = dateUtil.getDayOfWeek(year, month, 1) | ||
30 | + if (firstDayOfWeekIsMon && firstDay === 0) { | ||
31 | + firstDay = 7 | ||
32 | + } | ||
33 | + const [, end] = [0, 7 - firstDay] | ||
34 | + return calendarDates.slice(0, firstDayOfWeekIsMon ? end + 1 : end) | ||
35 | +} | ||
36 | + | ||
37 | +/** | ||
38 | + * 当月最后一周所有日期 | ||
39 | + */ | ||
40 | +function lastWeekInMonth(target = {}, calendarDates = [], calendarConfig = {}) { | ||
41 | + const { firstDayOfWeek } = calendarConfig | ||
42 | + const firstDayOfWeekIsMon = firstDayOfWeek === 'Mon' | ||
43 | + const { year, month } = target | ||
44 | + const lastDay = dateUtil.getDatesCountOfMonth(year, month) | ||
45 | + let lastDayWeek = dateUtil.getDayOfWeek(year, month, lastDay) | ||
46 | + if (firstDayOfWeekIsMon && lastDayWeek === 0) { | ||
47 | + lastDayWeek = 7 | ||
48 | + } | ||
49 | + const [start, end] = [lastDay - lastDayWeek, lastDay] | ||
50 | + return calendarDates.slice(firstDayOfWeekIsMon ? start : start - 1, end) | ||
51 | +} | ||
52 | + | ||
53 | +/** | ||
54 | + * 判断目标日期是否在某些指定日历内 | ||
55 | + */ | ||
56 | +function dateIsInDatesRange(target, dates) { | ||
57 | + if (!target || !dates || !dates.length) return false | ||
58 | + const targetDateStr = dateUtil.toTimeStr(target) | ||
59 | + let rst = false | ||
60 | + for (let date of dates) { | ||
61 | + const dateStr = dateUtil.toTimeStr(date) | ||
62 | + if (dateStr === targetDateStr) { | ||
63 | + rst = true | ||
64 | + return rst | ||
65 | + } | ||
66 | + rst = false | ||
67 | + } | ||
68 | + return rst | ||
69 | +} | ||
70 | + | ||
71 | +function getDatesWhenTargetInFirstWeek(target, firstWeekDates) { | ||
72 | + const { year, month } = target | ||
73 | + const prevMonthInfo = dateUtil.getPrevMonthInfo({ year, month }) | ||
74 | + let lastMonthDatesCount = dateUtil.getDatesCountOfMonth( | ||
75 | + prevMonthInfo.year, | ||
76 | + prevMonthInfo.month | ||
77 | + ) | ||
78 | + let dates = firstWeekDates | ||
79 | + let firstWeekCount = firstWeekDates.length | ||
80 | + for (let i = 0; i < 7 - firstWeekCount; i++) { | ||
81 | + const week = dateUtil.getDayOfWeek(+year, +month, lastMonthDatesCount) | ||
82 | + dates.unshift({ | ||
83 | + year: prevMonthInfo.year, | ||
84 | + month: prevMonthInfo.month, | ||
85 | + date: lastMonthDatesCount, | ||
86 | + week | ||
87 | + }) | ||
88 | + lastMonthDatesCount -= 1 | ||
89 | + } | ||
90 | + return dates | ||
91 | +} | ||
92 | + | ||
93 | +function getDatesWhenTargetInLastWeek(target, lastWeekDates) { | ||
94 | + const { year, month } = target | ||
95 | + const prevMonthInfo = dateUtil.getNextMonthInfo({ year, month }) | ||
96 | + let dates = lastWeekDates | ||
97 | + let lastWeekCount = lastWeekDates.length | ||
98 | + for (let i = 0; i < 7 - lastWeekCount; i++) { | ||
99 | + const week = dateUtil.getDayOfWeek(+year, +month, i + 1) | ||
100 | + dates.push({ | ||
101 | + year: prevMonthInfo.year, | ||
102 | + month: prevMonthInfo.month, | ||
103 | + date: i + 1, | ||
104 | + week | ||
105 | + }) | ||
106 | + } | ||
107 | + return dates | ||
108 | +} | ||
109 | + | ||
110 | +function getDates(target, calendarDates = [], calendarConfig = {}) { | ||
111 | + const { year, month, date } = target | ||
112 | + const targetDay = dateUtil.getDayOfWeek(year, month, date) | ||
113 | + const { firstDayOfWeek } = calendarConfig | ||
114 | + const firstDayOfWeekIsMon = firstDayOfWeek === 'Mon' | ||
115 | + if (firstDayOfWeekIsMon) { | ||
116 | + const startIdx = date - (targetDay || 7) | ||
117 | + return calendarDates.splice(startIdx, 7) | ||
118 | + } else { | ||
119 | + const startIdx = date - targetDay - 1 | ||
120 | + return calendarDates.splice(startIdx, 7) | ||
121 | + } | ||
122 | +} | ||
123 | + | ||
124 | +function getTargetWeekDates(target, calendarConfig) { | ||
125 | + if (!target) return | ||
126 | + const { year, month } = target | ||
127 | + const calendarDates = dateUtil.calcDates(year, month) | ||
128 | + const firstWeekDates = firstWeekInMonth(target, calendarDates, calendarConfig) | ||
129 | + const lastWeekDates = lastWeekInMonth(target, calendarDates, calendarConfig) | ||
130 | + if (dateIsInDatesRange(target, firstWeekDates)) { | ||
131 | + return getDatesWhenTargetInFirstWeek(target, firstWeekDates) | ||
132 | + } else if (dateIsInDatesRange(target, lastWeekDates)) { | ||
133 | + return getDatesWhenTargetInLastWeek(target, lastWeekDates) | ||
134 | + } else { | ||
135 | + return getDates(target, calendarDates, calendarConfig) | ||
136 | + } | ||
137 | +} | ||
138 | + | ||
139 | +/** | ||
140 | + * 计算周视图下当前这一周最后一天 | ||
141 | + */ | ||
142 | +function calculateLastDateOfCurrentWeek(calendarData = {}) { | ||
143 | + const { dates = [] } = calendarData | ||
144 | + return dates[dates.length - 1] | ||
145 | +} | ||
146 | +/** | ||
147 | + * 计算周视图下当前这一周第一天 | ||
148 | + */ | ||
149 | +function calculateFirstDateOfCurrentWeek(calendarData = {}) { | ||
150 | + const { dates } = calendarData | ||
151 | + return dates[0] | ||
152 | +} | ||
153 | + | ||
154 | +/** | ||
155 | + * 计算下一周的日期 | ||
156 | + */ | ||
157 | +function calculateNextWeekDates(calendarData = {}) { | ||
158 | + let { curYear, curMonth } = calendarData | ||
159 | + let calendarDates = [] | ||
160 | + let lastDateInThisWeek = calculateLastDateOfCurrentWeek(calendarData) | ||
161 | + const { year: LYear, month: LMonth } = lastDateInThisWeek | ||
162 | + if (curYear !== LYear || curMonth !== LMonth) { | ||
163 | + calendarDates = dateUtil.calcDates(LYear, LMonth) | ||
164 | + curYear = LYear | ||
165 | + curMonth = LMonth | ||
166 | + } else { | ||
167 | + calendarDates = dateUtil.calcDates(curYear, curMonth) | ||
168 | + } | ||
169 | + const lastDateInThisMonth = dateUtil.getDatesCountOfMonth(curYear, curMonth) | ||
170 | + const count = lastDateInThisMonth - lastDateInThisWeek.date | ||
171 | + const lastDateIdx = calendarDates.findIndex( | ||
172 | + date => dateUtil.toTimeStr(date) === dateUtil.toTimeStr(lastDateInThisWeek) | ||
173 | + ) | ||
174 | + const startIdx = lastDateIdx + 1 | ||
175 | + if (count >= 7) { | ||
176 | + return { | ||
177 | + dates: calendarDates.splice(startIdx, 7), | ||
178 | + year: curYear, | ||
179 | + month: curMonth | ||
180 | + } | ||
181 | + } else { | ||
182 | + const nextMonth = dateUtil.getNextMonthInfo({ | ||
183 | + year: curYear, | ||
184 | + month: curMonth | ||
185 | + }) | ||
186 | + const { year, month } = nextMonth || {} | ||
187 | + const calendarDatesOfNextMonth = dateUtil.calcDates(year, month) | ||
188 | + const remainDatesOfThisMonth = calendarDates.splice(startIdx) | ||
189 | + const patchDatesOfNextMonth = calendarDatesOfNextMonth.splice( | ||
190 | + 0, | ||
191 | + 7 - remainDatesOfThisMonth.length | ||
192 | + ) | ||
193 | + return { | ||
194 | + dates: [...remainDatesOfThisMonth, ...patchDatesOfNextMonth], | ||
195 | + ...nextMonth | ||
196 | + } | ||
197 | + } | ||
198 | +} | ||
199 | + | ||
200 | +/** | ||
201 | + * 计算上一周的日期 | ||
202 | + */ | ||
203 | +function calculatePrevWeekDates(calendarData = {}) { | ||
204 | + let { curYear, curMonth } = calendarData | ||
205 | + let firstDateInThisWeek = calculateFirstDateOfCurrentWeek(calendarData) | ||
206 | + let calendarDates = [] | ||
207 | + const { year: FYear, month: FMonth } = firstDateInThisWeek | ||
208 | + if (curYear !== FYear || curMonth !== FMonth) { | ||
209 | + calendarDates = dateUtil.calcDates(FYear, FMonth) | ||
210 | + curYear = FYear | ||
211 | + curMonth = FMonth | ||
212 | + } else { | ||
213 | + calendarDates = dateUtil.calcDates(curYear, curMonth) | ||
214 | + } | ||
215 | + const firstDateIdx = calendarDates.findIndex( | ||
216 | + date => dateUtil.toTimeStr(date) === dateUtil.toTimeStr(firstDateInThisWeek) | ||
217 | + ) | ||
218 | + if (firstDateIdx - 7 >= 0) { | ||
219 | + const startIdx = firstDateIdx - 7 | ||
220 | + return { | ||
221 | + dates: calendarDates.splice(startIdx, 7), | ||
222 | + year: curYear, | ||
223 | + month: curMonth | ||
224 | + } | ||
225 | + } else { | ||
226 | + const prevMonth = dateUtil.getPrevMonthInfo({ | ||
227 | + year: curYear, | ||
228 | + month: curMonth | ||
229 | + }) | ||
230 | + const { year, month } = prevMonth || {} | ||
231 | + const calendarDatesOfPrevMonth = dateUtil.calcDates(year, month) | ||
232 | + const remainDatesOfThisMonth = calendarDates.splice( | ||
233 | + 0, | ||
234 | + firstDateInThisWeek.date - 1 | ||
235 | + ) | ||
236 | + const patchDatesOfPrevMonth = calendarDatesOfPrevMonth.splice( | ||
237 | + -(7 - remainDatesOfThisMonth.length) | ||
238 | + ) | ||
239 | + return { | ||
240 | + dates: [...patchDatesOfPrevMonth, ...remainDatesOfThisMonth], | ||
241 | + ...prevMonth | ||
242 | + } | ||
243 | + } | ||
244 | +} | ||
245 | + | ||
246 | +export default () => { | ||
247 | + return { | ||
248 | + name: 'week', | ||
249 | + beforeRender(calendarData = {}, calendarConfig = {}, component) { | ||
250 | + const { initializedWeekMode, selectedDates } = calendarData | ||
251 | + if (calendarConfig.weekMode && !initializedWeekMode) { | ||
252 | + const { defaultDate } = calendarConfig | ||
253 | + const target = | ||
254 | + (selectedDates && selectedDates[0]) || | ||
255 | + (defaultDate && dateUtil.transformDateRow2Dict(defaultDate)) || | ||
256 | + dateUtil.todayFMD() | ||
257 | + const waitRenderData = this.methods( | ||
258 | + component | ||
259 | + ).__calcDatesWhenSwitchView('week', target) | ||
260 | + const { data, config } = waitRenderData || {} | ||
261 | + const setSelectDates = this.methods( | ||
262 | + component | ||
263 | + ).__selectTargetDateWhenJump(target, data.dates, config) | ||
264 | + return { | ||
265 | + calendarData: { | ||
266 | + ...data, | ||
267 | + ...setSelectDates, | ||
268 | + weeksCh: dateUtil.getWeekHeader(calendarConfig.firstDayOfWeek), | ||
269 | + initializedWeekMode: true | ||
270 | + }, | ||
271 | + calendarConfig | ||
272 | + } | ||
273 | + } | ||
274 | + return { | ||
275 | + calendarData, | ||
276 | + calendarConfig | ||
277 | + } | ||
278 | + }, | ||
279 | + onSwitchCalendar(target = {}, calendarData = {}, component) { | ||
280 | + const { direction } = target | ||
281 | + const { curYear, curMonth } = calendarData | ||
282 | + const calendarConfig = getCalendarConfig(component) | ||
283 | + let waitRenderData = {} | ||
284 | + if (calendarConfig.weekMode) { | ||
285 | + if (direction === 'left') { | ||
286 | + waitRenderData = calculateNextWeekDates(calendarData) | ||
287 | + } else { | ||
288 | + waitRenderData = calculatePrevWeekDates(calendarData) | ||
289 | + } | ||
290 | + const { dates, year, month } = waitRenderData | ||
291 | + return { | ||
292 | + ...calendarData, | ||
293 | + dates, | ||
294 | + curYear: year || curYear, | ||
295 | + curMonth: month || curMonth | ||
296 | + } | ||
297 | + } | ||
298 | + return calendarData | ||
299 | + }, | ||
300 | + methods(component) { | ||
301 | + return { | ||
302 | + __selectTargetDateWhenJump: (target = {}, dates = [], config = {}) => { | ||
303 | + let selectedDate = target | ||
304 | + const weekDates = dates.map((date, idx) => { | ||
305 | + const tmp = { ...date } | ||
306 | + tmp.id = idx | ||
307 | + const isTarget = | ||
308 | + dateUtil.toTimeStr(target) === dateUtil.toTimeStr(tmp) | ||
309 | + if (isTarget && !target.choosed && config.autoChoosedWhenJump) { | ||
310 | + tmp.choosed = true | ||
311 | + selectedDate = tmp | ||
312 | + } | ||
313 | + return tmp | ||
314 | + }) | ||
315 | + return { | ||
316 | + dates: weekDates, | ||
317 | + selectedDates: [selectedDate] | ||
318 | + } | ||
319 | + }, | ||
320 | + __calcDatesForWeekMode(target, config = {}, calendarData = {}) { | ||
321 | + const { year, month } = target || {} | ||
322 | + const weekDates = getTargetWeekDates(target, config) | ||
323 | + weekDates.forEach((date, idx) => (date.id = idx)) | ||
324 | + return { | ||
325 | + data: { | ||
326 | + ...calendarData, | ||
327 | + prevMonthGrids: null, | ||
328 | + nextMonthGrids: null, | ||
329 | + dates: weekDates, | ||
330 | + curYear: year, | ||
331 | + curMonth: month | ||
332 | + }, | ||
333 | + config: { | ||
334 | + ...config, | ||
335 | + weekMode: true | ||
336 | + } | ||
337 | + } | ||
338 | + }, | ||
339 | + __calcDatesForMonthMode(target, config = {}, calendarData = {}) { | ||
340 | + const { year, month } = target || {} | ||
341 | + const waitRenderData = calcJumpData({ | ||
342 | + dateInfo: target, | ||
343 | + config | ||
344 | + }) | ||
345 | + return { | ||
346 | + data: { | ||
347 | + ...calendarData, | ||
348 | + ...waitRenderData, | ||
349 | + curYear: year, | ||
350 | + curMonth: month | ||
351 | + }, | ||
352 | + config: { | ||
353 | + ...config, | ||
354 | + weekMode: false | ||
355 | + } | ||
356 | + } | ||
357 | + }, | ||
358 | + /** | ||
359 | + * 周、月视图切换 | ||
360 | + * @param {string} view 视图 [week, month] | ||
361 | + * @param {object} target | ||
362 | + */ | ||
363 | + __calcDatesWhenSwitchView: (view, target) => { | ||
364 | + const calendarConfig = getCalendarConfig(component) | ||
365 | + if (calendarConfig.multi) | ||
366 | + return logger.warn('多选模式不能切换周月视图') | ||
367 | + const existCalendarData = getCalendarData('calendar', component) || {} | ||
368 | + const { | ||
369 | + selectedDates = [], | ||
370 | + dates = [], | ||
371 | + curYear, | ||
372 | + curMonth | ||
373 | + } = existCalendarData | ||
374 | + const currentMonthSelected = selectedDates.filter( | ||
375 | + item => curYear === +item.year || curMonth === +item.month | ||
376 | + ) | ||
377 | + let jumpTarget = {} | ||
378 | + if (target) { | ||
379 | + jumpTarget = target | ||
380 | + } else { | ||
381 | + if (currentMonthSelected.length) { | ||
382 | + jumpTarget = currentMonthSelected.pop() | ||
383 | + } else { | ||
384 | + jumpTarget = dates[0] | ||
385 | + } | ||
386 | + } | ||
387 | + if (view === 'week') { | ||
388 | + return this.methods(component).__calcDatesForWeekMode( | ||
389 | + jumpTarget, | ||
390 | + calendarConfig, | ||
391 | + existCalendarData | ||
392 | + ) | ||
393 | + } else { | ||
394 | + return this.methods(component).__calcDatesForMonthMode( | ||
395 | + jumpTarget, | ||
396 | + calendarConfig, | ||
397 | + existCalendarData | ||
398 | + ) | ||
399 | + } | ||
400 | + }, | ||
401 | + weekModeJump: dateInfo => { | ||
402 | + const target = dateInfo || dateUtil.todayFMD() | ||
403 | + const existCalendarData = getCalendarData('calendar', component) || {} | ||
404 | + const waitRenderData = this.methods( | ||
405 | + component | ||
406 | + ).__calcDatesWhenSwitchView('week', target) | ||
407 | + const { data, config } = waitRenderData || {} | ||
408 | + const setSelectDates = this.methods( | ||
409 | + component | ||
410 | + ).__selectTargetDateWhenJump(target, data.dates, config) | ||
411 | + return renderCalendar.call( | ||
412 | + component, | ||
413 | + { | ||
414 | + ...existCalendarData, | ||
415 | + ...data, | ||
416 | + ...setSelectDates | ||
417 | + }, | ||
418 | + config | ||
419 | + ) | ||
420 | + }, | ||
421 | + switchView: (view, target) => { | ||
422 | + const waitRenderData = this.methods( | ||
423 | + component | ||
424 | + ).__calcDatesWhenSwitchView(view, target) | ||
425 | + const { data, config } = waitRenderData || {} | ||
426 | + if (!data) return logger.warn('当前状态不能切换为周视图') | ||
427 | + return renderCalendar.call(component, data, config) | ||
428 | + } | ||
429 | + } | ||
430 | + } | ||
431 | + } | ||
432 | +} |
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +import plugins from './plugins/index' | ||
2 | +import { getCalendarConfig } from './utils/index' | ||
3 | + | ||
4 | +/** | ||
5 | + * 渲染日历 | ||
6 | + */ | ||
7 | +export function renderCalendar(calendarData, calendarConfig) { | ||
8 | + return new Promise(resolve => { | ||
9 | + const Component = this | ||
10 | + if (Component.firstRender === void 0) { | ||
11 | + Component.firstRender = true | ||
12 | + } else { | ||
13 | + Component.firstRender = false | ||
14 | + } | ||
15 | + const exitData = Component.data.calendar || {} | ||
16 | + for (let plugin of plugins.installed) { | ||
17 | + const [, p] = plugin | ||
18 | + if (typeof p.beforeRender === 'function') { | ||
19 | + const { | ||
20 | + calendarData: newData, | ||
21 | + calendarConfig: newConfig | ||
22 | + } = p.beforeRender( | ||
23 | + { ...exitData, ...calendarData }, | ||
24 | + calendarConfig || getCalendarConfig(Component), | ||
25 | + Component | ||
26 | + ) | ||
27 | + calendarData = newData | ||
28 | + calendarConfig = newConfig | ||
29 | + } | ||
30 | + } | ||
31 | + | ||
32 | + Component.setData( | ||
33 | + { | ||
34 | + config: calendarConfig, | ||
35 | + calendar: calendarData | ||
36 | + }, | ||
37 | + () => { | ||
38 | + const rst = { | ||
39 | + calendar: calendarData, | ||
40 | + config: calendarConfig, | ||
41 | + firstRender: Component.firstRender | ||
42 | + } | ||
43 | + resolve(rst) | ||
44 | + if (Component.firstRender) { | ||
45 | + Component.triggerEvent('afterCalendarRender', rst) | ||
46 | + Component.firstRender = false | ||
47 | + } | ||
48 | + } | ||
49 | + ) | ||
50 | + }) | ||
51 | +} |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +@font-face { | ||
2 | + font-family: 'iconfont'; | ||
3 | + src: url(data:font/truetype;charset=utf-8;base64,AAEAAAANAIAAAwBQRkZUTYda3jUAAAfEAAAAHEdERUYAKQANAAAHpAAAAB5PUy8yPllJ4AAAAVgAAABWY21hcAAP65kAAAHIAAABQmdhc3D//wADAAAHnAAAAAhnbHlmLotR3AAAAxwAAAGkaGVhZBTU+ykAAADcAAAANmhoZWEHKwOFAAABFAAAACRobXR4DasB4gAAAbAAAAAWbG9jYQC0AR4AAAMMAAAAEG1heHABEwAyAAABOAAAACBuYW1lKeYRVQAABMAAAAKIcG9zdEoLnOYAAAdIAAAAUgABAAAAAQAAiPM8al8PPPUACwQAAAAAANjbW5YAAAAA2NtblgCzAAQDTQL8AAAACAACAAAAAAAAAAEAAAOA/4AAXAQAAAAAAANNAAEAAAAAAAAAAAAAAAAAAAAEAAEAAAAHACYAAgAAAAAAAgAAAAoACgAAAP8AAAAAAAAAAQQAAZAABQAAAokCzAAAAI8CiQLMAAAB6wAyAQgAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA5+vn7gOA/4AAXAOAAIAAAAABAAAAAAAABAAAAAAAAAAEAAAABAABLgD4ALQAswAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAA5+7//wAA5+v//xgYAAEAAAAAAAABBgAAAQAAAAAAAAABAgAAAAIAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJgBMAI4A0gABAS4ABAMKAvwAEgAACQEmBh0BFBcJAQYdARQWNwE2NAL+/j0ECQYBaP6YBgkEAcMMAZkBYAMEBU0IBf7n/ucFCE0FBAMBYAoeAAAAAQD4AAQC1AL8ABIAAAE1NCYHAQYUFwEWNj0BNCcJATYC1AkE/j0MDAHDBAkG/pgBaAYCpk0FBAP+oAoeCv6gAwQFTQgFARkBGQUAAAIAtAAgA00C4AASACUAAAkBNiYrASIHAwYUFwEWOwEyNicTATYmKwEiBwMGFBcBFjsBMjYnAREBCQMEBU0IBf8HBwD/BQhNBQQDJwEJAwQFTQgF/wcHAP8FCE0FBAMBgAFTBAkG/roJFgn+ugYJBAFTAVMECQb+ugkWCf66BgkEAAAAAAIAswAgA0wC4AASACUAAAEDJisBIgYXCQEGFjsBMjcBNjQlAyYrASIGFwkBBhY7ATI3ATY0AhX/BQhNBQQDAQn+9wMEBU0IBQD/BwEp/wUITQUEAwEJ/vcDBAVNCAUA/wcBlAFGBgkE/q3+rQQJBgFGCRYJAUYGCQT+rf6tBAkGAUYJFgAAAAAAABIA3gABAAAAAAAAABUALAABAAAAAAABAAgAVAABAAAAAAACAAcAbQABAAAAAAADAAgAhwABAAAAAAAEAAgAogABAAAAAAAFAAsAwwABAAAAAAAGAAgA4QABAAAAAAAKACsBQgABAAAAAAALABMBlgADAAEECQAAACoAAAADAAEECQABABAAQgADAAEECQACAA4AXQADAAEECQADABAAdQADAAEECQAEABAAkAADAAEECQAFABYAqwADAAEECQAGABAAzwADAAEECQAKAFYA6gADAAEECQALACYBbgAKAEMAcgBlAGEAdABlAGQAIABiAHkAIABpAGMAbwBuAGYAbwBuAHQACgAACkNyZWF0ZWQgYnkgaWNvbmZvbnQKAABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABSAGUAZwB1AGwAYQByAABSZWd1bGFyAABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABWAGUAcgBzAGkAbwBuACAAMQAuADAAAFZlcnNpb24gMS4wAABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAHMAdgBnADIAdAB0AGYAIABmAHIAbwBtACAARgBvAG4AdABlAGwAbABvACAAcAByAG8AagBlAGMAdAAuAABHZW5lcmF0ZWQgYnkgc3ZnMnR0ZiBmcm9tIEZvbnRlbGxvIHByb2plY3QuAABoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAABodHRwOi8vZm9udGVsbG8uY29tAAACAAAAAAAAAAoAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAcAAAABAAIBAgEDAQQBBQVyaWdodARsZWZ0CmRvdWJsZWxlZnQLZG91YmxlcmlnaHQAAAAAAAH//wACAAEAAAAMAAAAFgAAAAIAAQADAAYAAQAEAAAAAgAAAAAAAAABAAAAANWkJwgAAAAA2NtblgAAAADY21uW) format('truetype'); | ||
4 | + font-weight: normal; | ||
5 | + font-style: normal; | ||
6 | +} | ||
7 | + | ||
8 | +.iconfont { | ||
9 | + font-family: "iconfont" !important; | ||
10 | + font-size: 16px; | ||
11 | + font-style: normal; | ||
12 | + -webkit-font-smoothing: antialiased; | ||
13 | +} | ||
14 | + | ||
15 | +.icon-right::before { | ||
16 | + content: "\e7eb"; | ||
17 | +} | ||
18 | + | ||
19 | +.icon-left::before { | ||
20 | + content: "\e7ec"; | ||
21 | +} | ||
22 | + | ||
23 | +.icon-doubleleft::before { | ||
24 | + content: "\e7ed"; | ||
25 | +} | ||
26 | + | ||
27 | +.icon-doubleright::before { | ||
28 | + content: "\e7ee"; | ||
29 | +} |
@@ -0,0 +1,61 @@ | @@ -0,0 +1,61 @@ | ||
1 | + | ||
2 | +/* 日历主要颜色相关样式 */ | ||
3 | + | ||
4 | +.default_color, | ||
5 | +.default_weekend-color, | ||
6 | +.default_handle-color, | ||
7 | +.default_week-color { | ||
8 | + color: #ff629a; | ||
9 | +} | ||
10 | + | ||
11 | +.default_today { | ||
12 | + color: #fff; | ||
13 | + background-color: #874fb4; | ||
14 | +} | ||
15 | + | ||
16 | +.default_choosed { | ||
17 | + color: #fff; | ||
18 | + background-color: #ff629a; | ||
19 | +} | ||
20 | + | ||
21 | +.default_date-disable { | ||
22 | + color: #c7c7c7; | ||
23 | +} | ||
24 | + | ||
25 | +.default_choosed.default_date-disable { | ||
26 | + color: #e2e2e2; | ||
27 | + background-color: #c2afb6; | ||
28 | +} | ||
29 | + | ||
30 | +.default_prev-month-date, | ||
31 | +.default_next-month-date { | ||
32 | + color: #e2e2e2; | ||
33 | +} | ||
34 | + | ||
35 | +.default_normal-date { | ||
36 | + color: #88d2ac; | ||
37 | +} | ||
38 | + | ||
39 | +.default_todo-circle { | ||
40 | + border-color: #88d2ac; | ||
41 | +} | ||
42 | + | ||
43 | +.default_todo-dot { | ||
44 | + background-color: #e54d42; | ||
45 | +} | ||
46 | + | ||
47 | +.default_date-desc { | ||
48 | + color: #c2c2c2; | ||
49 | +} | ||
50 | + | ||
51 | +.default_date-desc-lunar { | ||
52 | + color: #e54d42; | ||
53 | +} | ||
54 | + | ||
55 | +.default_date-desc-disable { | ||
56 | + color: #e2e2e2; | ||
57 | +} | ||
58 | + | ||
59 | +.default_festival { | ||
60 | + color: #c2c2c2; | ||
61 | +} |
@@ -0,0 +1,58 @@ | @@ -0,0 +1,58 @@ | ||
1 | +.elegant_color, | ||
2 | +.elegant_weekend-color, | ||
3 | +.elegant_handle-color, | ||
4 | +.elegant_week-color { | ||
5 | + color: #333; | ||
6 | +} | ||
7 | + | ||
8 | +.elegant_today { | ||
9 | + color: #000; | ||
10 | + background-color: #e1e7f5; | ||
11 | +} | ||
12 | + | ||
13 | +.elegant_choosed { | ||
14 | + color: #000; | ||
15 | + background-color: #e2e2e2; | ||
16 | +} | ||
17 | + | ||
18 | +.elegant_date-disable { | ||
19 | + color: #c7c7c7; | ||
20 | +} | ||
21 | + | ||
22 | +.elegant_choosed.elegant_date-disable { | ||
23 | + color: #999; | ||
24 | + background-color: #ebebeb; | ||
25 | +} | ||
26 | + | ||
27 | +.elegant_prev-month-date, | ||
28 | +.elegant_next-month-date { | ||
29 | + color: #e2e2e2; | ||
30 | +} | ||
31 | + | ||
32 | +.elegant_normal-date { | ||
33 | + color: #777; | ||
34 | +} | ||
35 | + | ||
36 | +.elegant_todo-circle { | ||
37 | + border-color: #161035; | ||
38 | +} | ||
39 | + | ||
40 | +.elegant_todo-dot { | ||
41 | + background-color: #161035; | ||
42 | +} | ||
43 | + | ||
44 | +.elegant_date-desc { | ||
45 | + color: #c2c2c2; | ||
46 | +} | ||
47 | + | ||
48 | +.elegant_date-desc-lunar { | ||
49 | + color: #161035; | ||
50 | +} | ||
51 | + | ||
52 | +.elegant_date-desc-disable { | ||
53 | + color: #e2e2e2; | ||
54 | +} | ||
55 | + | ||
56 | +.elegant_festival { | ||
57 | + color: #c2c2c2; | ||
58 | +} |
@@ -0,0 +1,284 @@ | @@ -0,0 +1,284 @@ | ||
1 | +import Logger from './logger' | ||
2 | +import WxData from './wxData' | ||
3 | + | ||
4 | +let systemInfo | ||
5 | +export function getSystemInfo() { | ||
6 | + if (systemInfo) return systemInfo | ||
7 | + systemInfo = wx.getSystemInfoSync() | ||
8 | + return systemInfo | ||
9 | +} | ||
10 | + | ||
11 | +export function isIos() { | ||
12 | + const sys = getSystemInfo() | ||
13 | + return /iphone|ios/i.test(sys.platform) | ||
14 | +} | ||
15 | + | ||
16 | +class Gesture { | ||
17 | + /** | ||
18 | + * 左滑 | ||
19 | + * @param {object} e 事件对象 | ||
20 | + * @returns {boolean} 布尔值 | ||
21 | + */ | ||
22 | + isLeft(gesture = {}, touche = {}) { | ||
23 | + const { startX, startY } = gesture | ||
24 | + const deltaX = touche.clientX - startX | ||
25 | + const deltaY = touche.clientY - startY | ||
26 | + if (deltaX < -60 && deltaY < 20 && deltaY > -20) { | ||
27 | + return true | ||
28 | + } else { | ||
29 | + return false | ||
30 | + } | ||
31 | + } | ||
32 | + /** | ||
33 | + * 右滑 | ||
34 | + * @param {object} e 事件对象 | ||
35 | + * @returns {boolean} 布尔值 | ||
36 | + */ | ||
37 | + isRight(gesture = {}, touche = {}) { | ||
38 | + const { startX, startY } = gesture | ||
39 | + const deltaX = touche.clientX - startX | ||
40 | + const deltaY = touche.clientY - startY | ||
41 | + | ||
42 | + if (deltaX > 60 && deltaY < 20 && deltaY > -20) { | ||
43 | + return true | ||
44 | + } else { | ||
45 | + return false | ||
46 | + } | ||
47 | + } | ||
48 | +} | ||
49 | + | ||
50 | +class DateUtil { | ||
51 | + newDate(year, month, date) { | ||
52 | + let cur = `${+year}-${+month}-${+date}` | ||
53 | + if (isIos()) { | ||
54 | + cur = `${+year}/${+month}/${+date}` | ||
55 | + } | ||
56 | + return new Date(cur) | ||
57 | + } | ||
58 | + /** | ||
59 | + * 计算指定日期时间戳 | ||
60 | + * @param {object} date | ||
61 | + */ | ||
62 | + getTimeStamp(dateInfo) { | ||
63 | + if (typeof dateInfo === 'string') { | ||
64 | + dateInfo = this.transformDateRow2Dict(dateInfo) | ||
65 | + } | ||
66 | + if (Object.prototype.toString.call(dateInfo) !== '[object Object]') return | ||
67 | + const dateUtil = new DateUtil() | ||
68 | + return dateUtil | ||
69 | + .newDate(dateInfo.year, dateInfo.month, dateInfo.date) | ||
70 | + .getTime() | ||
71 | + } | ||
72 | + /** | ||
73 | + * 计算指定月份共多少天 | ||
74 | + * @param {number} year 年份 | ||
75 | + * @param {number} month 月份 | ||
76 | + */ | ||
77 | + getDatesCountOfMonth(year, month) { | ||
78 | + return new Date(Date.UTC(year, month, 0)).getUTCDate() | ||
79 | + } | ||
80 | + /** | ||
81 | + * 计算指定月份第一天星期几 | ||
82 | + * @param {number} year 年份 | ||
83 | + * @param {number} month 月份 | ||
84 | + */ | ||
85 | + firstDayOfWeek(year, month) { | ||
86 | + return new Date(Date.UTC(year, month - 1, 1)).getUTCDay() | ||
87 | + } | ||
88 | + /** | ||
89 | + * 计算指定日期星期几 | ||
90 | + * @param {number} year 年份 | ||
91 | + * @param {number} month 月份 | ||
92 | + * @param {number} date 日期 | ||
93 | + */ | ||
94 | + getDayOfWeek(year, month, date) { | ||
95 | + return new Date(Date.UTC(year, month - 1, date)).getUTCDay() | ||
96 | + } | ||
97 | + formatTimestamp(timestamp) { | ||
98 | + const date = new Date(timestamp) | ||
99 | + return { | ||
100 | + year: date.getFullYear(), | ||
101 | + month: date.getMonth() + 1, | ||
102 | + date: date.getDate() | ||
103 | + } | ||
104 | + } | ||
105 | + todayTimestamp() { | ||
106 | + return new Date().getTime() | ||
107 | + } | ||
108 | + todayFMD() { | ||
109 | + const timestamp = this.todayTimestamp() | ||
110 | + return this.formatTimestamp(timestamp) | ||
111 | + } | ||
112 | + toTimeStr(dateInfo = {}) { | ||
113 | + return `${+dateInfo.year}-${+dateInfo.month}-${+dateInfo.date}` | ||
114 | + } | ||
115 | + transformDateRow2Dict(dateStr) { | ||
116 | + if (typeof dateStr === 'string' && dateStr.includes('-')) { | ||
117 | + const [year, month, date] = dateStr.split('-') | ||
118 | + return this.tranformStr2NumOfDate({ | ||
119 | + year, | ||
120 | + month, | ||
121 | + date | ||
122 | + }) | ||
123 | + } | ||
124 | + return {} | ||
125 | + } | ||
126 | + tranformStr2NumOfDate(date = {}) { | ||
127 | + const target = { ...date } | ||
128 | + // 可能传入字符串 | ||
129 | + target.year = +target.year | ||
130 | + target.month = +target.month | ||
131 | + target.date = +target.date | ||
132 | + return target | ||
133 | + } | ||
134 | + sortDatesByTime(dates = [], sortType) { | ||
135 | + return dates.sort((a, b) => { | ||
136 | + const at = this.getTimeStamp(a) | ||
137 | + const bt = this.getTimeStamp(b) | ||
138 | + if (at < bt && sortType !== 'desc') { | ||
139 | + return -1 | ||
140 | + } else { | ||
141 | + return 1 | ||
142 | + } | ||
143 | + }) | ||
144 | + } | ||
145 | + getPrevMonthInfo(date = {}) { | ||
146 | + const prevMonthInfo = | ||
147 | + Number(date.month) > 1 | ||
148 | + ? { | ||
149 | + year: +date.year, | ||
150 | + month: Number(date.month) - 1 | ||
151 | + } | ||
152 | + : { | ||
153 | + year: Number(date.year) - 1, | ||
154 | + month: 12 | ||
155 | + } | ||
156 | + return prevMonthInfo | ||
157 | + } | ||
158 | + getNextMonthInfo(date = {}) { | ||
159 | + const nextMonthInfo = | ||
160 | + Number(date.month) < 12 | ||
161 | + ? { | ||
162 | + year: +date.year, | ||
163 | + month: Number(date.month) + 1 | ||
164 | + } | ||
165 | + : { | ||
166 | + year: Number(date.year) + 1, | ||
167 | + month: 1 | ||
168 | + } | ||
169 | + return nextMonthInfo | ||
170 | + } | ||
171 | + getPrevYearInfo(date = {}) { | ||
172 | + return { | ||
173 | + year: Number(date.year) - 1, | ||
174 | + month: +date.month | ||
175 | + } | ||
176 | + } | ||
177 | + getNextYearInfo(date = {}) { | ||
178 | + return { | ||
179 | + year: Number(date.year) + 1, | ||
180 | + month: +date.month | ||
181 | + } | ||
182 | + } | ||
183 | + findDateIndexInArray(target, dates) { | ||
184 | + return dates.findIndex( | ||
185 | + item => dateUtil.toTimeStr(item) === dateUtil.toTimeStr(target) | ||
186 | + ) | ||
187 | + } | ||
188 | + calcDates(year, month) { | ||
189 | + const datesCount = this.getDatesCountOfMonth(year, month) | ||
190 | + const dates = [] | ||
191 | + const today = dateUtil.todayFMD() | ||
192 | + for (let i = 1; i <= datesCount; i++) { | ||
193 | + const week = dateUtil.getDayOfWeek(+year, +month, i) | ||
194 | + const date = { | ||
195 | + year: +year, | ||
196 | + id: i - 1, | ||
197 | + month: +month, | ||
198 | + date: i, | ||
199 | + week, | ||
200 | + isToday: | ||
201 | + +today.year === +year && +today.month === +month && i === +today.date | ||
202 | + } | ||
203 | + dates.push(date) | ||
204 | + } | ||
205 | + return dates | ||
206 | + } | ||
207 | + /** | ||
208 | + * 日期数组根据日期去重 | ||
209 | + * @param {array} array 数组 | ||
210 | + */ | ||
211 | + uniqueArrayByDate(array = []) { | ||
212 | + let uniqueObject = {} | ||
213 | + let uniqueArray = [] | ||
214 | + array.forEach(item => { | ||
215 | + uniqueObject[dateUtil.toTimeStr(item)] = item | ||
216 | + }) | ||
217 | + for (let i in uniqueObject) { | ||
218 | + uniqueArray.push(uniqueObject[i]) | ||
219 | + } | ||
220 | + return uniqueArray | ||
221 | + } | ||
222 | + /** | ||
223 | + * 筛选指定年月日期 | ||
224 | + * @param {object} target 指定年月 | ||
225 | + * @param {array} dates 待筛选日期 | ||
226 | + */ | ||
227 | + filterDatesByYM(target, dates) { | ||
228 | + if (target) { | ||
229 | + const { year, month } = target | ||
230 | + const _dates = dates.filter( | ||
231 | + item => +item.year === +year && +item.month === +month | ||
232 | + ) | ||
233 | + return _dates | ||
234 | + } | ||
235 | + return dates | ||
236 | + } | ||
237 | + getWeekHeader(firstDayOfWeek) { | ||
238 | + let weeksCh = ['日', '一', '二', '三', '四', '五', '六'] | ||
239 | + if (firstDayOfWeek === 'Mon') { | ||
240 | + weeksCh = ['一', '二', '三', '四', '五', '六', '日'] | ||
241 | + } | ||
242 | + return weeksCh | ||
243 | + } | ||
244 | +} | ||
245 | + | ||
246 | +/** | ||
247 | + * 获取当前页面实例 | ||
248 | + */ | ||
249 | +export function getCurrentPage() { | ||
250 | + const pages = getCurrentPages() || [] | ||
251 | + const last = pages.length - 1 | ||
252 | + return pages[last] || {} | ||
253 | +} | ||
254 | + | ||
255 | +export function getComponentById(componentId) { | ||
256 | + const logger = new Logger() | ||
257 | + let page = getCurrentPage() || {} | ||
258 | + if (page.selectComponent && typeof page.selectComponent === 'function') { | ||
259 | + if (componentId) { | ||
260 | + return page.selectComponent(componentId) | ||
261 | + } else { | ||
262 | + logger.warn('请传入组件ID') | ||
263 | + } | ||
264 | + } else { | ||
265 | + logger.warn('该基础库暂不支持多个小程序日历组件') | ||
266 | + } | ||
267 | +} | ||
268 | + | ||
269 | +export const logger = new Logger() | ||
270 | +export const calendarGesture = new Gesture() | ||
271 | +export const dateUtil = new DateUtil() | ||
272 | +export const getCalendarData = (key, component) => | ||
273 | + new WxData(component).getData(key) | ||
274 | +export const setCalendarData = (data, component) => | ||
275 | + new WxData(component).setData(data) | ||
276 | +export const getCalendarConfig = component => | ||
277 | + getCalendarData('config', component) | ||
278 | +export const setCalendarConfig = (config, component) => | ||
279 | + setCalendarData( | ||
280 | + { | ||
281 | + config | ||
282 | + }, | ||
283 | + component | ||
284 | + ) |
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +export default class Logger { | ||
2 | + info(msg) { | ||
3 | + console.log( | ||
4 | + '%cInfo: %c' + msg, | ||
5 | + 'color:#FF0080;font-weight:bold', | ||
6 | + 'color: #FF509B' | ||
7 | + ) | ||
8 | + } | ||
9 | + warn(msg) { | ||
10 | + console.log( | ||
11 | + '%cWarn: %c' + msg, | ||
12 | + 'color:#FF6600;font-weight:bold', | ||
13 | + 'color: #FF9933' | ||
14 | + ) | ||
15 | + } | ||
16 | + tips(msg) { | ||
17 | + console.log( | ||
18 | + '%cTips: %c' + msg, | ||
19 | + 'color:#00B200;font-weight:bold', | ||
20 | + 'color: #00CC33' | ||
21 | + ) | ||
22 | + } | ||
23 | +} |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +class WxData { | ||
2 | + constructor(component) { | ||
3 | + this.Component = component | ||
4 | + } | ||
5 | + getData(key) { | ||
6 | + const data = this.Component.data | ||
7 | + if (!key) return data | ||
8 | + if (key.includes('.')) { | ||
9 | + let keys = key.split('.') | ||
10 | + const tmp = keys.reduce((prev, next) => { | ||
11 | + return prev[next] | ||
12 | + }, data) | ||
13 | + return tmp | ||
14 | + } else { | ||
15 | + return this.Component.data[key] | ||
16 | + } | ||
17 | + } | ||
18 | + setData(data) { | ||
19 | + return new Promise((resolve, reject) => { | ||
20 | + if (!data) return reject('no data to set') | ||
21 | + if (typeof data === 'object') { | ||
22 | + this.Component.setData(data, () => { | ||
23 | + resolve(data) | ||
24 | + }) | ||
25 | + } | ||
26 | + }) | ||
27 | + } | ||
28 | +} | ||
29 | + | ||
30 | +export default WxData |
config.js
1 | //域名要在小程序的管理平台配置好,如果出现调用时报错,无效的域名,可在微信开发工具左边点项目-》配置信息-》看一下配置的域名【request合法域名】有没有刷新下来,没有的话就点下面的刷新 | 1 | //域名要在小程序的管理平台配置好,如果出现调用时报错,无效的域名,可在微信开发工具左边点项目-》配置信息-》看一下配置的域名【request合法域名】有没有刷新下来,没有的话就点下面的刷新 |
2 | 2 | ||
3 | -let host = 'https://proxy.shunzhi.net/'; //正式 | 3 | +// let host = 'https://proxy.shunzhi.net/'; //正式 |
4 | +let host = 'https://proxy.shunzhi.net/card'; //正式 | ||
4 | 5 | ||
5 | let file = 'https://wxsxh.myjxt.com:51314/file-center/'; //图片上传 | 6 | let file = 'https://wxsxh.myjxt.com:51314/file-center/'; //图片上传 |
6 | 7 |
2.52 KB
2.9 KB
3.28 KB
12.7 KB
1.62 KB
4.08 KB
1.16 KB
5.09 KB
6.51 KB
4.32 KB
62.6 KB
3.82 KB
2.99 KB
4.35 KB
2.95 KB
84.5 KB
package-lock.json
1 | { | 1 | { |
2 | - "name": "sxhClockIn", | ||
3 | - "version": "2.0.0", | ||
4 | - "lockfileVersion": 2, | 2 | + "name": "sxh_clock_in", |
3 | + "version": "1.0.0", | ||
4 | + "lockfileVersion": 1, | ||
5 | "requires": true, | 5 | "requires": true, |
6 | - "packages": { | ||
7 | - "": { | ||
8 | - "name": "sxhClockIn", | ||
9 | - "version": "2.0.0", | ||
10 | - "license": "ISC", | ||
11 | - "dependencies": { | ||
12 | - "@vant/weapp": "^1.10.5" | ||
13 | - } | ||
14 | - }, | ||
15 | - "node_modules/@vant/weapp": { | ||
16 | - "version": "1.10.5", | ||
17 | - "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.10.5.tgz", | ||
18 | - "integrity": "sha512-bAHp9r0ZiRsOqPOLzQHI/ZvkAlXzol1/TFhM70MyghuxkzJTjcDUd8RIfLkCN3c1MCK/PfBGw2an8/afygftCg==" | ||
19 | - } | ||
20 | - }, | ||
21 | "dependencies": { | 6 | "dependencies": { |
22 | "@vant/weapp": { | 7 | "@vant/weapp": { |
23 | "version": "1.10.5", | 8 | "version": "1.10.5", |
24 | "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.10.5.tgz", | 9 | "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.10.5.tgz", |
25 | "integrity": "sha512-bAHp9r0ZiRsOqPOLzQHI/ZvkAlXzol1/TFhM70MyghuxkzJTjcDUd8RIfLkCN3c1MCK/PfBGw2an8/afygftCg==" | 10 | "integrity": "sha512-bAHp9r0ZiRsOqPOLzQHI/ZvkAlXzol1/TFhM70MyghuxkzJTjcDUd8RIfLkCN3c1MCK/PfBGw2an8/afygftCg==" |
11 | + }, | ||
12 | + "moment": { | ||
13 | + "version": "2.29.4", | ||
14 | + "resolved": "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz", | ||
15 | + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" | ||
26 | } | 16 | } |
27 | } | 17 | } |
28 | } | 18 | } |
package.json
@@ -4,7 +4,8 @@ | @@ -4,7 +4,8 @@ | ||
4 | "description": "计划管家", | 4 | "description": "计划管家", |
5 | "main": "app.js", | 5 | "main": "app.js", |
6 | "dependencies": { | 6 | "dependencies": { |
7 | - "@vant/weapp": "^1.10.5" | 7 | + "@vant/weapp": "^1.10.5", |
8 | + "moment": "^2.29.4" | ||
8 | }, | 9 | }, |
9 | "scripts": { | 10 | "scripts": { |
10 | "test": "echo \"Error: no test specified\" && exit 1" | 11 | "test": "echo \"Error: no test specified\" && exit 1" |
pages/index/achievement/achievement.js
1 | // pages/index/achievement/achievement.js | 1 | // pages/index/achievement/achievement.js |
2 | +// 引入插件安装器 | ||
3 | +import plugin from '../../../component/v2/plugins/index' | ||
4 | +import week from '../../../component/v2/plugins/week' | ||
5 | +import todo from '../../../component/v2/plugins/todo' | ||
6 | +import request from '../../../api/request.js' | ||
7 | +import moment from 'moment'; | ||
8 | +plugin | ||
9 | + .use(week) | ||
10 | + .use(todo) | ||
2 | Page({ | 11 | Page({ |
3 | 12 | ||
4 | /** | 13 | /** |
5 | * 页面的初始数据 | 14 | * 页面的初始数据 |
6 | */ | 15 | */ |
7 | data: { | 16 | data: { |
17 | + calendarConfig: { | ||
18 | + theme: 'elegant', | ||
19 | + weekMode: true, // 周视图模式 | ||
20 | + // highlightToday: true, // 是否高亮显示当天 | ||
21 | + hideHeader: true, // 隐藏日历头部操作栏 | ||
22 | + autoChoosedWhenJump: true, // 设置默认日期及跳转到指定日期后是否需要自动选中 | ||
23 | + defaultDate: moment(new Date().getTime()).format('YYYY-MM-DD'), // 默认选中指定某天,如需选中需配置 autoChoosedWhenJump: true | ||
24 | + }, | ||
25 | + isDisplay: false, | ||
26 | + calendar: {}, //日历 | ||
27 | + valueId: '', //任务ID | ||
28 | + taskVo: { | ||
29 | + allowRepairCard: 0, | ||
30 | + hasData: 0, | ||
31 | + statisticsUnit: "", | ||
32 | + submitCondition: "", | ||
33 | + id: 0, | ||
34 | + releaseTime: "", | ||
35 | + signTotal: 0, | ||
36 | + taskCycle: 0, | ||
37 | + taskDesc: "", | ||
38 | + taskFrequency: "", | ||
39 | + taskTitle: "", | ||
40 | + weekDay: "" | ||
41 | + }, | ||
42 | + resData: [], //成果数据 | ||
43 | + recordVo: { | ||
44 | + commitTime: "", | ||
45 | + files: [], | ||
46 | + signDate: "", | ||
47 | + taskRecordDesc: "", | ||
48 | + taskStatisticsParam: "" | ||
49 | + }, //成果数据当天 | ||
50 | + recordVoShow: false, | ||
51 | + dayMoment: 0, //数据月份 | ||
52 | + }, | ||
53 | + /** | ||
54 | + * 选择日期后执行的事件 | ||
55 | + */ | ||
56 | + afterTapDate(e) { | ||
57 | + let date = e.detail.date | ||
58 | + // let month = e.detail.month | ||
59 | + // let year = e.detail.year | ||
60 | + let recordVo = this.data.resData.eventDetails[date - 1].recordVo | ||
61 | + if (recordVo != null) { | ||
62 | + console.log('复制', recordVo) | ||
63 | + this.setData({ | ||
64 | + recordVo: recordVo | ||
65 | + }) | ||
66 | + this.setData({ | ||
67 | + recordVoShow: true | ||
68 | + }) | ||
69 | + } else { | ||
70 | + this.setData({ | ||
71 | + recordVoShow: false | ||
72 | + }) | ||
73 | + } | ||
74 | + }, | ||
75 | + //获取信息 | ||
76 | + getInfo(doday, isOne = 0) { | ||
77 | + request({ | ||
78 | + url: `/wx/task/getSignRecord`, | ||
79 | + method: 'get', | ||
80 | + data: { | ||
81 | + // wx.getStorageSync('userInfo_id'), | ||
82 | + "taskId": this.data.valueId, | ||
83 | + "signDate": doday | ||
84 | + }, | ||
85 | + }).then(res => { | ||
86 | + if (res.code == 0) { | ||
87 | + this.setData({ | ||
88 | + resData: res.data | ||
89 | + }) | ||
90 | + this.getV2(res.data) | ||
91 | + if (isOne == 1) { | ||
92 | + let e = { | ||
93 | + detail: { | ||
94 | + date: moment().date(), | ||
95 | + month: moment().month() + 1, | ||
96 | + year: moment().year() | ||
97 | + } | ||
98 | + } | ||
99 | + this.afterTapDate(e) | ||
100 | + } | ||
101 | + } else { | ||
102 | + wx.showToast({ | ||
103 | + title: res.msg, | ||
104 | + icon: 'none' | ||
105 | + }) | ||
106 | + } | ||
107 | + }) | ||
108 | + }, | ||
109 | + //初始化日历 | ||
110 | + initialize() { | ||
111 | + // 设置待办 | ||
112 | + this.setData({ | ||
113 | + 'calendar': this.selectComponent('#calendar').calendar | ||
114 | + }) | ||
115 | + }, | ||
116 | + //显示日历 | ||
117 | + getV2(resData) { | ||
118 | + this.setData({ | ||
119 | + taskVo: resData.taskVo | ||
120 | + }) | ||
121 | + // const calendar = this.selectComponent('#calendar').calendar | ||
122 | + this.data.calendar.setTodos({ | ||
123 | + // 待办点标记设置 | ||
124 | + pos: 'bottom', // 待办点标记位置 ['top', 'bottom'] | ||
125 | + dotColor: 'red', // 待办点标记颜色 | ||
126 | + circle: false, // 待办圆圈标记设置(如圆圈标记已签到日期),该设置与点标记设置互斥 | ||
127 | + showLabelAlways: true, // 点击时是否显示待办事项(圆点/文字),在 circle 为 true 及当日历配置 showLunar 为 true 时,此配置失效 | ||
128 | + dates: resData.eventDetails | ||
129 | + }) | ||
8 | }, | 130 | }, |
9 | - | ||
10 | /** | 131 | /** |
11 | * 生命周期函数--监听页面加载 | 132 | * 生命周期函数--监听页面加载 |
12 | */ | 133 | */ |
13 | onLoad(options) { | 134 | onLoad(options) { |
14 | - | 135 | + this.setData({ |
136 | + valueId: options.valueId | ||
137 | + }) | ||
15 | }, | 138 | }, |
16 | // 统一返回 | 139 | // 统一返回 |
17 | handleBack() { | 140 | handleBack() { |
18 | wx.navigateBack() | 141 | wx.navigateBack() |
19 | }, | 142 | }, |
20 | /** | 143 | /** |
21 | - * 用户点击右上角分享 | 144 | + * 生命周期函数--监听页面初次渲染完成 |
22 | */ | 145 | */ |
23 | - onShareAppMessage() { | ||
24 | - | ||
25 | - } | 146 | + onReady() { |
147 | + this.initialize() | ||
148 | + this.getInfo(moment(new Date().getTime()).format('YYYY-MM-DD'), 1) | ||
149 | + }, | ||
26 | }) | 150 | }) |
27 | \ No newline at end of file | 151 | \ No newline at end of file |
pages/index/achievement/achievement.json
1 | { | 1 | { |
2 | "usingComponents": { | 2 | "usingComponents": { |
3 | - "van-icon": "@vant/weapp/icon/index" | 3 | + "van-icon": "@vant/weapp/icon/index", |
4 | + "calendar": "/component/v2/index", | ||
5 | + "van-popup": "@vant/weapp/popup/index", | ||
6 | + "van-field": "@vant/weapp/field/index", | ||
7 | + "van-image": "@vant/weapp/image/index", | ||
8 | + "van-button": "@vant/weapp/button/index" | ||
4 | }, | 9 | }, |
5 | - "navigationStyle": "custom" | 10 | + "navigationBarTitleText": "我的成果" |
6 | } | 11 | } |
7 | \ No newline at end of file | 12 | \ No newline at end of file |
pages/index/achievement/achievement.wxml
1 | <!--pages/index/achievement/achievement.wxml--> | 1 | <!--pages/index/achievement/achievement.wxml--> |
2 | <view class="punch_detail"> | 2 | <view class="punch_detail"> |
3 | - <!-- 顶部统一返回 --> | ||
4 | - <view class="navigation_back" bindtap="handleBack"> | ||
5 | - <van-icon name="arrow-left" /> | 3 | + <calendar id="calendar" config="{{calendarConfig}}" bind:afterTapDate="afterTapDate"/> |
4 | + <!-- <view class="btn" bindtap="getInfo">按钮</view> --> | ||
5 | + <view class="line_grey"></view> | ||
6 | + <view class="card"> | ||
7 | + <view class="card_title">{{taskVo.taskTitle}}</view> | ||
8 | + <view class="card_flex"> | ||
9 | + <view class="flex_grey">已进行 {{taskVo.signTotal +' / ' +taskVo.taskCycle}} 天</view> | ||
10 | + <view class="flex_grey">打卡频次 : {{taskVo.taskFrequency}}</view> | ||
11 | + <view class="flex_grey">{{taskVo.allowRepairCard == 1 ?'允许补卡': '不允许补卡'}}</view> | ||
12 | + </view> | ||
13 | + <view class="card_context">{{taskVo.taskDesc}}</view> | ||
14 | + <view class="grey_font"> | ||
15 | + <view>我发布与{{taskVo.weekDay}} {{taskVo.releaseTime}}</view> | ||
16 | + <view class="grey_font_bottom"></view> | ||
17 | + </view> | ||
6 | </view> | 18 | </view> |
7 | - <image class="temporary" src="/img/_check_in5.png" mode="widthFix" alt="" /> | ||
8 | 19 | ||
20 | + <view class="grey_line"></view> | ||
21 | + <view class="box" wx:if="{{recordVoShow}}"> | ||
22 | + <view class="box_title">打卡成果</view> | ||
23 | + <view class="box_blue" wx:if="{{recordVo.hasData==1}}">本次打卡坚持了<span>{{recordVo.taskStatisticsParam}}{{taskVo.statisticsUnit}}</span></view> | ||
24 | + <view class="box_grey">"{{recordVo.taskRecordDesc}}"</view> | ||
25 | + <view class="box_pic"> | ||
26 | + <view class="box_img" wx:for="{{recordVo.files}}" wx:key="index" wx:for-item="value"> | ||
27 | + <van-image width="100%" height="26vw" fit="fill" src="{{value}}" /> | ||
28 | + </view> | ||
29 | + </view> | ||
30 | + </view> | ||
9 | </view> | 31 | </view> |
10 | \ No newline at end of file | 32 | \ No newline at end of file |
pages/index/achievement/achievement.wxss
1 | /* pages/index/achievement/achievement.wxss */ | 1 | /* pages/index/achievement/achievement.wxss */ |
2 | +.btn { | ||
3 | + width: 20vw; | ||
4 | + height: 20vw; | ||
5 | + background-color: aqua; | ||
6 | + font-size: 5vw; | ||
7 | +} | ||
8 | +.line_grey { | ||
9 | + width: 90vw; | ||
10 | + height: 1px; | ||
11 | + background-color: #999; | ||
12 | + margin: 10px 5vw 20px; | ||
13 | +} | ||
14 | +.card { | ||
15 | + width: 92vw; | ||
16 | + margin-left: 4vw; | ||
17 | +} | ||
18 | +.card_title { | ||
19 | + font-size: 18px; | ||
20 | + color: #556191; | ||
21 | + margin: 15px 0; | ||
22 | +} | ||
23 | +.card_flex { | ||
24 | + display: flex; | ||
25 | +} | ||
26 | +.flex_grey { | ||
27 | + padding: 7px 10px; | ||
28 | + box-sizing: border-box; | ||
29 | + margin: 0 5px 10px 0; | ||
30 | + font-size: 13px; | ||
31 | + background-color: #F4F4F4; | ||
32 | + color: #666666; | ||
33 | + border-radius: 3px; | ||
34 | +} | ||
35 | +.card_context { | ||
36 | + font-size: 16px; | ||
37 | + margin: 10px 0; | ||
38 | +} | ||
39 | +.grey_font { | ||
40 | + font-size: 14px; | ||
41 | + color: #999999; | ||
42 | + margin: 20px 0; | ||
43 | +} | ||
44 | +.grey_font_bottom { | ||
45 | + margin-top: 5px; | ||
46 | +} | ||
47 | +.btn_box { | ||
48 | + display: flex; | ||
49 | + justify-content: space-around; | ||
50 | + position: fixed; | ||
51 | + bottom: 50px; | ||
52 | + width: 100vw; | ||
53 | +} | ||
54 | +.pop_title { | ||
55 | + font-size: 18px; | ||
56 | + font-weight: bold; | ||
57 | + text-align: center; | ||
58 | + margin: 20px 0; | ||
59 | +} | ||
60 | +.pop_flex { | ||
61 | + display: flex; | ||
62 | + justify-content: space-between; | ||
63 | + align-items: center; | ||
64 | + padding: 0 20px; | ||
65 | + box-sizing: border-box; | ||
66 | +} | ||
67 | +.pop_cell { | ||
68 | + width: 40vw; | ||
69 | + display: flex; | ||
70 | + align-items: center; | ||
71 | +} | ||
72 | +.pop_fz { | ||
73 | + width: 70px; | ||
74 | +} | ||
75 | +.pop_btn { | ||
76 | + position: absolute; | ||
77 | + bottom: 30px; | ||
78 | + width: 90vw; | ||
79 | + margin: 0 5vw; | ||
80 | +} | ||
81 | +.pop_tip { | ||
82 | + position: absolute; | ||
83 | + bottom: 90px; | ||
84 | + width: 90vw; | ||
85 | + margin: 0 5vw; | ||
86 | +} | ||
87 | +.pop_pic { | ||
88 | + width: 70px; | ||
89 | + height: 30px; | ||
90 | +} | ||
91 | +.grey_line { | ||
92 | + width: 90vw; | ||
93 | + height: 1px; | ||
94 | + margin: 20vw 5vw 10vw ; | ||
95 | + background-color: #999; | ||
96 | +} | ||
97 | +.box { | ||
98 | + padding: 0 5vw; | ||
99 | + box-sizing: border-box; | ||
100 | + margin-bottom: 20px; | ||
101 | +} | ||
102 | +.box_title { | ||
103 | + font-size: 20px; | ||
104 | + font-weight: bold; | ||
105 | +} | ||
106 | +.box_blue { | ||
107 | + padding: 7px 10px; | ||
108 | + box-sizing: border-box; | ||
109 | + background-color: #EDF5FF; | ||
110 | + color: #333333; | ||
111 | + margin: 15px 0; | ||
112 | + border-radius: 10px; | ||
113 | +} | ||
114 | +.box_blue span { | ||
115 | + color: #3A86F5; | ||
116 | +} | ||
117 | +.box_grey { | ||
118 | + padding: 18px 10px; | ||
119 | + box-sizing: border-box; | ||
120 | + background-color: #FBFBFB; | ||
121 | + color: #666666 ; | ||
122 | + margin: 15px 0; | ||
123 | + border-radius: 10px; | ||
124 | +} | ||
125 | +.box_pic { | ||
126 | + display: flex; | ||
127 | + justify-content: space-between; | ||
128 | + flex-wrap: wrap; | ||
129 | +} | ||
130 | +.box_img { | ||
131 | + width: 26vw; | ||
132 | + margin:0 0 10px; | ||
133 | + border-radius: 10px; | ||
134 | +} | ||
2 | \ No newline at end of file | 135 | \ No newline at end of file |
pages/index/index.js
@@ -4,63 +4,73 @@ import request from '../../api/request.js' | @@ -4,63 +4,73 @@ import request from '../../api/request.js' | ||
4 | 4 | ||
5 | Page({ | 5 | Page({ |
6 | data: { | 6 | data: { |
7 | - showAdd: false, //新建打卡 | ||
8 | - tabindex: 1, | 7 | + active: 1, |
8 | + taskList: [] | ||
9 | // bannerList: [], // 轮播图 | 9 | // bannerList: [], // 轮播图 |
10 | }, | 10 | }, |
11 | - /** | ||
12 | - * 生命周期函数--监听页面加载 | ||
13 | - */ | ||
14 | - onLoad: function (options) { | ||
15 | - // this.getBannerList() //获取banner | ||
16 | - }, | ||
17 | - onShow:function (options) { | ||
18 | - this.setData({ | ||
19 | - showAdd:false | ||
20 | - }) | ||
21 | - }, | ||
22 | - // 排行榜 | ||
23 | - handleRank(){ | ||
24 | - wx.navigateTo({ | ||
25 | - url: '/pages/index/rank/rank', | ||
26 | - }) | ||
27 | - }, | ||
28 | - handleTab1() { | ||
29 | - this.setData({ | ||
30 | - tabindex: 1 | ||
31 | - }) | ||
32 | - }, | ||
33 | - handleTab2() { | 11 | + checkTabs(e) { |
12 | + let index = e.currentTarget.dataset.index | ||
34 | this.setData({ | 13 | this.setData({ |
35 | - tabindex: 2 | ||
36 | - }) | 14 | + active: index |
15 | + }) //修改参数 | ||
37 | }, | 16 | }, |
38 | - handleAdd() { | ||
39 | - this.setData({ | ||
40 | - showAdd: true | 17 | + |
18 | + //打卡记录列表 | ||
19 | + getTaskList() { | ||
20 | + request({ | ||
21 | + url: `/wx/task/cardTaskList`, | ||
22 | + method: 'post', | ||
23 | + data: { | ||
24 | + "oneselfFlag": 1, | ||
25 | + "page": 1, | ||
26 | + "pageSize": 999, | ||
27 | + "userId": wx.getStorageSync("userInfo_id") | ||
28 | + }, | ||
29 | + }).then(res => { | ||
30 | + if (res.code == 0) { | ||
31 | + this.setData({ | ||
32 | + taskList: res.rows | ||
33 | + }) | ||
34 | + } else { | ||
35 | + wx.showToast({ | ||
36 | + title: res.msg, | ||
37 | + icon: 'none', | ||
38 | + duration: 1500 | ||
39 | + }) | ||
40 | + } | ||
41 | }) | 41 | }) |
42 | }, | 42 | }, |
43 | - closeAdd() { | ||
44 | - this.setData({ | ||
45 | - showAdd: false | 43 | + |
44 | + //查看排行榜 | ||
45 | + toRank() { | ||
46 | + wx.switchTab({ | ||
47 | + url: './rank/rank', | ||
46 | }) | 48 | }) |
47 | }, | 49 | }, |
48 | - // 打卡成果 | ||
49 | - handleAchievement(){ | 50 | + |
51 | + // 打卡成果 | ||
52 | + handleAchievement(e){ | ||
50 | wx.navigateTo({ | 53 | wx.navigateTo({ |
51 | - url: '/pages/index/achievement/achievement', | 54 | + url: '/pages/index/achievement/achievement?valueId='+e.currentTarget.dataset.valueid , |
52 | }) | 55 | }) |
53 | }, | 56 | }, |
54 | // 去打卡 | 57 | // 去打卡 |
55 | - handleDetail(){ | 58 | + handleDetail(e){ |
59 | + let eData = e.currentTarget.dataset | ||
56 | wx.navigateTo({ | 60 | wx.navigateTo({ |
57 | - url: '/pages/index/punchDetail/punchDetail', | 61 | + url: '/pages/index/punchDetail/punchDetail?valueId='+eData.valueid , |
58 | }) | 62 | }) |
63 | + }, | ||
64 | + /** | ||
65 | + * 生命周期函数--监听页面加载 | ||
66 | + */ | ||
67 | + onLoad: function (options) { | ||
68 | + // this.getBannerList() //获取banner | ||
59 | }, | 69 | }, |
60 | - // 自定义模板 | ||
61 | - handleNewPunch(){ | ||
62 | - wx.navigateTo({ | ||
63 | - url: '/pages/index/newPunch/newPunch', | 70 | + onShow: function (options) { |
71 | + this.getTaskList() | ||
72 | + this.setData({ | ||
73 | + showAdd: false | ||
64 | }) | 74 | }) |
65 | }, | 75 | }, |
66 | // 获取banner图 | 76 | // 获取banner图 |
pages/index/index.json
1 | { | 1 | { |
2 | "usingComponents": { | 2 | "usingComponents": { |
3 | - "van-popup": "@vant/weapp/popup/index" | 3 | + "van-popup": "@vant/weapp/popup/index", |
4 | + "van-tab": "@vant/weapp/tab/index", | ||
5 | + "van-tabs": "@vant/weapp/tabs/index", | ||
6 | + "van-progress": "@vant/weapp/progress/index" | ||
4 | }, | 7 | }, |
5 | "navigationBarTextStyle": "black", | 8 | "navigationBarTextStyle": "black", |
6 | - "navigationStyle": "custom" | 9 | + "navigationBarTitleText": "打卡" |
7 | } | 10 | } |
8 | \ No newline at end of file | 11 | \ No newline at end of file |
pages/index/index.wxml
1 | <view class="main"> | 1 | <view class="main"> |
2 | - <image class="temporary" hidden="{{tabindex==2}}" src="/img/_index1.png" mode="widthFix" alt="" /> | ||
3 | - <image class="temporary" hidden="{{tabindex==1}}" src="/img/_index2.png" mode="widthFix" alt="" /> | ||
4 | - <!-- 排行榜 --> | ||
5 | - <text class="temporary_box" style="width: 370rpx;height: 100rpx;position: absolute;top: 192rpx;left: 20rpx;" bindtap="handleRank"></text> | ||
6 | - <!-- 两个tab --> | ||
7 | - <text class="temporary_box" style="width: 160rpx;height: 80rpx;position: absolute;top: 300rpx;left: 32rpx;" bindtap="handleTab1"></text> | ||
8 | - <text class="temporary_box" style="width: 160rpx;height: 80rpx;position: absolute;top: 300rpx;left: 200rpx;" bindtap="handleTab2"></text> | ||
9 | - <!-- 打卡成果 --> | ||
10 | - <text class="temporary_box" style="width: 350rpx;height: 100rpx;position: absolute;top: 1000rpx;left: 20rpx;" bindtap="handleAchievement"></text> | ||
11 | - <!-- 去打卡 --> | ||
12 | - <text class="temporary_box" style="width: 350rpx;height: 100rpx;position: absolute;top: 1000rpx;right: 20rpx;" bindtap="handleDetail"></text> | ||
13 | - <!-- 新建打卡 --> | ||
14 | - <text class="temporary_box" style="width: 120rpx;height: 120rpx;position: absolute;top: 1200rpx;right: 20rpx;" bindtap="handleAdd"></text> | ||
15 | - <van-popup show="{{ showAdd }}" position="bottom" custom-style="height: 80%;" bind:close="closeAdd"> | ||
16 | - <image class="temporary" src="/img/_index3.png" mode="widthFix" alt="" /> | ||
17 | - <!-- 自定义模板 --> | ||
18 | - <text class="temporary_box" style="width: 180rpx;height: 220rpx;position: absolute;top: 364rpx;left: 20rpx;" bindtap="handleNewPunch"></text> | ||
19 | - </van-popup> | 2 | + <!-- <view class="bck" style="background-image: url('https://szyundisk.oss-cn-hangzhou.aliyuncs.com/null/67c3d489-6635-4bef-90f2-03553f56fd0a.png')"> |
3 | + </view> --> | ||
4 | + <!-- 打卡排行榜 --> | ||
5 | + <!-- <view class="box"> | ||
6 | + <view class="title_name"> | ||
7 | + </view> | ||
8 | + <vidw class="title_view" bindtap="toRank">立即查看</vidw> | ||
9 | + <view class="tabs_css"> | ||
10 | + <view class="{{active == 1?'tabs_item check' :'tabs_item no_check'}}" bindtap="checkTabs" data-index='1'>我的打卡</view> | ||
11 | + <view class="{{active == 2?'tabs_item check' :'tabs_item no_check'}} " bindtap='checkTabs' data-index='2'>我创建的</view> | ||
12 | + </view> | ||
13 | + <view class="tabs_div"></view> | ||
14 | + </view> --> | ||
15 | + <view class="white_box"> | ||
16 | + <view class="card" wx:for="{{taskList}}" wx:key="index" wx:for-item="value"> | ||
17 | + <view class="card_title"> | ||
18 | + <view class="title_L"> | ||
19 | + <image class="title_pic" src="/img/answer/bj.png" alt="" /> | ||
20 | + </view> | ||
21 | + <view class="title_R"> | ||
22 | + <view>{{value.taskTitle}}</view> | ||
23 | + <view class="grey_font">开始时间 {{value.startDate}}</view> | ||
24 | + </view> | ||
25 | + </view> | ||
26 | + <view class="day_font">{{value.taskDesc}}</view> | ||
27 | + <!-- <view class="day_font2">已坚持打卡 | ||
28 | + <text class="day_font2_large">1/50 </text>天 | ||
29 | + </view> --> | ||
30 | + <view> | ||
31 | + <van-progress percentage="50" color='#3F5EFF' stroke-width="13" pivot-text=' ' /> | ||
32 | + </view> | ||
33 | + <view class="flex_font"> | ||
34 | + <text class="grey_flex">打卡频次:</text> | ||
35 | + {{value.taskFrequency}} | ||
36 | + </view> | ||
37 | + <view class="flex_font" wx:if="{{value.submitCondition != null}}"> | ||
38 | + <text class="grey_flex">打卡要求:</text> | ||
39 | + {{ value.submitCondition == '无限制' ? '无限制': '需要 '+value.submitCondition}} | ||
40 | + </view> | ||
41 | + <view class="flex_font"> | ||
42 | + <view class="grey_flex">其他:</view> | ||
43 | + {{value.allowRepairCard == 1 ? '允许补卡': '不允许补卡'}} | ||
44 | + </view> | ||
45 | + <view class="grey_line"></view> | ||
46 | + <view class="blue_font"> | ||
47 | + <view bindtap="handleAchievement" data-valueId="{{value.id}}">打卡成果</view> | ||
48 | + <view class="blue_line"></view> | ||
49 | + <view bindtap="handleDetail" data-valueId="{{value.id}}">去打卡</view> | ||
50 | + </view> | ||
51 | + </view> | ||
52 | + </view> | ||
20 | 53 | ||
21 | </view> | 54 | </view> |
22 | \ No newline at end of file | 55 | \ No newline at end of file |
pages/index/index.wxss
@@ -0,0 +1,196 @@ | @@ -0,0 +1,196 @@ | ||
1 | +.bck { | ||
2 | + position: absolute; | ||
3 | + top: 0; | ||
4 | + left: 0; | ||
5 | + width: 100%; | ||
6 | + height: 250px; | ||
7 | + z-index: -1; | ||
8 | + background-size: 100% 100%; | ||
9 | +} | ||
10 | + | ||
11 | +.box { | ||
12 | + padding: 100px 7vw 0; | ||
13 | + box-sizing: border-box; | ||
14 | +} | ||
15 | + | ||
16 | +.title_name { | ||
17 | + font-size: 7vw; | ||
18 | + font-weight: bold; | ||
19 | + letter-spacing: 1.5vw; | ||
20 | + color: #fff; | ||
21 | + margin-bottom: 20px; | ||
22 | +} | ||
23 | + | ||
24 | +.title_view { | ||
25 | + height: 20px; | ||
26 | + font-size: 4.8vw; | ||
27 | + letter-spacing: 0.5vw; | ||
28 | + color: #fff; | ||
29 | + opacity: 0.7; | ||
30 | +} | ||
31 | + | ||
32 | +.tabs_css { | ||
33 | + margin: 30px 0; | ||
34 | + display: flex; | ||
35 | +} | ||
36 | +.tabs_div { | ||
37 | + margin: 30px 0; | ||
38 | +} | ||
39 | + | ||
40 | +.tabs_item { | ||
41 | + margin-right: 20px; | ||
42 | + font-size: 4.3vw; | ||
43 | + color: #fff; | ||
44 | +} | ||
45 | + | ||
46 | +.check {} | ||
47 | + | ||
48 | +.no_check { | ||
49 | + opacity: 0.6; | ||
50 | +} | ||
51 | + | ||
52 | +/**/ | ||
53 | +.white_box { | ||
54 | + width: 100vw; | ||
55 | + min-height: 550px; | ||
56 | + /* background-color: rebeccapurple; */ | ||
57 | + background-color: #F5F6FA; | ||
58 | + border-top-left-radius: 8vw; | ||
59 | + border-top-right-radius: 8vw; | ||
60 | + padding: 10vw 5vw; | ||
61 | + box-sizing: border-box; | ||
62 | +} | ||
63 | + | ||
64 | +.card { | ||
65 | + width: 90vw; | ||
66 | + background-color: #fff; | ||
67 | + border-radius: 8vw; | ||
68 | + padding: 8vw 7vw; | ||
69 | + margin-bottom: 30px; | ||
70 | + box-sizing: border-box; | ||
71 | + box-shadow: 1px 1px 1px 1px rgb(196, 196, 196); | ||
72 | +} | ||
73 | + | ||
74 | +.card_title { | ||
75 | + display: flex; | ||
76 | +} | ||
77 | + | ||
78 | +.title_L { | ||
79 | + flex-shrink: 0; | ||
80 | + width: 50px; | ||
81 | + height: 50px; | ||
82 | + margin-right: 15px; | ||
83 | +} | ||
84 | + | ||
85 | +.title_pic { | ||
86 | + width: 100%; | ||
87 | + height: 100%; | ||
88 | +} | ||
89 | + | ||
90 | +.title_R { | ||
91 | + height: 50px; | ||
92 | + display: flex; | ||
93 | + align-content: space-between; | ||
94 | + flex-wrap: wrap; | ||
95 | + font-size: 4.6vw; | ||
96 | +} | ||
97 | + | ||
98 | +.grey_font { | ||
99 | + width: 100%; | ||
100 | + color: #999; | ||
101 | + font-size: 3.8vw; | ||
102 | +} | ||
103 | + | ||
104 | +.day_font { | ||
105 | + margin: 20px 0 20px; | ||
106 | + letter-spacing: 0.2vw; | ||
107 | + font-size: 4vw; | ||
108 | +} | ||
109 | + | ||
110 | +.day_font2 { | ||
111 | + margin: 20px 0; | ||
112 | + letter-spacing: 0.2vw; | ||
113 | + font-size: 3.8vw; | ||
114 | +} | ||
115 | + | ||
116 | +.day_font2_large { | ||
117 | + font-size: 5.5vw; | ||
118 | + font-weight: bold; | ||
119 | +} | ||
120 | + | ||
121 | +.flex_font { | ||
122 | + font-size: 3.5vw; | ||
123 | + margin: 20px 0; | ||
124 | + display: flex; | ||
125 | +} | ||
126 | + | ||
127 | +.grey_flex { | ||
128 | + width: 80px; | ||
129 | + color: #999; | ||
130 | +} | ||
131 | + | ||
132 | +.grey_line { | ||
133 | + width: 100%; | ||
134 | + height: 1px; | ||
135 | + background-color: #E5E5E5; | ||
136 | +} | ||
137 | + | ||
138 | +.blue_line { | ||
139 | + width: 1px; | ||
140 | + height: 20px; | ||
141 | + background-color: #EAEAEA; | ||
142 | +} | ||
143 | + | ||
144 | +.blue_font { | ||
145 | + display: flex; | ||
146 | + justify-content: space-around; | ||
147 | + margin-top: 20px; | ||
148 | + font-size: 4.1vw; | ||
149 | + color: #4C92F9; | ||
150 | +} | ||
151 | + | ||
152 | +.blue_tip { | ||
153 | + position: fixed; | ||
154 | + bottom: 40px; | ||
155 | + right: 3vw; | ||
156 | +} | ||
157 | + | ||
158 | +.img_tip { | ||
159 | + width: 70px; | ||
160 | + height: 70px; | ||
161 | +} | ||
162 | + | ||
163 | +.pop_card { | ||
164 | + padding: 5vw; | ||
165 | + box-sizing: border-box; | ||
166 | +} | ||
167 | + | ||
168 | +.pop_title { | ||
169 | + font-size: 4.8vw; | ||
170 | + font-weight: bold; | ||
171 | + letter-spacing: 1px; | ||
172 | + margin-bottom: 30px; | ||
173 | +} | ||
174 | + | ||
175 | +.tem_box { | ||
176 | + display: flex; | ||
177 | + flex-wrap: wrap; | ||
178 | +} | ||
179 | + | ||
180 | +.tem_item { | ||
181 | + width: 23vw; | ||
182 | + height: 170px; | ||
183 | + text-align: center; | ||
184 | + margin: 0 3vw 30px; | ||
185 | +} | ||
186 | + | ||
187 | +.tem_pic { | ||
188 | + width: 23vw; | ||
189 | + height: 120px; | ||
190 | + border-radius: 10px; | ||
191 | +} | ||
192 | + | ||
193 | +.tem_font { | ||
194 | + font-size: 3.9vw; | ||
195 | + margin-top: 10px; | ||
196 | +} | ||
0 | \ No newline at end of file | 197 | \ No newline at end of file |
pages/index/newPunch/newPunch.js
1 | // pages/index/rank/rank.js | 1 | // pages/index/rank/rank.js |
2 | +import request from '../../../api/request.js' | ||
3 | +import moment from 'moment'; | ||
2 | Page({ | 4 | Page({ |
3 | 5 | ||
4 | /** | 6 | /** |
5 | * 页面的初始数据 | 7 | * 页面的初始数据 |
6 | */ | 8 | */ |
7 | data: { | 9 | data: { |
10 | + tempId: 0, | ||
11 | + form: { | ||
12 | + taskTitle: '', //任务标题 | ||
13 | + taskDesc: '', //任务描述内容 | ||
14 | + allowRepairCard: 2, //是否允许补卡 1是 2否 | ||
15 | + hasData: 2, //是否需要提交数据 1是 2否 | ||
16 | + // id: '', // 任务ID | ||
17 | + lackNum: '', // 缺卡次数 | ||
18 | + remindTime: '', // 打卡提醒时间点 | ||
19 | + startDate: '', // 打卡开始时间 | ||
20 | + statisticsUnit: '', // 统计单位 hasData=1 时,必传 | ||
21 | + submitCondition: '', //提交包含条件:图片、视频、音频 | ||
22 | + taskCycle: '', //打卡周期 | ||
23 | + taskFileUrl: [], //任务文件(含多个) | ||
24 | + taskFrequency: '', //打卡频次 | ||
25 | + userId: '', //所属用户ID | ||
26 | + }, | ||
27 | + fileList: [], | ||
28 | + //弹出层 | ||
29 | + //统计单位 | ||
30 | + unitShow: false, | ||
31 | + columnsUnit: ['分钟', '小时', '个', '篇', '本', '张', '页', '次'], | ||
32 | + //开始时间 | ||
33 | + startTimeShow: false, | ||
34 | + columnsStartTime: ['9', '10', '11', '12'], | ||
35 | + minDate: new Date().getTime(), | ||
36 | + currentDate: new Date().getTime(), | ||
37 | + formatter(type, value) { | ||
38 | + if (type === 'year') { | ||
39 | + return `${value}年`; | ||
40 | + } | ||
41 | + if (type === 'month') { | ||
42 | + return `${value}月`; | ||
43 | + } | ||
44 | + return value; | ||
45 | + }, | ||
46 | + //打卡周期 | ||
47 | + clockCycleShow: false, | ||
48 | + columnsClockCycle: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10','11', '12', '13', '14', '15', '16', '17', '18', '19', '20','21', '22', '23', '24', '25', '26', '27', '28', '29', '30','31', | ||
49 | + '32', '33', '34', '35', '36', '37', '38', '39', '40','41', | ||
50 | + '42', '43', '44', '45', '46', '47', '48', '49', '40','51', | ||
51 | + '52', '53', '54', '55', '56', '57', '58', '59', '60','61', | ||
52 | + '62', '63', '64', '65', '66', '67', '68', '69', '70','71', | ||
53 | + '72', '73', '74', '75', '76', '77', '78', '79', '80','81', | ||
54 | + '82', '83', '84', '85', '86', '87', '88', '89', '90'], | ||
55 | + //打卡频次 | ||
56 | + clockRateShow: false, | ||
57 | + columnsClockRate: ['每天', '7天', '一个月'], | ||
58 | + //打卡提醒 | ||
59 | + clockRemindShow: false, | ||
60 | + columnsClockRemind: [ | ||
61 | + { | ||
62 | + values: ['每天','周一', '周二', '周三', '周四', '周五', '周六', '周日'], | ||
63 | + defaultIndex: 2, | ||
64 | + }, | ||
65 | + // 第二列 | ||
66 | + { | ||
67 | + values: ['8:00', '9:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00'], | ||
68 | + defaultIndex: 1, | ||
69 | + }, | ||
70 | + ], | ||
71 | + //打卡缺卡提醒 | ||
72 | + clockLackShow: false, | ||
73 | + columnsClockLack: [1,2,3], | ||
74 | + //必须包含 | ||
75 | + containShow: false, | ||
76 | + columnsContain: ['无限制','图片'], | ||
77 | + }, | ||
78 | + //获取模板详情 / 空模板 | ||
79 | + getDetail() { | ||
80 | + request({ | ||
81 | + url: `/wx/temp/getTempDetail`, | ||
82 | + method: 'get', | ||
83 | + data: { | ||
84 | + "tempId": this.data.tempId, | ||
85 | + }, | ||
86 | + }).then(res => { | ||
87 | + if (res.code == 0) { | ||
88 | + const data = res.data | ||
89 | + this.setData({ | ||
90 | + 'form.taskTitle': data.taskTitle | ||
91 | + }) | ||
92 | + this.setData({ | ||
93 | + 'form.taskDesc': data.taskDesc | ||
94 | + }) | ||
95 | + this.setData({ | ||
96 | + 'form.allowRepairCard': data.allowRepairCard | ||
97 | + }) | ||
98 | + this.setData({ | ||
99 | + 'form.hasData': data.hasData | ||
100 | + }) | ||
101 | + this.setData({ | ||
102 | + 'form.lackNum': data.lackNum | ||
103 | + }) | ||
104 | + this.setData({ | ||
105 | + 'form.remindTime': data.remindTime | ||
106 | + }) | ||
107 | + this.setData({ | ||
108 | + 'form.startDate': moment(new Date().getTime()).format('YYYY-MM-DD') | ||
109 | + }) | ||
110 | + this.setData({ | ||
111 | + 'form.statisticsUnit': data.statisticsUnit | ||
112 | + }) | ||
113 | + this.setData({ | ||
114 | + 'form.submitCondition': data.submitCondition | ||
115 | + }) | ||
116 | + this.setData({ | ||
117 | + 'form.taskCycle': data.taskCycle | ||
118 | + }) | ||
119 | + this.setData({ | ||
120 | + 'form.taskFileUrl': [] | ||
121 | + }) | ||
122 | + this.setData({ | ||
123 | + 'form.taskFrequency': data.taskFrequency | ||
124 | + }) | ||
125 | + } else { | ||
126 | + wx.showToast({ | ||
127 | + title: res.msg, | ||
128 | + icon: 'none', | ||
129 | + duration: 1000 | ||
130 | + }) | ||
131 | + } | ||
132 | + }) | ||
133 | + }, | ||
134 | + //输入 | ||
135 | + onfieldChange(e) { | ||
136 | + this.setData({ | ||
137 | + 'form.taskTitle': e.detail | ||
138 | + }) | ||
139 | + }, | ||
140 | + //输入 | ||
141 | + onfieldDescChange(e) { | ||
142 | + this.setData({ | ||
143 | + 'form.taskDesc': e.detail | ||
144 | + }) | ||
145 | + }, | ||
146 | + //开关 | ||
147 | + onSwitch(e) { | ||
148 | + console.log(e) | ||
149 | + this.setData({ | ||
150 | + 'form.hasData': e.detail | ||
151 | + }) | ||
152 | + }, | ||
153 | + onChange(e) { | ||
154 | + console.log(e) | ||
155 | + this.setData({ | ||
156 | + 'form.allowRepairCard': e.detail | ||
157 | + }) | ||
158 | + }, | ||
159 | + //文件上传 | ||
160 | + afterRead(event) { | ||
161 | + const { | ||
162 | + file | ||
163 | + } = event.detail; | ||
164 | + var that = this | ||
165 | + // 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式 | ||
166 | + wx.uploadFile({ | ||
167 | + url: 'https://market.myjxt.com:51311/file/fileUpload', // 仅为示例,非真实的接口地址 | ||
168 | + filePath: file.url, | ||
169 | + name: 'file', | ||
170 | + formData: { | ||
171 | + user: 'test' | ||
172 | + }, | ||
173 | + success(res) { | ||
174 | + // 上传完成需要更新 fileList | ||
175 | + const { | ||
176 | + fileList = [] | ||
177 | + } = that.data; | ||
178 | + fileList.push({ | ||
179 | + ...file, | ||
180 | + url: res.data | ||
181 | + }); | ||
182 | + console.log(res,fileList) | ||
183 | + that.setData({ | ||
184 | + fileList | ||
185 | + }); | ||
186 | + that.setData({ | ||
187 | + 'form.taskFileUrl': fileList.map(v => v.url) | ||
188 | + }) | ||
189 | + }, | ||
190 | + }); | ||
191 | + }, | ||
192 | + //删除 | ||
193 | + delFile(event) { | ||
194 | + let [list,index] = [this.data.fileList,event.detail.index] | ||
195 | + list.splice(index,1) | ||
196 | + this.setData({ | ||
197 | + fileList:list | ||
198 | + }) | ||
199 | + this.setData({ | ||
200 | + 'form.taskFileUrl': this.data.fileList.map(v => v.url) | ||
201 | + }) | ||
202 | + }, | ||
203 | + //开关 | ||
204 | + onswitchChange({ | ||
205 | + detail | ||
206 | + }) { | ||
207 | + this.setData({ | ||
208 | + 'form.checked': detail | ||
209 | + }); | ||
210 | + }, | ||
211 | + //创建 | ||
212 | + createTask() { | ||
213 | + console.log(this.data.form) | ||
214 | + if(this.data.form.hasData == 1 && !this.data.form.statisticsUnit) { | ||
215 | + return wx.showToast({title: '请选择统计单位',icon: 'none',}) | ||
216 | + } | ||
217 | + request({ | ||
218 | + url: `/wx/task/addCardTask`, | ||
219 | + method: 'post', | ||
220 | + data: this.data.form, | ||
221 | + }).then(res => { | ||
222 | + if (res.code == 0) { | ||
223 | + wx.navigateTo({ | ||
224 | + url: '../../mine/record/record' | ||
225 | + }) | ||
226 | + }else { | ||
227 | + wx.showToast({ | ||
228 | + title: res.msg, | ||
229 | + icon: 'none', | ||
230 | + duration: 1000 | ||
231 | + }) | ||
232 | + } | ||
233 | + }) | ||
8 | }, | 234 | }, |
9 | - | ||
10 | /** | 235 | /** |
11 | * 生命周期函数--监听页面加载 | 236 | * 生命周期函数--监听页面加载 |
12 | */ | 237 | */ |
13 | onLoad(options) { | 238 | onLoad(options) { |
14 | - | 239 | + this.setData({ |
240 | + 'form.userId': wx.getStorageSync('userInfo_id') | ||
241 | + }) | ||
242 | + this.setData({ | ||
243 | + tempId: options.tempId | ||
244 | + }, () => { | ||
245 | + this.getDetail() | ||
246 | + }) | ||
15 | }, | 247 | }, |
16 | // 创建完成 | 248 | // 创建完成 |
17 | - handleCreate(){ | 249 | + handleCreate() { |
18 | // console.log(111) | 250 | // console.log(111) |
19 | wx.switchTab({ | 251 | wx.switchTab({ |
20 | - url: '/pages/index/index', | 252 | + url: '/pages/index/index', |
21 | }) | 253 | }) |
22 | }, | 254 | }, |
23 | // 统一返回 | 255 | // 统一返回 |
@@ -29,5 +261,154 @@ Page({ | @@ -29,5 +261,154 @@ Page({ | ||
29 | */ | 261 | */ |
30 | onShareAppMessage() { | 262 | onShareAppMessage() { |
31 | 263 | ||
32 | - } | 264 | + }, |
265 | + /* | ||
266 | + 弹出层 - 统计单位 | ||
267 | + */ | ||
268 | + openUnitShow() { | ||
269 | + this.setData({ | ||
270 | + unitShow: true | ||
271 | + }) | ||
272 | + }, | ||
273 | + closeUnitShow() { | ||
274 | + this.setData({ | ||
275 | + unitShow: false | ||
276 | + }) | ||
277 | + }, | ||
278 | + changeUnitShow(e) { | ||
279 | + console.log(e) | ||
280 | + this.setData({ | ||
281 | + 'form.statisticsUnit': e.detail.value | ||
282 | + }) | ||
283 | + this.setData({ | ||
284 | + unitShow: false | ||
285 | + }) | ||
286 | + }, | ||
287 | + /* | ||
288 | + 弹出层 - 开始时间 | ||
289 | + */ | ||
290 | + openStartTimeShow() { | ||
291 | + this.setData({ | ||
292 | + startTimeShow: true | ||
293 | + }) | ||
294 | + }, | ||
295 | + closeStartTimeShow() { | ||
296 | + this.setData({ | ||
297 | + startTimeShow: false | ||
298 | + }) | ||
299 | + }, | ||
300 | + changeStartTimeShow(e) { | ||
301 | + let time = moment(e.detail).format('YYYY-MM-DD') | ||
302 | + this.setData({ | ||
303 | + 'form.startDate': time, | ||
304 | + }); | ||
305 | + this.setData({ | ||
306 | + startTimeShow: false | ||
307 | + }) | ||
308 | + }, | ||
309 | + /* | ||
310 | + 弹出层 - 打卡周期 | ||
311 | + */ | ||
312 | + openClockCycleShow() { | ||
313 | + this.setData({ | ||
314 | + clockCycleShow: true | ||
315 | + }) | ||
316 | + }, | ||
317 | + closeClockCycleShow() { | ||
318 | + this.setData({ | ||
319 | + clockCycleShow: false | ||
320 | + }) | ||
321 | + }, | ||
322 | + changeClockCycleShow(e) { | ||
323 | + this.setData({ | ||
324 | + 'form.taskCycle': e.detail.value | ||
325 | + }) | ||
326 | + this.setData({ | ||
327 | + clockCycleShow: false | ||
328 | + }) | ||
329 | + }, | ||
330 | + /* | ||
331 | + 弹出层 - 打卡频次 | ||
332 | + */ | ||
333 | + openClockRateShow() { | ||
334 | + this.setData({ | ||
335 | + clockRateShow: true | ||
336 | + }) | ||
337 | + }, | ||
338 | + closeClockRateShow() { | ||
339 | + this.setData({ | ||
340 | + clockRateShow: false | ||
341 | + }) | ||
342 | + }, | ||
343 | + changeClockRateShow(e) { | ||
344 | + this.setData({ | ||
345 | + 'form.taskFrequency': e.detail.value | ||
346 | + }) | ||
347 | + this.setData({ | ||
348 | + clockRateShow: false | ||
349 | + }) | ||
350 | + }, | ||
351 | + /* | ||
352 | + 弹出层 - 打卡提醒 | ||
353 | + */ | ||
354 | + openClockRemindShow() { | ||
355 | + this.setData({ | ||
356 | + clockRemindShow: true | ||
357 | + }) | ||
358 | + }, | ||
359 | + closeClockRemindShow() { | ||
360 | + this.setData({ | ||
361 | + clockRemindShow: false | ||
362 | + }) | ||
363 | + }, | ||
364 | + changeClockRemindShow(e) { | ||
365 | + this.setData({ | ||
366 | + 'form.remindTime': e.detail.value[0] + '::' + e.detail.value[1] | ||
367 | + }) | ||
368 | + this.setData({ | ||
369 | + clockRemindShow: false | ||
370 | + }) | ||
371 | + }, | ||
372 | + /* | ||
373 | + 弹出层 - 打卡缺卡提醒 | ||
374 | + */ | ||
375 | + openClockLackShow() { | ||
376 | + this.setData({ | ||
377 | + clockLackShow: true | ||
378 | + }) | ||
379 | + }, | ||
380 | + closeClockLackShow() { | ||
381 | + this.setData({ | ||
382 | + clockLackShow: false | ||
383 | + }) | ||
384 | + }, | ||
385 | + changeClockLackShow(e) { | ||
386 | + this.setData({ | ||
387 | + 'form.lackNum': e.detail.value | ||
388 | + }) | ||
389 | + this.setData({ | ||
390 | + clockLackShow: false | ||
391 | + }) | ||
392 | + }, | ||
393 | + /* | ||
394 | + 弹出层 - 必须包含 | ||
395 | + */ | ||
396 | + openContainShow() { | ||
397 | + this.setData({ | ||
398 | + containShow: true | ||
399 | + }) | ||
400 | + }, | ||
401 | + closeContainShow() { | ||
402 | + this.setData({ | ||
403 | + containShow: false | ||
404 | + }) | ||
405 | + }, | ||
406 | + changeContainShow(e) { | ||
407 | + this.setData({ | ||
408 | + 'form.submitCondition': e.detail.value | ||
409 | + }) | ||
410 | + this.setData({ | ||
411 | + containShow: false | ||
412 | + }) | ||
413 | + }, | ||
33 | }) | 414 | }) |
34 | \ No newline at end of file | 415 | \ No newline at end of file |
pages/index/newPunch/newPunch.json
1 | { | 1 | { |
2 | "usingComponents": { | 2 | "usingComponents": { |
3 | - "van-icon": "@vant/weapp/icon/index" | 3 | + "van-icon": "@vant/weapp/icon/index", |
4 | + "van-cell-group": "@vant/weapp/cell-group/index", | ||
5 | + "van-field": "@vant/weapp/field/index", | ||
6 | + "van-cell": "@vant/weapp/cell/index", | ||
7 | + "van-switch": "@vant/weapp/switch/index", | ||
8 | + "van-button": "@vant/weapp/button/index", | ||
9 | + "van-popup": "@vant/weapp/popup/index", | ||
10 | + "van-picker": "@vant/weapp/picker/index", | ||
11 | + "van-uploader": "@vant/weapp/uploader/index", | ||
12 | + "van-datetime-picker": "@vant/weapp/datetime-picker/index" | ||
4 | }, | 13 | }, |
5 | - "navigationStyle": "custom" | 14 | + "navigationBarTitleText": "打卡模板" |
6 | } | 15 | } |
7 | \ No newline at end of file | 16 | \ No newline at end of file |
pages/index/newPunch/newPunch.wxml
1 | <!--pages/index/rank/rank.wxml--> | 1 | <!--pages/index/rank/rank.wxml--> |
2 | <view class="punch_detail"> | 2 | <view class="punch_detail"> |
3 | - <!-- 顶部统一返回 --> | ||
4 | - <view class="navigation_back" bindtap="handleBack"> | ||
5 | - <van-icon name="arrow-left" /> | 3 | + <view class="title_card"> |
4 | + <van-cell-group border="{{ false }}"> | ||
5 | + <van-field value="{{ form.taskTitle }}" placeholder="请输入标题" border="{{ false }}" bind:change="onfieldChange" /> | ||
6 | + </van-cell-group> | ||
7 | + <view class="grey_line"></view> | ||
8 | + <view class="box_card"> | ||
9 | + <van-cell-group border="{{ false }}"> | ||
10 | + <van-field value="{{ form.taskDesc }}" type="textarea" placeholder="请输入" autosize border="{{ false }}" bind:change="onfieldDescChange" /> | ||
11 | + </van-cell-group> | ||
12 | + </view> | ||
13 | + <view class="tip_card"> | ||
14 | + <van-uploader accept='image' file-list="{{ fileList }}" deletable="{{ true }}" bind:after-read="afterRead" bind:delete="delFile"> | ||
15 | + <view class="tip_item"> | ||
16 | + <image class="pic" src="/img/answer/tp1.png" alt="" /> | ||
17 | + </view> | ||
18 | + </van-uploader> | ||
19 | + <!-- <view class="tip_item"> | ||
20 | + <image class="pic" src="/img/answer/sp1.png" alt="" /> | ||
21 | + </view> | ||
22 | + <view class="tip_item"> | ||
23 | + <image class="pic" src="/img/answer/yp1.png" alt="" /> | ||
24 | + </view> --> | ||
25 | + </view> | ||
6 | </view> | 26 | </view> |
7 | - <image class="temporary" src="/img/_new_punch.png" mode="widthFix" alt="" /> | ||
8 | - <!-- 创建完成返回首页 --> | ||
9 | - <text class="temporary_box" style="width: 700rpx;height: 100rpx;position: absolute;top: 2392rpx;right: 32rpx;" bindtap="handleCreate"></text> | 27 | + <view class="white_card"> |
28 | + <view class="bold_font">需要提交数据</view> | ||
29 | + <view> | ||
30 | + <van-switch checked="{{ form.hasData }}" size='20' active-value='1' inactive-value='2' bind:change="onSwitch" /> | ||
31 | + </view> | ||
32 | + </view> | ||
33 | + <view class="grey_line"></view> | ||
34 | + <view class="white_card_nopadding" wx:if="{{form.hasData == 1}}"> | ||
35 | + <van-cell-group border="{{ false }}"> | ||
36 | + <van-cell title="统计单位" value="{{ form.statisticsUnit }}" is-link label="请选择统计单位" border="{{ false }}" bindtap="openUnitShow" /> | ||
37 | + </van-cell-group> | ||
38 | + </view> | ||
39 | + <view class="white_card"> | ||
40 | + <view>允许补卡</view> | ||
41 | + <view> | ||
42 | + <van-switch checked="{{ form.allowRepairCard }}" size='20' bind:change="onChange" active-value='1' inactive-value='2' /> | ||
43 | + </view> | ||
44 | + </view> | ||
45 | + <view class="sm_grey_font"> | ||
46 | + 开启后,在打卡周期内,学生家长可对未打卡的任务进行补卡。 | ||
47 | + </view> | ||
48 | + <view class="white_card_nopadding"> | ||
49 | + <van-cell-group border="{{ false }}"> | ||
50 | + <van-cell title="开始时间" value="{{ form.startDate }}" is-link border="{{ false }}" bindtap="openStartTimeShow" /> | ||
51 | + </van-cell-group> | ||
52 | + </view> | ||
53 | + <view class="white_card_nopadding"> | ||
54 | + <van-cell-group border="{{ false }}"> | ||
55 | + <van-cell title="打卡周期" value="{{ form.taskCycle + ' 天'}}" is-link border="{{ false }}" bindtap="openClockCycleShow" /> | ||
56 | + </van-cell-group> | ||
57 | + </view> | ||
58 | + <view class="white_card_nopadding"> | ||
59 | + <van-cell-group border="{{ false }}"> | ||
60 | + <van-cell title="打卡频次" value="{{ form.taskFrequency }}" is-link border="{{ false }}" bindtap="openClockRateShow" /> | ||
61 | + </van-cell-group> | ||
62 | + </view> | ||
63 | + | ||
64 | + <view class="clearance"></view> | ||
65 | + <view class="white_card_nopadding"> | ||
66 | + <van-cell-group border="{{ false }}"> | ||
67 | + <van-cell title="打卡提醒" value="{{ form.remindTime }}" is-link border="{{ false }}" bindtap="openClockRemindShow" /> | ||
68 | + </van-cell-group> | ||
69 | + </view> | ||
70 | + <view class="white_card_nopadding"> | ||
71 | + <van-cell-group border="{{ false }}"> | ||
72 | + <van-cell title="缺卡打卡提醒" value="{{ form.lackNum + ' 次' }}" is-link border="{{ false }}" bindtap="openClockLackShow" /> | ||
73 | + </van-cell-group> | ||
74 | + </view> | ||
75 | + | ||
76 | + <view class="sm_grey_font"> | ||
77 | + 学生如缺卡达到一定条件,将会提醒家长 | ||
78 | + </view> | ||
79 | + <view class="white_card_nopadding"> | ||
80 | + <van-cell-group border="{{ false }}" > | ||
81 | + <van-cell title="提交时必须包含" value="{{ form.submitCondition }}" is-link border="{{ false }}" bindtap="openContainShow" /> | ||
82 | + </van-cell-group> | ||
83 | + </view> | ||
84 | + | ||
85 | + <view class="clearance"></view> | ||
86 | + <view class="btn"> | ||
87 | + <van-button type="info" round block bindtap="createTask">创建打卡</van-button> | ||
88 | + </view> | ||
89 | + | ||
90 | + <!--统计单位--> | ||
91 | + <van-popup show="{{ unitShow }}" position="bottom" custom-style="height: 40%;" round bind:close="closeUnitShow"> | ||
92 | + <van-picker columns="{{ columnsUnit }}" bind:confirm="changeUnitShow" bind:cancel="closeUnitShow" show-toolbar title="统计单位" /> | ||
93 | + </van-popup> | ||
94 | + | ||
95 | + <!--开始时间--> | ||
96 | + <van-popup show="{{ startTimeShow }}" position="bottom" custom-style="height: 40%;" round bind:close="closeStartTimeShow"> | ||
97 | + <!-- <van-picker columns="{{ columnsStartTime }}" bind:confirm="changeStartTimeShow" bind:cancel="closeStartTimeShow" show-toolbar title="开始时间" /> --> | ||
98 | + <van-datetime-picker title="开始时间" type="date" value="{{ form.startTimeShow }}" min-date="{{ minDate }}" bind:confirm="changeStartTimeShow" bind:cancel="closeStartTimeShow" formatter="{{ formatter }}" /> | ||
99 | + </van-popup> | ||
100 | + | ||
101 | + <!--打卡周期--> | ||
102 | + <van-popup show="{{ clockCycleShow }}" position="bottom" custom-style="height: 40%;" round bind:close="closeClockCycleShow"> | ||
103 | + <van-picker columns="{{ columnsClockCycle }}" bind:confirm="changeClockCycleShow" bind:cancel="closeClockCycleShow" show-toolbar title="打卡周期" /> | ||
104 | + </van-popup> | ||
105 | + | ||
106 | + <!--打卡频次--> | ||
107 | + <van-popup show="{{ clockRateShow }}" position="bottom" custom-style="height: 40%;" round bind:close="closeClockRateShow"> | ||
108 | + <van-picker columns="{{ columnsClockRate }}" bind:confirm="changeClockRateShow" bind:cancel="closeClockRateShow" show-toolbar title="打卡频次" /> | ||
109 | + </van-popup> | ||
110 | + | ||
111 | + <!--打卡提醒--> | ||
112 | + <van-popup show="{{ clockRemindShow }}" position="bottom" custom-style="height: 40%;" round bind:close="closeClockRemindShow"> | ||
113 | + <van-picker columns="{{ columnsClockRemind }}" bind:confirm="changeClockRemindShow" bind:cancel="closeClockRemindShow" show-toolbar title="打卡提醒" /> | ||
114 | + </van-popup> | ||
115 | + | ||
116 | + <!--打卡缺卡提醒--> | ||
117 | + <van-popup show="{{ clockLackShow }}" position="bottom" custom-style="height: 40%;" round bind:close="closeClockLackShow"> | ||
118 | + <van-picker columns="{{ columnsClockLack }}" bind:confirm="changeClockLackShow" bind:cancel="closeClockLackShow" show-toolbar title="缺卡打卡提醒" /> | ||
119 | + </van-popup> | ||
10 | 120 | ||
121 | + <!-- 必须包含 --> | ||
122 | + <van-popup show="{{ containShow }}" position="bottom" custom-style="height: 40%;" round bind:close="closeContainShow"> | ||
123 | + <van-picker columns="{{ columnsContain }}" bind:confirm="changeContainShow" bind:cancel="closeContainShow" show-toolbar title="提交时必须包含" /> | ||
124 | + </van-popup> | ||
11 | </view> | 125 | </view> |
12 | \ No newline at end of file | 126 | \ No newline at end of file |
pages/index/newPunch/newPunch.wxss
1 | /* pages/index/newPunch/newPunch.wxss */ | 1 | /* pages/index/newPunch/newPunch.wxss */ |
2 | +.punch_detail { | ||
3 | + position: absolute; | ||
4 | + width: 100vw; | ||
5 | + min-height: 100vh; | ||
6 | + background-color: #F5F6FA; | ||
7 | +} | ||
8 | + | ||
9 | +.title_card { | ||
10 | + margin: 15px 0; | ||
11 | +} | ||
12 | + | ||
13 | +.grey_line { | ||
14 | + width: 80vw; | ||
15 | + height: 1px; | ||
16 | +} | ||
17 | + | ||
18 | +.box_card { | ||
19 | + width: 100vw; | ||
20 | + min-height: 120px; | ||
21 | + background-color: #fff; | ||
22 | +} | ||
23 | + | ||
24 | +.tip_card { | ||
25 | + padding: 20px; | ||
26 | + box-sizing: border-box; | ||
27 | + display: flex; | ||
28 | + background-color: #fff; | ||
29 | +} | ||
30 | + | ||
31 | +.tip_item { | ||
32 | + width: 70px; | ||
33 | + height: 30px; | ||
34 | + margin-right: 5vw; | ||
35 | +} | ||
36 | + | ||
37 | +.pic { | ||
38 | + width: 100%; | ||
39 | + height: 100%; | ||
40 | +} | ||
41 | + | ||
42 | +.white_card { | ||
43 | + width: 100vw; | ||
44 | + background-color: #fff; | ||
45 | + padding: 20px 15px; | ||
46 | + box-sizing: border-box; | ||
47 | + display: flex; | ||
48 | + justify-content: space-between; | ||
49 | +} | ||
50 | + | ||
51 | +.bold_font { | ||
52 | + font-weight: bold; | ||
53 | +} | ||
54 | + | ||
55 | +.white_card_nopadding { | ||
56 | + width: 100vw; | ||
57 | + background-color: #fff; | ||
58 | + font-weight: bold; | ||
59 | + height: 60px; | ||
60 | + padding-top: 11px; | ||
61 | + box-sizing: border-box; | ||
62 | +} | ||
63 | + | ||
64 | +.sm_grey_font { | ||
65 | + padding: 15px 0 15px 20px; | ||
66 | + box-sizing: border-box; | ||
67 | + font-size: 12px; | ||
68 | + color: #999; | ||
69 | +} | ||
70 | + | ||
71 | +.clearance { | ||
72 | + width: 100vw; | ||
73 | + height: 20px; | ||
74 | +} | ||
75 | + | ||
76 | +.btn { | ||
77 | + width: 100vw; | ||
78 | + height: 80px; | ||
79 | + background-color: #fff; | ||
80 | + padding: 20px 30px 80px; | ||
81 | + box-sizing: border-box; | ||
82 | +} | ||
2 | \ No newline at end of file | 83 | \ No newline at end of file |
pages/index/punchDetail/punchDetail.js
1 | -// pages/index/punchDetail/punchDetail.js | 1 | +// pages/index/achievement/achievement.js |
2 | +// 引入插件安装器 | ||
3 | +import plugin from '../../../component/v2/plugins/index' | ||
4 | +import week from '../../../component/v2/plugins/week' | ||
5 | +import todo from '../../../component/v2/plugins/todo' | ||
6 | +import request from '../../../api/request.js' | ||
7 | +import moment from 'moment'; | ||
8 | +plugin | ||
9 | + .use(week) | ||
10 | + .use(todo) | ||
2 | Page({ | 11 | Page({ |
3 | 12 | ||
4 | /** | 13 | /** |
5 | * 页面的初始数据 | 14 | * 页面的初始数据 |
6 | */ | 15 | */ |
7 | data: { | 16 | data: { |
8 | - showEdit: false, //确认打卡 | ||
9 | - Clocked: false, //已打卡状态,只是为了演示用 | ||
10 | - showSuccess:false | 17 | + calendarConfig: { |
18 | + theme: 'elegant', | ||
19 | + weekMode: true, // 周视图模式 | ||
20 | + highlightToday: true, // 是否高亮显示当天 | ||
21 | + hideHeader: true, // 隐藏日历头部操作栏 | ||
22 | + }, | ||
23 | + isDisplay: false, | ||
24 | + clockShow: false, | ||
25 | + form: { | ||
26 | + id: '', //任务ID | ||
27 | + isRepair: 1, //是否补卡1立即打卡2补卡 | ||
28 | + repairDate: '', //补卡日期,当isRepair=2时必传,格式:YYYY-MM-dd | ||
29 | + statisticsUnit: '', //统计单位所含内容 | ||
30 | + taskDesc: '', //打卡描述内容 | ||
31 | + taskFileUrl: [], //任务文件(含多个) | ||
32 | + userId: '' | ||
33 | + }, | ||
34 | + fileList: [], | ||
35 | + calendar: {}, //日历 | ||
36 | + valueId: '', //任务ID | ||
37 | + taskVo: { | ||
38 | + allowRepairCard: 0, | ||
39 | + hasData: 0, | ||
40 | + statisticsUnit: "", | ||
41 | + submitCondition: "", | ||
42 | + id: 0, | ||
43 | + releaseTime: "", | ||
44 | + signTotal: 0, | ||
45 | + taskCycle: 0, | ||
46 | + taskDesc: "", | ||
47 | + taskFrequency: "", | ||
48 | + taskTitle: "", | ||
49 | + weekDay: "" | ||
50 | + }, | ||
51 | + resData: [], //成果数据 | ||
52 | + recordVo: { | ||
53 | + commitTime: "", | ||
54 | + files: [], | ||
55 | + signDate: "", | ||
56 | + taskRecordDesc: "", | ||
57 | + taskStatisticsParam: "" | ||
58 | + }, //成果数据当天 | ||
59 | + recordVoShow: false, | ||
60 | + isToday:true,//是否是今天 | ||
61 | + isLarge:false, //是否大于今天 | ||
62 | + repairText: '' | ||
11 | }, | 63 | }, |
12 | - | ||
13 | - /** | ||
14 | - * 生命周期函数--监听页面加载 | 64 | + /** |
65 | + * 选择日期后执行的事件 | ||
15 | */ | 66 | */ |
16 | - onLoad(options) { | 67 | + afterTapDate(e) { |
68 | + let date = e.detail.date | ||
69 | + this.setData({ | ||
70 | + isToday:e.detail.isToday | ||
71 | + }) | ||
72 | + //选择的年月日 | ||
73 | + let checkDay = e.detail.year +'-' + e.detail.month +'-' + e.detail.date | ||
74 | + let checktimeDate= new Date(moment(checkDay).format('YYYY-MM-DD')).getTime() | ||
75 | + //选择的日期是否大于今天 | ||
76 | + if(checktimeDate > new Date().getTime()) { | ||
77 | + console.log('ff') | ||
78 | + this.setData({ | ||
79 | + isLarge: true | ||
80 | + }) | ||
81 | + }else { | ||
82 | + this.setData({ | ||
83 | + isLarge: false | ||
84 | + }) | ||
85 | + } | ||
86 | + this.setData({ | ||
87 | + repairText: e.detail.todoText | ||
88 | + }) | ||
89 | + let recordVo = this.data.resData.eventDetails[date - 1].recordVo | ||
90 | + //匹配数据 | ||
91 | + if (recordVo != null) { | ||
92 | + console.log('复制',recordVo) | ||
93 | + this.setData({ | ||
94 | + recordVo: recordVo | ||
95 | + }) | ||
96 | + this.setData({ | ||
97 | + recordVoShow: true | ||
98 | + }) | ||
99 | + }else { | ||
100 | + this.setData({ | ||
101 | + recordVoShow: false | ||
102 | + }) | ||
103 | + } | ||
104 | + }, | ||
105 | + //获取信息 | ||
106 | + getInfo(doday) { | ||
107 | + request({ | ||
108 | + url: `/wx/task/getSignRecord`, | ||
109 | + method: 'get', | ||
110 | + data: { | ||
111 | + // wx.getStorageSync('userInfo_id'), | ||
112 | + "taskId": this.data.valueId, | ||
113 | + "signDate": doday | ||
114 | + }, | ||
115 | + }).then(res => { | ||
116 | + if (res.code == 0) { | ||
117 | + this.setData({ | ||
118 | + resData: res.data | ||
119 | + }) | ||
120 | + this.getV2(res.data) | ||
121 | + } else { | ||
122 | + wx.showToast({ | ||
123 | + title: res.msg, | ||
124 | + icon: 'none' | ||
125 | + }) | ||
126 | + } | ||
127 | + }) | ||
128 | + }, | ||
129 | + //初始化日历 | ||
130 | + initialize() { | ||
131 | + // 设置待办 | ||
132 | + this.setData({ | ||
133 | + 'calendar': this.selectComponent('#calendar').calendar | ||
134 | + }) | ||
17 | 135 | ||
18 | }, | 136 | }, |
19 | - // 打卡成果 | ||
20 | - handleAchievement(){ | 137 | + //显示日历 |
138 | + getV2(resData) { | ||
139 | + this.setData({ | ||
140 | + taskVo: resData.taskVo | ||
141 | + }) | ||
142 | + // const calendar = this.selectComponent('#calendar').calendar | ||
143 | + this.data.calendar.setTodos({ | ||
144 | + // 待办点标记设置 | ||
145 | + pos: 'bottom', // 待办点标记位置 ['top', 'bottom'] | ||
146 | + dotColor: 'purple', // 待办点标记颜色 | ||
147 | + circle: false, // 待办圆圈标记设置(如圆圈标记已签到日期),该设置与点标记设置互斥 | ||
148 | + showLabelAlways: true, // 点击时是否显示待办事项(圆点/文字),在 circle 为 true 及当日历配置 showLunar 为 true 时,此配置失效 | ||
149 | + dates: resData.eventDetails | ||
150 | + }) | ||
151 | + }, | ||
152 | + //成果 | ||
153 | + toAchieve(e) { | ||
21 | wx.navigateTo({ | 154 | wx.navigateTo({ |
22 | - url: '/pages/index/achievement/achievement', | 155 | + url: '../achievement/achievement?valueId='+this.data.valueId, |
23 | }) | 156 | }) |
24 | }, | 157 | }, |
25 | - // 打开打卡信息填写 | ||
26 | - handleEdit() { | ||
27 | - console.log(111) | 158 | + //唤起 打卡 |
159 | + toClock() { | ||
28 | this.setData({ | 160 | this.setData({ |
29 | - showEdit: true | 161 | + clockShow: true |
30 | }) | 162 | }) |
31 | }, | 163 | }, |
32 | - // 关闭打卡信息填写 | ||
33 | - closeEdit() { | 164 | + //唤起补卡 |
165 | + toRepairClock() { | ||
166 | + let selectData = this.data.calendar.getSelectedDates() | ||
167 | + let doday = selectData[0].year + '-' + selectData[0].month + '-' + selectData[0].date | ||
168 | + console.log(doday) | ||
169 | + let repairDate= moment(doday).format('YYYY-MM-DD') | ||
170 | + this.setData({ | ||
171 | + 'form.isRepair':2 | ||
172 | + }) | ||
173 | + this.setData({ | ||
174 | + 'form.repairDate':repairDate | ||
175 | + }) | ||
34 | this.setData({ | 176 | this.setData({ |
35 | - showEdit: false | 177 | + clockShow: true |
36 | }) | 178 | }) |
37 | }, | 179 | }, |
38 | - // 提交打卡信息,跳转打卡成功页面 | ||
39 | - handleSubmit() { | 180 | + //确定-打卡 |
181 | + toCardTask() { | ||
40 | this.setData({ | 182 | this.setData({ |
41 | - Clocked: true, | ||
42 | - showEdit: false, | ||
43 | - showSuccess:true | 183 | + 'form.id': this.data.valueId |
184 | + }) | ||
185 | + this.setData({ | ||
186 | + 'form.userId': wx.getStorageSync('userInfo_id') | ||
187 | + }) | ||
188 | + if(this.data.taskVo.submitCondition=='图片') { | ||
189 | + if(this.data.form.taskFileUrl.length == 0) { | ||
190 | + return wx.showToast({ | ||
191 | + title: '请上传图片', | ||
192 | + icon: 'none' | ||
193 | + }) | ||
194 | + } | ||
195 | + } | ||
196 | + request({ | ||
197 | + url: `/wx/task/commitCardTask`, | ||
198 | + method: 'post', | ||
199 | + data: this.data.form, | ||
200 | + }).then(res => { | ||
201 | + if (res.code == 0) { | ||
202 | + wx.showToast({ | ||
203 | + title: '打卡成功', | ||
204 | + icon: 'none' | ||
205 | + }) | ||
206 | + this.closeClockShow() | ||
207 | + this.getInfo(moment(new Date().getTime()).format('YYYY-MM-DD')) | ||
208 | + } else { | ||
209 | + wx.showToast({ | ||
210 | + title: res.msg, | ||
211 | + icon: 'none' | ||
212 | + }) | ||
213 | + } | ||
44 | }) | 214 | }) |
45 | }, | 215 | }, |
46 | - colseSuccess(){ | 216 | + /** |
217 | + * 生命周期函数--监听页面加载 | ||
218 | + */ | ||
219 | + onLoad(options) { | ||
47 | this.setData({ | 220 | this.setData({ |
48 | - showSuccess:false | 221 | + valueId: options.valueId |
49 | }) | 222 | }) |
50 | }, | 223 | }, |
224 | + /** | ||
225 | + * 生命周期函数--监听页面初次渲染完成 | ||
226 | + */ | ||
227 | + onReady() { | ||
228 | + this.initialize() | ||
229 | + this.getInfo(moment(new Date().getTime()).format('YYYY-MM-DD')) | ||
230 | + }, | ||
231 | + // 统一返回 | ||
51 | handleBack() { | 232 | handleBack() { |
52 | wx.navigateBack() | 233 | wx.navigateBack() |
53 | }, | 234 | }, |
@@ -56,5 +237,79 @@ Page({ | @@ -56,5 +237,79 @@ Page({ | ||
56 | */ | 237 | */ |
57 | onShareAppMessage() { | 238 | onShareAppMessage() { |
58 | 239 | ||
240 | + }, | ||
241 | + //统计单位所含内容 | ||
242 | + onStatisChange(e) { | ||
243 | + this.setData({ | ||
244 | + 'form.statisticsUnit': e.detail | ||
245 | + }) | ||
246 | + }, | ||
247 | + //内容 | ||
248 | + onTaskDescChange(e) { | ||
249 | + this.setData({ | ||
250 | + 'form.taskDesc': e.detail | ||
251 | + }) | ||
252 | + }, | ||
253 | + //文件上传 | ||
254 | + afterRead(event) { | ||
255 | + const { | ||
256 | + file | ||
257 | + } = event.detail; | ||
258 | + var that = this | ||
259 | + // 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式 | ||
260 | + wx.uploadFile({ | ||
261 | + url: 'https://market.myjxt.com:51311/file/fileUpload', // 仅为示例,非真实的接口地址 | ||
262 | + filePath: file.url, | ||
263 | + name: 'file', | ||
264 | + formData: { | ||
265 | + user: 'test' | ||
266 | + }, | ||
267 | + success(res) { | ||
268 | + // 上传完成需要更新 fileList | ||
269 | + const { | ||
270 | + fileList = [] | ||
271 | + } = that.data; | ||
272 | + fileList.push({ | ||
273 | + ...file, | ||
274 | + url: res.data | ||
275 | + }); | ||
276 | + console.log(res, fileList) | ||
277 | + that.setData({ | ||
278 | + fileList | ||
279 | + }); | ||
280 | + that.setData({ | ||
281 | + 'form.taskFileUrl': fileList.map(v => v.url) | ||
282 | + }) | ||
283 | + }, | ||
284 | + }); | ||
285 | + }, | ||
286 | + //删除 | ||
287 | + delFile(event) { | ||
288 | + let [list, index] = [this.data.fileList, event.detail.index] | ||
289 | + list.splice(index, 1) | ||
290 | + this.setData({ | ||
291 | + fileList: list | ||
292 | + }) | ||
293 | + this.setData({ | ||
294 | + 'form.taskFileUrl': this.data.fileList.map(v => v.url) | ||
295 | + }) | ||
296 | + }, | ||
297 | + //关闭 | ||
298 | + closeClockShow() { | ||
299 | + this.setData({ | ||
300 | + clockShow: false | ||
301 | + }) | ||
302 | + let form = { | ||
303 | + id: '', //任务ID | ||
304 | + isRepair: 1, //是否补卡1立即打卡2补卡 | ||
305 | + repairDate: '', //补卡日期,当isRepair=2时必传,格式:YYYY-MM-dd | ||
306 | + statisticsUnit: '', //统计单位所含内容 | ||
307 | + taskDesc: '', //打卡描述内容 | ||
308 | + taskFileUrl: [], //任务文件(含多个) | ||
309 | + userId: '' | ||
310 | + } | ||
311 | + this.setData({ | ||
312 | + form: form | ||
313 | + }) | ||
59 | } | 314 | } |
60 | }) | 315 | }) |
61 | \ No newline at end of file | 316 | \ No newline at end of file |
pages/index/punchDetail/punchDetail.json
1 | { | 1 | { |
2 | "usingComponents": { | 2 | "usingComponents": { |
3 | "van-icon": "@vant/weapp/icon/index", | 3 | "van-icon": "@vant/weapp/icon/index", |
4 | - "van-popup": "@vant/weapp/popup/index" | 4 | + "calendar": "/component/v2/index", |
5 | + "van-popup": "@vant/weapp/popup/index", | ||
6 | + "van-field": "@vant/weapp/field/index", | ||
7 | + "van-uploader": "@vant/weapp/uploader/index", | ||
8 | + "van-button": "@vant/weapp/button/index" | ||
5 | }, | 9 | }, |
6 | - "navigationStyle": "custom" | 10 | + "navigationBarTitleText": "立即打卡" |
7 | } | 11 | } |
8 | \ No newline at end of file | 12 | \ No newline at end of file |
pages/index/punchDetail/punchDetail.wxml
1 | -<!--pages/index/punchDetail/punchDetail.wxml--> | 1 | +<!--pages/index/achievement/achievement.wxml--> |
2 | <view class="punch_detail"> | 2 | <view class="punch_detail"> |
3 | - <!-- 顶部统一返回 --> | ||
4 | - <view class="navigation_back" bindtap="handleBack"> | ||
5 | - <van-icon name="arrow-left" /> | 3 | + <calendar id="calendar" config="{{calendarConfig}}" bind:afterTapDate="afterTapDate"/> |
4 | + <!-- <view class="btn" bindtap="getInfo">按钮</view> --> | ||
5 | + <view class="line_grey"></view> | ||
6 | + <view class="card"> | ||
7 | + <view class="card_title">{{taskVo.taskTitle}}</view> | ||
8 | + <view class="card_flex"> | ||
9 | + <view class="flex_grey">已进行 {{taskVo.signTotal +' / ' +taskVo.taskCycle}} 天</view> | ||
10 | + <view class="flex_grey">打卡频次 : {{taskVo.taskFrequency}}</view> | ||
11 | + <view class="flex_grey">{{taskVo.allowRepairCard == 1 ?'允许补卡': '不允许补卡'}}</view> | ||
12 | + </view> | ||
13 | + <view class="card_context">{{taskVo.taskDesc}}</view> | ||
14 | + <view class="grey_font"> | ||
15 | + <view>我发布与{{taskVo.weekDay}} {{taskVo.releaseTime}}</view> | ||
16 | + <view class="grey_font_bottom"></view> | ||
17 | + </view> | ||
18 | + </view> | ||
19 | + <view class="btn_box"> | ||
20 | + <van-button round color="#F4F4F4" bindtap='toAchieve' custom-style="color: #000;">我 的 成 果</van-button> | ||
21 | + <van-button round type="info" bindtap='toClock' wx:if="{{isToday}}">立 即 打 卡</van-button> | ||
22 | + <van-button round type="warning" bindtap='toRepairClock' wx:if="{{taskVo.allowRepairCard == 1&&repairText=='未打卡'&&!isToday&&!isLarge}}">补 卡</van-button> | ||
6 | </view> | 23 | </view> |
7 | - <!-- 已打卡 --> | ||
8 | - <image class="temporary" wx:if="{{Clocked}}" src="/img/_check_in3.png" mode="widthFix" alt="" /> | ||
9 | - <!-- 未打卡 --> | ||
10 | - <image class="temporary" wx:else src="/img/_check_in1.png" mode="widthFix" alt="" /> | ||
11 | - <!-- 我的成果 --> | ||
12 | - <text class="temporary_box" wx:if="{{!Clocked}}" style="width: 308rpx;height: 100rpx;position: absolute;top: 1412rpx;left: 32rpx;" bindtap="handleAchievement"></text> | ||
13 | - <!-- 立即打卡 --> | ||
14 | - <text class="temporary_box" wx:if="{{!Clocked}}" style="width: 308rpx;height: 100rpx;position: absolute;top: 1412rpx;right: 32rpx;" bindtap="handleEdit"></text> | ||
15 | 24 | ||
16 | - <!-- 立即打卡 --> | ||
17 | - <van-popup show="{{ showEdit }}" position="bottom" custom-style="height: 80%;" bind:close="closeEdit"> | ||
18 | - <image class="temporary" src="/img/_check_in2.png" mode="widthFix" alt="" /> | ||
19 | - <text class="temporary_box" style="width: 700rpx;height: 100rpx;position: absolute;top: 1452rpx;right: 32rpx;" bindtap="handleSubmit"></text> | ||
20 | - </van-popup> | ||
21 | - <!-- 打卡成果 --> | ||
22 | - <van-popup show="{{ showSuccess }}" custom-style="width:80%;height: 80%;" bind:close="colseSuccess"> | ||
23 | - <image class="temporary" src="/img/_check_in4.png" mode="widthFix" alt="" /> | ||
24 | - <text class="temporary_box" style="width: 200rpx;height: 60rpx;position: absolute;top: 800rpx;left: 200rpx;" bindtap="colseSuccess"></text> | 25 | + <!--打卡--> |
26 | + <van-popup show="{{ clockShow }}" position="bottom" custom-style="height: 60%;" round bind:close="closeClockShow"> | ||
27 | + <view class="pop_title">{{form.isRepair == 2? '补交打卡成果' : '提交打卡成果'}}</view> | ||
28 | + <view class="pop_flex" wx:if="{{taskVo.hasData==1}}"> | ||
29 | + <view>提交数据</view> | ||
30 | + <view class="pop_cell"> | ||
31 | + <view> | ||
32 | + <van-cell-group> | ||
33 | + <van-field value="{{ form.statisticsUnit }}" placeholder="请输入" border="{{ false }}" bind:change="onStatisChange" /> | ||
34 | + </van-cell-group> | ||
35 | + </view> | ||
36 | + <view class="pop_fz">{{taskVo.statisticsUnit}}</view> | ||
37 | + </view> | ||
38 | + </view> | ||
39 | + <van-field value="{{ form.taskDesc }}" label="" type="textarea" placeholder="填写内容(如:已完成)" autosize border="{{ false }}" bind:change="onTaskDescChange"/> | ||
40 | + <view class="pop_tip"> | ||
41 | + <van-uploader accept='image' file-list="{{ fileList }}" deletable="{{ true }}" bind:after-read="afterRead" bind:delete="delFile"> | ||
42 | + <view class="tip_item"> | ||
43 | + <image class="pop_pic" src="/img/answer/tp1.png" alt="" /> | ||
44 | + </view> | ||
45 | + </van-uploader> | ||
46 | + <!-- <image class="pop_pic" src="/img/answer/tp1.png" alt="" /> --> | ||
47 | + </view> | ||
48 | + <view class="pop_btn"> | ||
49 | + <van-button type="{{form.isRepair == 2? 'warning':'info'}}" block round bindtap="toCardTask">提 交</van-button> | ||
50 | + </view> | ||
25 | </van-popup> | 51 | </van-popup> |
26 | </view> | 52 | </view> |
27 | \ No newline at end of file | 53 | \ No newline at end of file |
pages/index/punchDetail/punchDetail.wxss
1 | /* pages/index/punchDetail/punchDetail.wxss */ | 1 | /* pages/index/punchDetail/punchDetail.wxss */ |
2 | +/* pages/index/achievement/achievement.wxss */ | ||
3 | +.btn { | ||
4 | + width: 20vw; | ||
5 | + height: 20vw; | ||
6 | + background-color: aqua; | ||
7 | + font-size: 5vw; | ||
8 | +} | ||
9 | +.line_grey { | ||
10 | + width: 90vw; | ||
11 | + height: 1px; | ||
12 | + background-color: #999; | ||
13 | + margin: 10px 5vw 20px; | ||
14 | +} | ||
15 | +.card { | ||
16 | + width: 92vw; | ||
17 | + margin-left: 4vw; | ||
18 | +} | ||
19 | +.card_title { | ||
20 | + font-size: 18px; | ||
21 | + color: #556191; | ||
22 | + margin: 15px 0; | ||
23 | +} | ||
24 | +.card_flex { | ||
25 | + display: flex; | ||
26 | +} | ||
27 | +.flex_grey { | ||
28 | + padding: 7px 10px; | ||
29 | + box-sizing: border-box; | ||
30 | + margin: 0 5px 10px 0; | ||
31 | + font-size: 13px; | ||
32 | + background-color: #F4F4F4; | ||
33 | + color: #666666; | ||
34 | + border-radius: 3px; | ||
35 | +} | ||
36 | +.card_context { | ||
37 | + font-size: 16px; | ||
38 | + margin: 10px 0; | ||
39 | +} | ||
40 | +.grey_font { | ||
41 | + font-size: 14px; | ||
42 | + color: #999999; | ||
43 | + margin: 20px 0; | ||
44 | +} | ||
45 | +.grey_font_bottom { | ||
46 | + margin-top: 5px; | ||
47 | +} | ||
48 | +.btn_box { | ||
49 | + display: flex; | ||
50 | + justify-content: space-around; | ||
51 | + position: fixed; | ||
52 | + bottom: 50px; | ||
53 | + width: 100vw; | ||
54 | +} | ||
55 | +.pop_title { | ||
56 | + font-size: 18px; | ||
57 | + font-weight: bold; | ||
58 | + text-align: center; | ||
59 | + margin: 20px 0; | ||
60 | +} | ||
61 | +.pop_flex { | ||
62 | + display: flex; | ||
63 | + justify-content: space-between; | ||
64 | + align-items: center; | ||
65 | + padding: 0 20px; | ||
66 | + box-sizing: border-box; | ||
67 | +} | ||
68 | +.pop_cell { | ||
69 | + width: 40vw; | ||
70 | + display: flex; | ||
71 | + align-items: center; | ||
72 | +} | ||
73 | +.pop_fz { | ||
74 | + width: 70px; | ||
75 | +} | ||
76 | +.pop_btn { | ||
77 | + position: absolute; | ||
78 | + bottom: 30px; | ||
79 | + width: 90vw; | ||
80 | + margin: 0 5vw; | ||
81 | +} | ||
82 | +.pop_tip { | ||
83 | + position: absolute; | ||
84 | + bottom: 90px; | ||
85 | + width: 90vw; | ||
86 | + margin: 0 5vw; | ||
87 | +} | ||
88 | +.pop_pic { | ||
89 | + width: 70px; | ||
90 | + height: 30px; | ||
91 | +} | ||
2 | \ No newline at end of file | 92 | \ No newline at end of file |
pages/index/rank/rank.js
1 | // pages/index/rank/rank.js | 1 | // pages/index/rank/rank.js |
2 | +import request from '../../../api/request.js' | ||
3 | +import moment from 'moment'; | ||
2 | Page({ | 4 | Page({ |
3 | 5 | ||
4 | /** | 6 | /** |
5 | * 页面的初始数据 | 7 | * 页面的初始数据 |
6 | */ | 8 | */ |
7 | data: { | 9 | data: { |
10 | + rankList: [], | ||
11 | + dayTime: '', | ||
12 | + user: { | ||
13 | + id: '', | ||
14 | + userName: '', | ||
15 | + nickname: '', | ||
16 | + phone: "", | ||
17 | + token: "", | ||
18 | + headImg: '' | ||
19 | + }, | ||
20 | + selfData: { | ||
21 | + id: 0, | ||
22 | + isOneSelf: 0, | ||
23 | + signDayNum: 0, | ||
24 | + signPercentage: "", | ||
25 | + signRecordNum: 0, | ||
26 | + userId: 0 | ||
27 | + } | ||
8 | }, | 28 | }, |
9 | 29 | ||
30 | + //排行榜列表 | ||
31 | + getRankList() { | ||
32 | + request({ | ||
33 | + url: `/wx/task/getSignRank`, | ||
34 | + method: 'post', | ||
35 | + data: { | ||
36 | + "page": 1, | ||
37 | + "pageSize": 999, | ||
38 | + "userId": wx.getStorageSync("userInfo_id") | ||
39 | + }, | ||
40 | + }).then(res => { | ||
41 | + if (res.code == 0) { | ||
42 | + this.setData({ | ||
43 | + rankList: res.rows | ||
44 | + }) | ||
45 | + console.log(this.data.rankList) | ||
46 | + } else { | ||
47 | + wx.showToast({ | ||
48 | + title: res.msg, | ||
49 | + icon: 'none', | ||
50 | + duration: 1500 | ||
51 | + }) | ||
52 | + } | ||
53 | + }) | ||
54 | + }, | ||
55 | + //去打卡 | ||
56 | + toOpen() { | ||
57 | + wx.navigateTo({ | ||
58 | + url: '/pages/index/index', | ||
59 | + }) | ||
60 | + }, | ||
61 | + //获取个人 | ||
62 | + getSelf() { | ||
63 | + request({ | ||
64 | + url: `/wx/task/getOneSelf`, | ||
65 | + method: 'get', | ||
66 | + data: { | ||
67 | + "userId": wx.getStorageSync("userInfo_id") | ||
68 | + }, | ||
69 | + }).then(res => { | ||
70 | + if (res.code == 0) { | ||
71 | + this.setData({ | ||
72 | + selfData: res.data | ||
73 | + }) | ||
74 | + } else { | ||
75 | + wx.showToast({ | ||
76 | + title: res.msg, | ||
77 | + icon: 'none', | ||
78 | + }) | ||
79 | + } | ||
80 | + }) | ||
81 | + }, | ||
10 | /** | 82 | /** |
11 | * 生命周期函数--监听页面加载 | 83 | * 生命周期函数--监听页面加载 |
12 | */ | 84 | */ |
13 | onLoad(options) { | 85 | onLoad(options) { |
14 | - | 86 | + |
15 | }, | 87 | }, |
16 | // 统一返回 | 88 | // 统一返回 |
17 | handleBack() { | 89 | handleBack() { |
18 | wx.navigateBack() | 90 | wx.navigateBack() |
19 | }, | 91 | }, |
20 | - /** | ||
21 | - * 用户点击右上角分享 | ||
22 | - */ | ||
23 | - onShareAppMessage() { | ||
24 | - | 92 | + onShow() { |
93 | + this.setData({ | ||
94 | + 'user': wx.getStorageSync('userInfo') | ||
95 | + }) | ||
96 | + this.setData({ | ||
97 | + "dayTime": moment(new Date().getTime()).format('YYYY-MM-DD') | ||
98 | + }) | ||
99 | + this.getSelf() | ||
100 | + this.getRankList() | ||
25 | } | 101 | } |
26 | }) | 102 | }) |
27 | \ No newline at end of file | 103 | \ No newline at end of file |
pages/index/rank/rank.json
1 | { | 1 | { |
2 | "usingComponents": { | 2 | "usingComponents": { |
3 | - "van-icon": "@vant/weapp/icon/index" | 3 | + "van-icon": "@vant/weapp/icon/index", |
4 | + "van-button": "@vant/weapp/button/index" | ||
4 | }, | 5 | }, |
5 | "navigationStyle": "custom" | 6 | "navigationStyle": "custom" |
6 | } | 7 | } |
7 | \ No newline at end of file | 8 | \ No newline at end of file |
pages/index/rank/rank.wxml
1 | <!--pages/index/rank/rank.wxml--> | 1 | <!--pages/index/rank/rank.wxml--> |
2 | -<view class="punch_detail"> | ||
3 | - <!-- 顶部统一返回 --> | ||
4 | - <view class="navigation_back" bindtap="handleBack"> | ||
5 | - <van-icon name="arrow-left" /> | ||
6 | - </view> | ||
7 | - <image class="temporary" src="/img/_rank.png" mode="widthFix" alt="" /> | 2 | +<!-- <view class="rank" style="background-image: url('https://szyundisk.oss-cn-hangzhou.aliyuncs.com/null/5f055580-1341-4c52-9154-c3b125c1107a.png')"> --> |
3 | +<view class="rank" style="background-image: url('https://szyundisk.oss-cn-hangzhou.aliyuncs.com/AdmissionsManageSys/54ec1f3f-dbb4-4660-ba24-4a6731e88def.png')"> | ||
4 | + <view class="rank_time">更新时间:{{dayTime}}</view> | ||
5 | + <view class="white_box"> | ||
6 | + <view class="title_box"> | ||
7 | + <view class="title_pic"> | ||
8 | + <image class="pic" src="{{user.headImg}}" alt="" /> | ||
9 | + {{user.userName != null ? user.userName : user.nickname}} | ||
10 | + </view> | ||
11 | + <view class="red_title">已坚持{{selfData.signDayNum}}天</view> | ||
12 | + <view class="red_title">{{selfData.signRecordNum}}次</view> | ||
13 | + </view> | ||
14 | + <view class="grey_title"> | ||
15 | + <view class="table_L"> | ||
16 | + <view>排名</view> | ||
17 | + <view>姓名</view> | ||
18 | + </view> | ||
19 | + <view>打卡数</view> | ||
20 | + </view> | ||
8 | 21 | ||
22 | + <view class="table_item" wx:for="{{ rankList }}" wx:key="index" wx:for-item="value"> | ||
23 | + <view class="table_L"> | ||
24 | + <image wx:if="{{index == 0}}" class="tem_pic" src="/img/answer/1.png" alt="" /> | ||
25 | + <image wx:if="{{index == 1}}" class="tem_pic" src="/img/answer/2.png" alt="" /> | ||
26 | + <image wx:if="{{index == 2}}" class="tem_pic" src="/img/answer/3.png" alt="" /> | ||
27 | + <view class="tem_pic" wx:if="{{index != 0 && index != 1 && index != 2}}">{{index + 1}}</view> | ||
28 | + <view>{{value.userName}}</view> | ||
29 | + </view> | ||
30 | + <view class="table_R"> | ||
31 | + <view class="grey_R">已坚持{{value.signDayNum}}天</view> | ||
32 | + <view>{{value.signRecordNum}}</view> | ||
33 | + </view> | ||
34 | + </view> | ||
35 | + </view> | ||
36 | + | ||
37 | + <view class="btn"> | ||
38 | + <van-button type="info" block round bindtap="toOpen">去打卡</van-button> | ||
39 | + </view> | ||
9 | </view> | 40 | </view> |
10 | \ No newline at end of file | 41 | \ No newline at end of file |
pages/index/rank/rank.wxss
1 | /* pages/index/rank/rank.wxss */ | 1 | /* pages/index/rank/rank.wxss */ |
2 | +.rank { | ||
3 | + position: absolute; | ||
4 | + width: 100vw; | ||
5 | + min-height: 100vh; | ||
6 | + background-size: 100% 100%; | ||
7 | + padding: 0 5vw; | ||
8 | + box-sizing: border-box; | ||
9 | +} | ||
10 | +.rank_time { | ||
11 | + font-size: 4.4vw; | ||
12 | + color: #fff; | ||
13 | + opacity: 0.8; | ||
14 | + margin-top: 125px; | ||
15 | + margin-left: 2vw; | ||
16 | +} | ||
17 | +.white_box{ | ||
18 | + width: 90vw; | ||
19 | + min-height: 72vh; | ||
20 | + margin-top: 40px; | ||
21 | + background-color: #fff; | ||
22 | + border-radius: 4vw; | ||
23 | + padding: 7vw 5vw; | ||
24 | + box-sizing: border-box; | ||
25 | +} | ||
26 | +.title_box { | ||
27 | + display: flex; | ||
28 | + justify-content: space-between; | ||
29 | + align-items: center; | ||
30 | + font-size: 3.9vw; | ||
31 | + font-weight: bold; | ||
32 | + padding: 30px 5vw; | ||
33 | + box-sizing: border-box; | ||
34 | + border-radius: 5vw; | ||
35 | + box-shadow: 1px 1px 1px 1px rgb(207, 206, 206); | ||
36 | +} | ||
37 | +.title_pic { | ||
38 | + display: flex; | ||
39 | + align-items: center; | ||
40 | +} | ||
41 | +.pic { | ||
42 | + width: 25px; | ||
43 | + height: 25px; | ||
44 | + border-radius: 25px; | ||
45 | + margin-right: 7px; | ||
46 | +} | ||
47 | +.red_title { | ||
48 | + color: #FD676A; | ||
49 | +} | ||
50 | +.grey_title { | ||
51 | + margin: 30px 0; | ||
52 | + font-size: 4.5vw; | ||
53 | + color: #999; | ||
54 | + display: flex; | ||
55 | + justify-content: space-between; | ||
56 | +} | ||
57 | +.table_L{ | ||
58 | + width: 28vw; | ||
59 | + display: flex; | ||
60 | + justify-content: space-between; | ||
61 | + align-items: center; | ||
62 | +} | ||
63 | +.L_box { | ||
64 | + width: 50px; | ||
65 | +} | ||
66 | + | ||
67 | +.table_item { | ||
68 | + margin: 20px 0; | ||
69 | + font-size: 4vw; | ||
70 | + color: #333; | ||
71 | + display: flex; | ||
72 | + justify-content: space-between; | ||
73 | + align-items: center; | ||
74 | +} | ||
75 | +.table_R { | ||
76 | + width: 45vw; | ||
77 | + display: flex; | ||
78 | + justify-content: space-between; | ||
79 | + align-items: center; | ||
80 | +} | ||
81 | +.grey_R { | ||
82 | + color:#999; | ||
83 | + font-size: 3.9vw; | ||
84 | +} | ||
85 | +.tem_pic { | ||
86 | + width: 22px; | ||
87 | + height: 28px; | ||
88 | + text-align: center; | ||
89 | +} | ||
90 | +.btn { | ||
91 | + position: fixed; | ||
92 | + bottom: 50px; | ||
93 | + width: 82vw; | ||
94 | + margin-left: 4vw; | ||
95 | +} | ||
2 | \ No newline at end of file | 96 | \ No newline at end of file |
pages/login/codeLogin/codeLogin.js
1 | // pages/login/codeLogin/codeLogin.js | 1 | // pages/login/codeLogin/codeLogin.js |
2 | -var app = getApp(); | 2 | +// var app = getApp(); |
3 | +var api = 'https://proxy.shunzhi.net/'; | ||
4 | +var api_card = 'https://proxy.shunzhi.net/card/'; | ||
5 | +var appid = 'wx186236fdcd93edcc'; | ||
3 | var util = require('../../../utils/md5.js') | 6 | var util = require('../../../utils/md5.js') |
4 | import request from '../../../api/request.js' | 7 | import request from '../../../api/request.js' |
5 | Page({ | 8 | Page({ |
@@ -21,6 +24,7 @@ Page({ | @@ -21,6 +24,7 @@ Page({ | ||
21 | path: '', //登录后跳转页面 | 24 | path: '', //登录后跳转页面 |
22 | modelShow: false, //完善信息 | 25 | modelShow: false, //完善信息 |
23 | phone: '', //getUserInfo获取到的手机号 | 26 | phone: '', //getUserInfo获取到的手机号 |
27 | + openId: '' | ||
24 | }, | 28 | }, |
25 | onLoad: function (options) { | 29 | onLoad: function (options) { |
26 | console.log('登录页options:', options) | 30 | console.log('登录页options:', options) |
@@ -69,20 +73,25 @@ Page({ | @@ -69,20 +73,25 @@ Page({ | ||
69 | }) | 73 | }) |
70 | } | 74 | } |
71 | request({ | 75 | request({ |
72 | - url: `h5/user/Oneclicklogin`, | ||
73 | - method: 'get', | 76 | + url: `/wx/app/oneClickLogin/`+ appid, |
77 | + method: 'post', | ||
74 | data: { | 78 | data: { |
75 | "encryptedData": this.data.encryptedData, | 79 | "encryptedData": this.data.encryptedData, |
76 | - "session_key": this.data.session_key, | 80 | + "sessionKey": this.data.session_key, |
77 | "iv": this.data.iv, | 81 | "iv": this.data.iv, |
82 | + "openId": this.data.openId | ||
78 | }, | 83 | }, |
79 | }).then(res => { | 84 | }).then(res => { |
80 | - if (res.success) { | 85 | + if (res.code == 0) { |
81 | if (res.data) { | 86 | if (res.data) { |
82 | this.setData({ | 87 | this.setData({ |
83 | phone: res.data.phone | 88 | phone: res.data.phone |
84 | }, () => { | 89 | }, () => { |
85 | - this.getUserInfo() | 90 | + wx.setStorageSync('userInfo', res.data) |
91 | + wx.setStorageSync('userInfo_id', res.data.id) | ||
92 | + wx.switchTab({ | ||
93 | + url: '/pages/mine/index', | ||
94 | + }) | ||
86 | }) | 95 | }) |
87 | } else { | 96 | } else { |
88 | wx.showToast({ | 97 | wx.showToast({ |
@@ -107,36 +116,39 @@ Page({ | @@ -107,36 +116,39 @@ Page({ | ||
107 | } | 116 | } |
108 | }, | 117 | }, |
109 | getUserInfo() { | 118 | getUserInfo() { |
110 | - let that = this | ||
111 | - request({ | ||
112 | - url: `h5/user/getuserInfoNew`, | ||
113 | - method: 'get', | ||
114 | - data: { | ||
115 | - // PhoneName: '13355752969' | ||
116 | - PhoneName: this.data.phone | ||
117 | - }, | ||
118 | - }).then((res) => { | ||
119 | - if (res.success) { | ||
120 | - if (res.data) { | ||
121 | - wx.setStorageSync('userInfo', res.data) | ||
122 | - wx.setStorageSync('showModal', '') | 119 | + // let that = this |
120 | + // request({ | ||
121 | + // url: `h5/user/getuserInfoNew`, | ||
122 | + // method: 'get', | ||
123 | + // data: { | ||
124 | + // // PhoneName: '13355752969' | ||
125 | + // PhoneName: this.data.phone | ||
126 | + // }, | ||
127 | + // }).then((res) => { | ||
128 | + // if (res.success) { | ||
129 | + // if (res.data) { | ||
130 | + // wx.setStorageSync('userInfo', res.data) | ||
131 | + // wx.setStorageSync('showModal', '') | ||
123 | 132 | ||
124 | - } | ||
125 | - } | ||
126 | - }) | 133 | + // } |
134 | + // } | ||
135 | + // }) | ||
127 | }, | 136 | }, |
128 | - getOpenId() { | 137 | + getOpenId() { |
129 | return request({ | 138 | return request({ |
130 | - url: `h5/MyVoluntary/GetOpenId`, | 139 | + url: `/wx/app/getOpenId/wx186236fdcd93edcc`, |
131 | method: 'get', | 140 | method: 'get', |
132 | data: { | 141 | data: { |
133 | code: this.data.loginCode | 142 | code: this.data.loginCode |
134 | }, | 143 | }, |
135 | }).then(res2 => { | 144 | }).then(res2 => { |
136 | - // console.log(res2.data); | ||
137 | this.setData({ | 145 | this.setData({ |
138 | - session_key: JSON.parse(res2.data).session_key | 146 | + session_key: res2.data.sessionKey |
139 | }) | 147 | }) |
148 | + this.setData({ | ||
149 | + openId: res2.data.openid | ||
150 | + }) | ||
151 | + console.log(this.data); | ||
140 | }) | 152 | }) |
141 | }, | 153 | }, |
142 | bindUserName: function (e) { | 154 | bindUserName: function (e) { |
@@ -181,16 +193,17 @@ Page({ | @@ -181,16 +193,17 @@ Page({ | ||
181 | wx.showLoading({ | 193 | wx.showLoading({ |
182 | title: '请求中', | 194 | title: '请求中', |
183 | }) | 195 | }) |
184 | - wx.request({ | ||
185 | - url: api + 'h5/MyVoluntary/CheckCodeIsRight', | 196 | + wx.request({ |
197 | + url: api_card + '/wx/app/loginCode', | ||
186 | data: { | 198 | data: { |
187 | - captcha: code, | ||
188 | - mobile: username | 199 | + code: code, |
200 | + phone: username | ||
189 | }, | 201 | }, |
190 | - method: 'get', | 202 | + method: 'post', |
191 | success: (res) => { | 203 | success: (res) => { |
192 | wx.hideLoading(); | 204 | wx.hideLoading(); |
193 | if (res.data.success) { | 205 | if (res.data.success) { |
206 | + console.log(res.data) | ||
194 | if (res.data.data) { | 207 | if (res.data.data) { |
195 | this.setData({ | 208 | this.setData({ |
196 | phone: res.data.data.phone | 209 | phone: res.data.data.phone |
@@ -306,7 +319,7 @@ Page({ | @@ -306,7 +319,7 @@ Page({ | ||
306 | } | 319 | } |
307 | }, | 320 | }, |
308 | getPhoneNumber(e) { | 321 | getPhoneNumber(e) { |
309 | - // console.log(e.detail) | 322 | + console.log(e.detail) |
310 | if (e.detail.errMsg == 'getPhoneNumber:ok') { | 323 | if (e.detail.errMsg == 'getPhoneNumber:ok') { |
311 | this.setData({ | 324 | this.setData({ |
312 | encryptedData: e.detail.encryptedData, | 325 | encryptedData: e.detail.encryptedData, |
@@ -315,7 +328,6 @@ Page({ | @@ -315,7 +328,6 @@ Page({ | ||
315 | this.login() | 328 | this.login() |
316 | }) | 329 | }) |
317 | } | 330 | } |
318 | - | ||
319 | }, | 331 | }, |
320 | //去查看协议 | 332 | //去查看协议 |
321 | toProtocol() { | 333 | toProtocol() { |
@@ -331,7 +343,7 @@ Page({ | @@ -331,7 +343,7 @@ Page({ | ||
331 | }, | 343 | }, |
332 | goIndex() { | 344 | goIndex() { |
333 | wx.switchTab({ | 345 | wx.switchTab({ |
334 | - url: '/pages/index/index', | 346 | + url: '/pages/index/rank/rank', |
335 | }) | 347 | }) |
336 | }, | 348 | }, |
337 | 349 |
pages/login/codeLogin/codeLogin.wxss
@@ -0,0 +1,167 @@ | @@ -0,0 +1,167 @@ | ||
1 | +// pages/login/loginNew/loginNew.js | ||
2 | +import request from '../../../api/request.js' | ||
3 | +var appid = 'wx186236fdcd93edcc'; | ||
4 | +Page({ | ||
5 | + | ||
6 | + /** | ||
7 | + * 页面的初始数据 | ||
8 | + */ | ||
9 | + data: { | ||
10 | + checked: true, | ||
11 | + session_key: '', | ||
12 | + openId: '', | ||
13 | + encryptedData: '', | ||
14 | + iv: '', | ||
15 | + phone: '' | ||
16 | + }, | ||
17 | + //多选框 | ||
18 | + onChange(e) { | ||
19 | + this.setData({ | ||
20 | + checked: e.detail | ||
21 | + }) | ||
22 | + }, | ||
23 | + //获取session_key | ||
24 | + getOpenId() { | ||
25 | + return request({ | ||
26 | + url: `/wx/app/getOpenId/wx186236fdcd93edcc`, | ||
27 | + method: 'get', | ||
28 | + data: { | ||
29 | + code: this.data.loginCode | ||
30 | + }, | ||
31 | + }).then(res2 => { | ||
32 | + this.setData({ | ||
33 | + session_key: res2.data.sessionKey | ||
34 | + }) | ||
35 | + this.setData({ | ||
36 | + openId: res2.data.openid | ||
37 | + }) | ||
38 | + console.log(this.data); | ||
39 | + }) | ||
40 | + }, | ||
41 | + getPhoneNumber(e) { | ||
42 | + console.log('?') | ||
43 | + if(!this.data.checked) { | ||
44 | + return wx.showToast({title: '请先阅读并同意用户协议和隐私协议',icon: 'none'}) | ||
45 | + } | ||
46 | + console.log(e.detail) | ||
47 | + if (e.detail.errMsg == 'getPhoneNumber:ok') { | ||
48 | + this.setData({ | ||
49 | + encryptedData: e.detail.encryptedData, | ||
50 | + iv: e.detail.iv, | ||
51 | + }, () => { | ||
52 | + this.login() | ||
53 | + }) | ||
54 | + } | ||
55 | + }, | ||
56 | + login() { | ||
57 | + if (!this.data.encryptedData || !this.data.session_key || !this.data.iv) { | ||
58 | + wx.showToast({ | ||
59 | + title: '一键登陆失败,请重试', | ||
60 | + icon: 'none', | ||
61 | + duration: 2000 | ||
62 | + }) | ||
63 | + } | ||
64 | + request({ | ||
65 | + url: `/wx/app/oneClickLogin/`+ appid, | ||
66 | + method: 'post', | ||
67 | + data: { | ||
68 | + "encryptedData": this.data.encryptedData, | ||
69 | + "sessionKey": this.data.session_key, | ||
70 | + "iv": this.data.iv, | ||
71 | + "openId": this.data.openId | ||
72 | + }, | ||
73 | + }).then(res => { | ||
74 | + if (res.code == 0) { | ||
75 | + if (res.data) { | ||
76 | + this.setData({ | ||
77 | + phone: res.data.phone | ||
78 | + }, () => { | ||
79 | + wx.setStorageSync('userInfo', res.data) | ||
80 | + wx.setStorageSync('userInfo_id', res.data.id) | ||
81 | + if(res.data.hasRecord == 1) { | ||
82 | + wx.switchTab({ | ||
83 | + url: '/pages/index/rank/rank', | ||
84 | + }) | ||
85 | + }else { | ||
86 | + wx.switchTab({ | ||
87 | + url: '/pages/mine/index', | ||
88 | + }) | ||
89 | + } | ||
90 | + }) | ||
91 | + } else { | ||
92 | + wx.showToast({ | ||
93 | + title: '一键登陆失败,请重试', | ||
94 | + icon: 'none', | ||
95 | + duration: 2000 | ||
96 | + }) | ||
97 | + } | ||
98 | + } | ||
99 | + }) | ||
100 | + }, | ||
101 | + /** | ||
102 | + * 生命周期函数--监听页面加载 | ||
103 | + */ | ||
104 | + onLoad() { | ||
105 | + wx.login({ | ||
106 | + success: (res) => { | ||
107 | + if (res.code) { | ||
108 | + this.setData({ | ||
109 | + loginCode: res.code | ||
110 | + }) | ||
111 | + this.getOpenId() | ||
112 | + } else { | ||
113 | + console.log('登录失败!' + res.errMsg) | ||
114 | + } | ||
115 | + } | ||
116 | + }) | ||
117 | + }, | ||
118 | + | ||
119 | + /** | ||
120 | + * 生命周期函数--监听页面初次渲染完成 | ||
121 | + */ | ||
122 | + onReady() { | ||
123 | + | ||
124 | + }, | ||
125 | + | ||
126 | + /** | ||
127 | + * 生命周期函数--监听页面显示 | ||
128 | + */ | ||
129 | + onShow() { | ||
130 | + | ||
131 | + }, | ||
132 | + | ||
133 | + /** | ||
134 | + * 生命周期函数--监听页面隐藏 | ||
135 | + */ | ||
136 | + onHide() { | ||
137 | + | ||
138 | + }, | ||
139 | + | ||
140 | + /** | ||
141 | + * 生命周期函数--监听页面卸载 | ||
142 | + */ | ||
143 | + onUnload() { | ||
144 | + | ||
145 | + }, | ||
146 | + | ||
147 | + /** | ||
148 | + * 页面相关事件处理函数--监听用户下拉动作 | ||
149 | + */ | ||
150 | + onPullDownRefresh() { | ||
151 | + | ||
152 | + }, | ||
153 | + | ||
154 | + /** | ||
155 | + * 页面上拉触底事件的处理函数 | ||
156 | + */ | ||
157 | + onReachBottom() { | ||
158 | + | ||
159 | + }, | ||
160 | + | ||
161 | + /** | ||
162 | + * 用户点击右上角分享 | ||
163 | + */ | ||
164 | + onShareAppMessage() { | ||
165 | + | ||
166 | + } | ||
167 | +}) | ||
0 | \ No newline at end of file | 168 | \ No newline at end of file |
@@ -0,0 +1,8 @@ | @@ -0,0 +1,8 @@ | ||
1 | +{ | ||
2 | + "usingComponents": { | ||
3 | + "van-button": "@vant/weapp/button/index", | ||
4 | + "van-checkbox": "@vant/weapp/checkbox/index", | ||
5 | + "van-checkbox-group": "@vant/weapp/checkbox-group/index" | ||
6 | + }, | ||
7 | + "navigationBarTitleText": "登录" | ||
8 | +} | ||
0 | \ No newline at end of file | 9 | \ No newline at end of file |
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +<!--pages/login/loginNew/loginNew.wxml--> | ||
2 | +<view> | ||
3 | + <view class="box"> | ||
4 | + <view class="img_box"> | ||
5 | + <image class="pic" src="/img/login_img.png" alt="" /> | ||
6 | + </view> | ||
7 | + <view class="box_title">Hey</view> | ||
8 | + <view class="box_grey">欢迎使用自主学习之旅~</view> | ||
9 | + </view> | ||
10 | + <view class="fied_box"> | ||
11 | + <view> | ||
12 | + <van-button type="info" block round open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">登 录</van-button> | ||
13 | + </view> | ||
14 | + <view class="small_font"> | ||
15 | + <van-checkbox value="{{ checked }}" shape="square" bind:change="onChange" icon-size='15'> | ||
16 | + <view class="small_font_tip"> | ||
17 | + 已同意 <navigator url="../protocol/protocol"><text class="blue_font"> 用户协议 </text></navigator>和<navigator url="../policy/policy"><text class="blue_font"> 隐私协议 </text></navigator> | ||
18 | + </view> | ||
19 | + </van-checkbox> | ||
20 | + </view> | ||
21 | + <van-notify id="van-notify" /> | ||
22 | + </view> | ||
23 | +</view> | ||
0 | \ No newline at end of file | 24 | \ No newline at end of file |
@@ -0,0 +1,46 @@ | @@ -0,0 +1,46 @@ | ||
1 | +/* pages/login/loginNew/loginNew.wxss */ | ||
2 | +.box { | ||
3 | + display: flex; | ||
4 | + justify-content: center; | ||
5 | + flex-wrap: wrap; | ||
6 | +} | ||
7 | +.img_box { | ||
8 | + width: 60vw; | ||
9 | + height: 60vw; | ||
10 | + margin: 100px 0 30px; | ||
11 | +} | ||
12 | +.pic { | ||
13 | + width: 100%; | ||
14 | + height: 100%; | ||
15 | +} | ||
16 | +.box_title { | ||
17 | + width: 100%; | ||
18 | + text-align: center; | ||
19 | + margin: 15px 0; | ||
20 | + font-weight: bold; | ||
21 | +} | ||
22 | +.box_grey { | ||
23 | + width: 100%; | ||
24 | + text-align: center; | ||
25 | + color: #999; | ||
26 | +} | ||
27 | +.fied_box { | ||
28 | + position: fixed; | ||
29 | + bottom: 40px; | ||
30 | + width: 100%; | ||
31 | + padding: 0 30px; | ||
32 | + box-sizing: border-box; | ||
33 | +} | ||
34 | +.small_font { | ||
35 | + display: flex; | ||
36 | + justify-content: center; | ||
37 | + font-size: 12px; | ||
38 | + margin: 10px 0 0; | ||
39 | +} | ||
40 | +.small_font_tip { | ||
41 | + display: flex; | ||
42 | +} | ||
43 | +.blue_font { | ||
44 | + color: #3578F9; | ||
45 | + text-decoration:underline; | ||
46 | +} | ||
0 | \ No newline at end of file | 47 | \ No newline at end of file |
pages/login/policy/policy.json
pages/login/protocol/protocol.json
pages/mine/index.js
@@ -6,7 +6,9 @@ Page({ | @@ -6,7 +6,9 @@ Page({ | ||
6 | * 页面的初始数据 | 6 | * 页面的初始数据 |
7 | */ | 7 | */ |
8 | data: { | 8 | data: { |
9 | - | 9 | + user_name: '', |
10 | + user_phone: '', | ||
11 | + user_img: '', | ||
10 | }, | 12 | }, |
11 | // 打卡记录 | 13 | // 打卡记录 |
12 | handleRecord(){ | 14 | handleRecord(){ |
@@ -14,13 +16,26 @@ Page({ | @@ -14,13 +16,26 @@ Page({ | ||
14 | url: '/pages/mine/record/record', | 16 | url: '/pages/mine/record/record', |
15 | }) | 17 | }) |
16 | }, | 18 | }, |
17 | -// 退出登录 | 19 | + // 退出登录 |
18 | handleLoginOut(){ | 20 | handleLoginOut(){ |
21 | + wx.clearStorage() | ||
22 | + wx.clearStorageSync() | ||
19 | wx.navigateTo({ | 23 | wx.navigateTo({ |
20 | - url: '/pages/login/codeLogin/codeLogin', | 24 | + url: '/pages/login/loginNew/loginNew', |
21 | }) | 25 | }) |
22 | }, | 26 | }, |
23 | /** | 27 | /** |
28 | + * 生命周期函数--监听页面加载 | ||
29 | + */ | ||
30 | + onLoad(options) { | ||
31 | + let userInfo = wx.getStorageSync('userInfo') | ||
32 | + this.setData({ | ||
33 | + "user_name": userInfo.userName || userInfo.nickname, | ||
34 | + "user_phone": userInfo.phone, | ||
35 | + 'user_img':userInfo.headImg, | ||
36 | + }) | ||
37 | + }, | ||
38 | + /** | ||
24 | * 用户点击右上角分享 | 39 | * 用户点击右上角分享 |
25 | */ | 40 | */ |
26 | onShareAppMessage: function () { | 41 | onShareAppMessage: function () { |
pages/mine/index.wxml
1 | -<view class="mine"> | ||
2 | - <image class="temporary" src="../../img/_mine.png" mode="widthFix" alt="" /> | ||
3 | - <!-- 打卡记录 --> | ||
4 | - <text class="temporary_box" style="width: 340rpx;height: 160rpx;position: absolute;top: 340rpx;left: 32rpx;" bindtap="handleRecord"></text> | ||
5 | - <!-- 退出登录 --> | ||
6 | - <text class="temporary_box" style="width: 340rpx;height: 160rpx;position: absolute;top: 340rpx;right: 32rpx;" bindtap="handleLoginOut"></text> | ||
7 | - | 1 | +<view class="mine" style="background-image: url('https://szyundisk.oss-cn-hangzhou.aliyuncs.com/null/89741dbf-cc76-45a6-a3c9-a210eb7deeef.png')"> |
2 | + <view class="title"> | ||
3 | + <view> | ||
4 | + <image class="pic" src="{{user_img}}" alt="" /> | ||
5 | + </view> | ||
6 | + <view class="title_box"> | ||
7 | + <view class="title_name">{{user_name}}</view> | ||
8 | + <view class="grey_title">{{user_phone}}</view> | ||
9 | + </view> | ||
10 | + </view> | ||
11 | + <view class="flex_card"> | ||
12 | + <view class="card_item" bindtap="handleRecord"> | ||
13 | + <view><image class="card_pic" src="/img/answer/dkjl.png" alt="" /></view> | ||
14 | + <view class="item_font">创建打卡</view> | ||
15 | + </view> | ||
16 | + <view class="grey_line"></view> | ||
17 | + <view class="card_item" bindtap="handleLoginOut"> | ||
18 | + <view><image class="card_pic" src="/img/answer/back.png" alt="" /></view> | ||
19 | + <view class="item_font">退出登录</view> | ||
20 | + </view> | ||
21 | + </view> | ||
8 | </view> | 22 | </view> |
pages/mine/index.wxss
@@ -0,0 +1,59 @@ | @@ -0,0 +1,59 @@ | ||
1 | + .mine { | ||
2 | + position: absolute; | ||
3 | + width: 100vw; | ||
4 | + min-height: 40vh; | ||
5 | + background-size: 100% 100%; | ||
6 | + padding: 140px 5vw 0; | ||
7 | + box-sizing: border-box; | ||
8 | + } | ||
9 | + .title { | ||
10 | + display: flex; | ||
11 | + } | ||
12 | + .pic { | ||
13 | + width: 60px; | ||
14 | + height: 60px; | ||
15 | + border-radius: 60px; | ||
16 | + } | ||
17 | + .title_box { | ||
18 | + margin-left: 20px; | ||
19 | + display: flex; | ||
20 | + align-content: space-between; | ||
21 | + flex-wrap: wrap; | ||
22 | + padding: 4px 0; | ||
23 | + box-sizing: border-box; | ||
24 | + } | ||
25 | + .title_name { | ||
26 | + font-size: 18px; | ||
27 | + font-weight: bold; | ||
28 | + } | ||
29 | + .grey_title { | ||
30 | + width: 100%; | ||
31 | + font-size: 14px; | ||
32 | + color: #999; | ||
33 | + } | ||
34 | + .flex_card { | ||
35 | + display: flex; | ||
36 | + justify-content: space-between; | ||
37 | + padding: 20px 50px; | ||
38 | + box-sizing: border-box; | ||
39 | + box-shadow: 1px 1px 1px 1px rgb(224, 224, 224); | ||
40 | + margin: 40px 0; | ||
41 | + background-color: #fff; | ||
42 | + border-radius: 20px; | ||
43 | + } | ||
44 | + .card_item { | ||
45 | + text-align: center; | ||
46 | + } | ||
47 | + .card_pic { | ||
48 | + width: 30px; | ||
49 | + height: 30px; | ||
50 | +} | ||
51 | +.item_font { | ||
52 | + margin-top: 10px; | ||
53 | + color:#5A6694 | ||
54 | + } | ||
55 | + .grey_line { | ||
56 | + width: 1px ; | ||
57 | + height: 60px; | ||
58 | + background-color: #999; | ||
59 | + } | ||
0 | \ No newline at end of file | 60 | \ No newline at end of file |
pages/mine/record/record.js
1 | // pages/index/record/record.js | 1 | // pages/index/record/record.js |
2 | +import request from '../../../api/request.js' | ||
2 | Page({ | 3 | Page({ |
3 | 4 | ||
4 | /** | 5 | /** |
5 | * 页面的初始数据 | 6 | * 页面的初始数据 |
6 | */ | 7 | */ |
7 | data: { | 8 | data: { |
8 | - tabindex: 1 | 9 | + tabindex: 0, |
10 | + showAdd: false, | ||
11 | + taskList: [], | ||
12 | + | ||
13 | + tempList: [ | ||
14 | + // {name:'自定义模板',url: '/img/answer/zdy.png'}, | ||
15 | + // {name:'英语模板',url: '/img/answer/english.png'}, | ||
16 | + // {name:'数学模板',url: '/img/answer/math.png'}, | ||
17 | + ] | ||
9 | }, | 18 | }, |
10 | 19 | ||
11 | - /** | ||
12 | - * 生命周期函数--监听页面加载 | ||
13 | - */ | ||
14 | - onLoad(options) { | 20 | + //打卡记录列表 |
21 | + getTaskList() { | ||
22 | + request({ | ||
23 | + url: `/wx/task/cardTaskList`, | ||
24 | + method: 'post', | ||
25 | + data: { | ||
26 | + "oneselfFlag": this.data.tabindex + 1, | ||
27 | + "page": 1, | ||
28 | + "pageSize": 999, | ||
29 | + "userId": wx.getStorageSync("userInfo_id") | ||
30 | + }, | ||
31 | + }).then(res => { | ||
32 | + if (res.code == 0) { | ||
33 | + this.setData({ | ||
34 | + taskList: res.rows | ||
35 | + }) | ||
36 | + } else { | ||
37 | + wx.showToast({ | ||
38 | + title: res.msg, | ||
39 | + icon: 'none', | ||
40 | + duration: 1500 | ||
41 | + }) | ||
42 | + } | ||
43 | + }) | ||
44 | + }, | ||
45 | + | ||
46 | + //模板列表 | ||
47 | + getTempList() { | ||
48 | + request({ | ||
49 | + url: `/wx/temp/tempList`, | ||
50 | + method: 'post', | ||
51 | + data: {}, | ||
52 | + }).then(res => { | ||
53 | + if (res.code == 0) { | ||
54 | + this.setData({ | ||
55 | + tempList: res.data | ||
56 | + }) | ||
57 | + } else { | ||
58 | + wx.showToast({ | ||
59 | + title: res.msg, | ||
60 | + icon: 'none', | ||
61 | + duration: 1500 | ||
62 | + }) | ||
63 | + } | ||
64 | + }) | ||
65 | + }, | ||
15 | 66 | ||
67 | + //打卡 | ||
68 | + toShow(e) { | ||
69 | + this.getTempList() | ||
70 | + this.setData({ | ||
71 | + showAdd: true | ||
72 | + }) | ||
16 | }, | 73 | }, |
17 | - handleTab1() { | 74 | + //关闭 |
75 | + closeAdd() { | ||
18 | this.setData({ | 76 | this.setData({ |
19 | - tabindex: 1 | 77 | + showAdd: false |
78 | + }) | ||
79 | + }, | ||
80 | + //选择模板 | ||
81 | + toPunch(e) { | ||
82 | + let obj = e.currentTarget.dataset | ||
83 | + let id = obj.value ? obj.value.id : 0 | ||
84 | + wx.navigateTo({ | ||
85 | + url: `../../index/newPunch/newPunch?tempId=${id}` | ||
20 | }) | 86 | }) |
21 | }, | 87 | }, |
22 | - handleTab2() { | 88 | + /** |
89 | + * 生命周期函数--监听页面加载 | ||
90 | + */ | ||
91 | + onLoad(options) { | ||
92 | + this.getTaskList() | ||
93 | + }, | ||
94 | + //切换 | ||
95 | + handleTab(e) { | ||
23 | this.setData({ | 96 | this.setData({ |
24 | - tabindex: 2 | 97 | + tabindex: e.detail.index |
25 | }) | 98 | }) |
99 | + this.getTaskList() | ||
26 | }, | 100 | }, |
27 | // 打卡成果 | 101 | // 打卡成果 |
28 | - handleAchievement(){ | 102 | + handleAchievement(e) { |
29 | wx.navigateTo({ | 103 | wx.navigateTo({ |
30 | - url: '/pages/index/achievement/achievement', | 104 | + url: '/pages/index/achievement/achievement?valueId=' + e.currentTarget.dataset.valueid, |
31 | }) | 105 | }) |
32 | }, | 106 | }, |
33 | // 去打卡 | 107 | // 去打卡 |
34 | - handleDetail(){ | 108 | + handleDetail(e) { |
109 | + let eData = e.currentTarget.dataset | ||
35 | wx.navigateTo({ | 110 | wx.navigateTo({ |
36 | - url: '/pages/index/punchDetail/punchDetail', | 111 | + url: '/pages/index/punchDetail/punchDetail?valueId=' + eData.valueid, |
37 | }) | 112 | }) |
38 | }, | 113 | }, |
39 | // 统一返回 | 114 | // 统一返回 |
pages/mine/record/record.json
1 | { | 1 | { |
2 | "usingComponents": { | 2 | "usingComponents": { |
3 | - "van-icon": "@vant/weapp/icon/index" | 3 | + "van-icon": "@vant/weapp/icon/index", |
4 | + "van-tab": "@vant/weapp/tab/index", | ||
5 | + "van-tabs": "@vant/weapp/tabs/index", | ||
6 | + "van-popup": "@vant/weapp/popup/index" | ||
4 | }, | 7 | }, |
5 | - "navigationStyle": "custom" | 8 | + "navigationBarTitleText":"打卡记录" |
6 | } | 9 | } |
7 | \ No newline at end of file | 10 | \ No newline at end of file |
pages/mine/record/record.wxml
1 | <!--pages/index/record/record.wxml--> | 1 | <!--pages/index/record/record.wxml--> |
2 | <view class="punch_detail"> | 2 | <view class="punch_detail"> |
3 | - <!-- 顶部统一返回 --> | ||
4 | - <view class="navigation_back" bindtap="handleBack"> | ||
5 | - <van-icon name="arrow-left" /> | 3 | + <view> |
4 | + <van-tabs active="{{ tabindex }}" bind:change="handleTab" line-height='0' title-inactive-color='#999' title-active-color='#556191'> | ||
5 | + <van-tab title="我发布的"></van-tab> | ||
6 | + <van-tab title="我的打卡"></van-tab> | ||
7 | + </van-tabs> | ||
6 | </view> | 8 | </view> |
7 | - <!-- 两个tab --> | ||
8 | - <text class="temporary_box" style="width: 320rpx;height: 80rpx;position: absolute;top: 160rpx;left: 32rpx;" bindtap="handleTab1"></text> | ||
9 | - <text class="temporary_box" style="width: 320rpx;height: 80rpx;position: absolute;top: 160rpx;right: 32rpx;" bindtap="handleTab2"></text> | ||
10 | - <!-- 打卡成果 --> | ||
11 | - <text class="temporary_box" wx:if="{{tabindex==1}}" style="width: 700rpx;height: 100rpx;position: absolute;top: 988rpx;left: 32rpx;" bindtap="handleAchievement"></text> | ||
12 | - <!-- 打卡成果 --> | ||
13 | - <text class="temporary_box" wx:if="{{tabindex==2}}" style="width: 350rpx;height: 100rpx;position: absolute;top: 920rpx;left: 20rpx;" bindtap="handleAchievement"></text> | ||
14 | - <!-- 去打卡 --> | ||
15 | - <text class="temporary_box" wx:if="{{tabindex==2}}" style="width: 350rpx;height: 100rpx;position: absolute;top: 920rpx;right: 20rpx;" bindtap="handleDetail"></text> | ||
16 | - | ||
17 | - <image class="temporary" hidden="{{tabindex==2}}" src="/img/_my_punch1.png" mode="widthFix" alt="" /> | ||
18 | - <image class="temporary" hidden="{{tabindex==1}}" src="/img/_my_punch2.png" mode="widthFix" alt="" /> | 9 | + <view class="bck"> |
10 | + <view class="grey_font">进行中打卡</view> | ||
11 | + <view class="card" wx:for="{{taskList}}" wx:key="index" wx:for-item="value"> | ||
12 | + <view class="card_title"> | ||
13 | + <view class="title_L"> | ||
14 | + <image class="title_pic" src="/img/answer/bj.png" alt="" /> | ||
15 | + </view> | ||
16 | + <view class="title_R"> | ||
17 | + <view>{{value.taskTitle}}</view> | ||
18 | + <view class="grey_font">开始时间 {{value.startDate}}</view> | ||
19 | + </view> | ||
20 | + </view> | ||
21 | + <view class="day_font" >{{value.taskDesc}}</view> | ||
22 | + <!-- <view class="day_font2">已坚持打卡 | ||
23 | + <text class="day_font2_large">1/50 </text>天 | ||
24 | + </view> --> | ||
25 | + <view> | ||
26 | + <van-progress percentage="50" color='#3F5EFF' stroke-width="13" pivot-text=' ' /> | ||
27 | + </view> | ||
28 | + <view class="flex_font"> | ||
29 | + <text class="grey_flex">打卡频次:</text> | ||
30 | + {{value.taskFrequency}} | ||
31 | + </view> | ||
32 | + <view class="flex_font" wx:if="{{value.submitCondition != null}}"> | ||
33 | + <text class="grey_flex">打卡要求:</text> | ||
34 | + {{ value.submitCondition == '无限制' ? '无限制': '需要 '+value.submitCondition}} | ||
35 | + </view> | ||
36 | + <view class="flex_font"> | ||
37 | + <view class="grey_flex">其他:</view> | ||
38 | + {{value.allowRepairCard == 1 ? '允许补卡': '不允许补卡'}} | ||
39 | + </view> | ||
40 | + <view class="grey_line"></view> | ||
41 | + <view class="blue_font" wx:if="{{tabindex == 0}}"> | ||
42 | + <view bindtap="handleAchievement" data-valueId="{{value.id}}">我的成果</view> | ||
43 | + <view class="blue_line"></view> | ||
44 | + <view bindtap="handleDetail" data-valueId="{{value.id}}">去打卡</view> | ||
45 | + </view> | ||
46 | + <view class="blue_font" wx:else> | ||
47 | + <view bindtap="handleAchievement" data-valueId="{{value.id}}">打卡成果</view> | ||
48 | + </view> | ||
49 | + </view> | ||
19 | 50 | ||
51 | + <view class="blue_tip" bindtap="toShow"> | ||
52 | + <image class="img_tip" src="/img/answer/add.png" alt="" /> | ||
53 | + </view> | ||
54 | + </view> | ||
55 | + | ||
56 | + <!-- 弹窗 --> | ||
57 | + <van-popup show="{{ showAdd }}" round position="bottom" custom-style="height: 60%;" bind:close="closeAdd"> | ||
58 | + <view class="pop_card"> | ||
59 | + <view class="pop_title">选择模板</view> | ||
60 | + <view class="tem_box"> | ||
61 | + <view class="tem_item" bindtap="toPunch" > | ||
62 | + <image class="tem_pic" src="/img/answer/zdy.png" alt="" /> | ||
63 | + <view class="tem_font">自定义模板</view> | ||
64 | + </view> | ||
65 | + <view class="tem_item" wx:for="{{tempList}}" wx:key="index" wx:for-item="value" bindtap="toPunch" data-value="{{value}}"> | ||
66 | + <image class="tem_pic" src="{{value.taskBackground}}" alt="" /> | ||
67 | + <view class="tem_font">{{value.taskTitle}}</view> | ||
68 | + </view> | ||
69 | + </view> | ||
70 | + </view> | ||
71 | + </van-popup> | ||
20 | </view> | 72 | </view> |
21 | \ No newline at end of file | 73 | \ No newline at end of file |
pages/mine/record/record.wxss
1 | /* pages/index/record/record.wxss */ | 1 | /* pages/index/record/record.wxss */ |
2 | +.punch_detail { | ||
3 | + position: absolute; | ||
4 | + width: 100vw; | ||
5 | + height: 100vh; | ||
6 | + background-color: #F5F6FA; | ||
7 | +} | ||
8 | + | ||
9 | +.bck { | ||
10 | + padding: 20px 4vw; | ||
11 | + box-sizing: border-box; | ||
12 | +} | ||
13 | + | ||
14 | +.grey_font { | ||
15 | + width: 100%; | ||
16 | + color: #999; | ||
17 | + font-size: 14px; | ||
18 | + margin-bottom: 15px; | ||
19 | +} | ||
20 | + | ||
21 | +/**/ | ||
22 | + | ||
23 | +.card { | ||
24 | + width: 92vw; | ||
25 | + background-color: #fff; | ||
26 | + border-radius: 8vw; | ||
27 | + padding: 8vw; | ||
28 | + margin-bottom: 30px; | ||
29 | + box-sizing: border-box; | ||
30 | + box-shadow: 1px 1px 1px 1px rgb(228, 228, 228); | ||
31 | +} | ||
32 | + | ||
33 | +.card_title { | ||
34 | + display: flex; | ||
35 | +} | ||
36 | + | ||
37 | +.title_L { | ||
38 | + flex-shrink: 0; | ||
39 | + width: 50px; | ||
40 | + height: 50px; | ||
41 | + margin-right: 15px; | ||
42 | +} | ||
43 | + | ||
44 | +.title_pic { | ||
45 | + width: 100%; | ||
46 | + height: 100%; | ||
47 | +} | ||
48 | + | ||
49 | +.title_R { | ||
50 | + height: 65px; | ||
51 | + display: flex; | ||
52 | + align-content: space-between; | ||
53 | + flex-wrap: wrap; | ||
54 | + font-size: 4.6vw; | ||
55 | +} | ||
56 | + | ||
57 | +/* .grey_font { | ||
58 | + width: 100%; | ||
59 | + color: #999; | ||
60 | + font-size: 3.8vw; | ||
61 | +} */ | ||
62 | + | ||
63 | +.day_font { | ||
64 | + margin: 10px 0 20px; | ||
65 | + letter-spacing: 0.2vw; | ||
66 | + font-size: 4vw; | ||
67 | +} | ||
68 | + | ||
69 | +.day_font2 { | ||
70 | + margin: 20px 0; | ||
71 | + letter-spacing: 0.2vw; | ||
72 | + font-size: 3.8vw; | ||
73 | +} | ||
74 | + | ||
75 | +.day_font2_large { | ||
76 | + font-size: 5.5vw; | ||
77 | + font-weight: bold; | ||
78 | +} | ||
79 | + | ||
80 | +.flex_font { | ||
81 | + font-size: 3.5vw; | ||
82 | + margin: 20px 0; | ||
83 | + display: flex; | ||
84 | +} | ||
85 | + | ||
86 | +.grey_flex { | ||
87 | + width: 80px; | ||
88 | + color: #999; | ||
89 | +} | ||
90 | + | ||
91 | +.grey_line { | ||
92 | + width: 100%; | ||
93 | + height: 1px; | ||
94 | + background-color: #EAEAEA; | ||
95 | +} | ||
96 | + | ||
97 | +.blue_font { | ||
98 | + display: flex; | ||
99 | + justify-content: space-around; | ||
100 | + margin-top: 15px; | ||
101 | + font-size: 4.1vw; | ||
102 | + color: #458EF8; | ||
103 | + font-weight: 540; | ||
104 | +} | ||
105 | + | ||
106 | +.blue_line { | ||
107 | + width: 1px; | ||
108 | + height: 15px; | ||
109 | + background-color: #EAEAEA; | ||
110 | +} | ||
111 | + | ||
112 | +.blue_tip { | ||
113 | + position: fixed; | ||
114 | + bottom: 50px; | ||
115 | + right: 3vw; | ||
116 | +} | ||
117 | + | ||
118 | +.img_tip { | ||
119 | + width: 70px; | ||
120 | + height: 70px; | ||
121 | +} | ||
122 | + | ||
123 | +.pop_card { | ||
124 | + padding: 5vw; | ||
125 | + box-sizing: border-box; | ||
126 | + } | ||
127 | + | ||
128 | + .pop_title { | ||
129 | + font-size: 4.8vw; | ||
130 | + font-weight: bold; | ||
131 | + letter-spacing: 1px; | ||
132 | + margin-bottom: 30px; | ||
133 | + } | ||
134 | + | ||
135 | + .tem_box { | ||
136 | + display: flex; | ||
137 | + flex-wrap: wrap; | ||
138 | + } | ||
139 | + | ||
140 | + .tem_item { | ||
141 | + width: 23vw; | ||
142 | + height: 170px; | ||
143 | + text-align: center; | ||
144 | + margin: 0 3vw 30px; | ||
145 | + } | ||
146 | + | ||
147 | + .tem_pic { | ||
148 | + width: 23vw; | ||
149 | + height: 120px; | ||
150 | + border-radius: 10px; | ||
151 | + } | ||
152 | + | ||
153 | + .tem_font { | ||
154 | + font-size: 3.9vw; | ||
155 | + margin-top: 10px; | ||
156 | + } | ||
2 | \ No newline at end of file | 157 | \ No newline at end of file |