Compare View
Commits (5)
-
结构调整
-
打卡模板创建
-
打卡功能简单版
Showing
92 changed files
Show diff stats
app.js
... | ... | @@ -44,9 +44,10 @@ App({ |
44 | 44 | view.onShareAppMessage = function () { |
45 | 45 | //你的分享配置 |
46 | 46 | return { |
47 | - title: name + '推荐大家都在用的升学大数据宝典', | |
47 | + title: name + '推荐您 一起开始自主学习之旅', | |
48 | 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 | 2 | "pages": [ |
3 | - "pages/index/index", | |
4 | - "pages/index/rank/rank", | |
3 | + "pages/login/loginNew/loginNew", | |
4 | + "pages/login/codeLogin/codeLogin", | |
5 | 5 | "pages/index/achievement/achievement", |
6 | - "pages/index/punchDetail/punchDetail", | |
6 | + "pages/index/rank/rank", | |
7 | + "pages/index/index", | |
7 | 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 | 12 | "pages/login/protocol/protocol", |
10 | 13 | "pages/login/policy/policy", |
11 | - "pages/mine/index", | |
12 | - "pages/mine/record/record", | |
13 | 14 | "pages/webview/webview" |
14 | 15 | ], |
15 | 16 | "window": { |
16 | 17 | "backgroundTextStyle": "dark", |
17 | 18 | "navigationBarBackgroundColor": "#fff", |
18 | - "navigationBarTitleText": "计划管家", | |
19 | + "navigationBarTitleText": "打卡管理", | |
19 | 20 | "navigationBarTextStyle": "black" |
20 | 21 | }, |
21 | 22 | "tabBar": { |
... | ... | @@ -24,7 +25,7 @@ |
24 | 25 | "borderStyle": "white", |
25 | 26 | "list": [ |
26 | 27 | { |
27 | - "pagePath": "pages/index/index", | |
28 | + "pagePath": "pages/index/rank/rank", | |
28 | 29 | "text": "首页", |
29 | 30 | "iconPath": "./img/tab_home_normat.png", |
30 | 31 | "selectedIconPath": "./img/tab_home_selected.png" | ... | ... |
app.wxss
... | ... | @@ -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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 | 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 | 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 | 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 | 6 | "dependencies": { |
22 | 7 | "@vant/weapp": { |
23 | 8 | "version": "1.10.5", |
24 | 9 | "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.10.5.tgz", |
25 | 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
pages/index/achievement/achievement.js
1 | 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 | 11 | Page({ |
3 | 12 | |
4 | 13 | /** |
5 | 14 | * 页面的初始数据 |
6 | 15 | */ |
7 | 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 | 134 | onLoad(options) { |
14 | - | |
135 | + this.setData({ | |
136 | + valueId: options.valueId | |
137 | + }) | |
15 | 138 | }, |
16 | 139 | // 统一返回 |
17 | 140 | handleBack() { |
18 | 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 | 151 | \ No newline at end of file | ... | ... |
pages/index/achievement/achievement.json
1 | 1 | { |
2 | 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 | 12 | \ No newline at end of file | ... | ... |
pages/index/achievement/achievement.wxml
1 | 1 | <!--pages/index/achievement/achievement.wxml--> |
2 | 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 | 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 | 31 | </view> |
10 | 32 | \ No newline at end of file | ... | ... |
pages/index/achievement/achievement.wxss
1 | 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 | 135 | \ No newline at end of file | ... | ... |
pages/index/index.js
... | ... | @@ -4,63 +4,73 @@ import request from '../../api/request.js' |
4 | 4 | |
5 | 5 | Page({ |
6 | 6 | data: { |
7 | - showAdd: false, //新建打卡 | |
8 | - tabindex: 1, | |
7 | + active: 1, | |
8 | + taskList: [] | |
9 | 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 | 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 | 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 | 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 | 76 | // 获取banner图 | ... | ... |
pages/index/index.json
1 | 1 | { |
2 | 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 | 8 | "navigationBarTextStyle": "black", |
6 | - "navigationStyle": "custom" | |
9 | + "navigationBarTitleText": "打卡" | |
7 | 10 | } |
8 | 11 | \ No newline at end of file | ... | ... |
pages/index/index.wxml
1 | 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 | 54 | </view> |
22 | 55 | \ No newline at end of file | ... | ... |
pages/index/index.wxss
... | ... | @@ -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 | 197 | \ No newline at end of file | ... | ... |
pages/index/newPunch/newPunch.js
1 | 1 | // pages/index/rank/rank.js |
2 | +import request from '../../../api/request.js' | |
3 | +import moment from 'moment'; | |
2 | 4 | Page({ |
3 | 5 | |
4 | 6 | /** |
5 | 7 | * 页面的初始数据 |
6 | 8 | */ |
7 | 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 | 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 | 250 | // console.log(111) |
19 | 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 | 261 | */ |
30 | 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 | 415 | \ No newline at end of file | ... | ... |
pages/index/newPunch/newPunch.json
1 | 1 | { |
2 | 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 | 16 | \ No newline at end of file | ... | ... |
pages/index/newPunch/newPunch.wxml
1 | 1 | <!--pages/index/rank/rank.wxml--> |
2 | 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 | 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 | 125 | </view> |
12 | 126 | \ No newline at end of file | ... | ... |
pages/index/newPunch/newPunch.wxss
1 | 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 | 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 | 11 | Page({ |
3 | 12 | |
4 | 13 | /** |
5 | 14 | * 页面的初始数据 |
6 | 15 | */ |
7 | 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 | 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 | 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 | 176 | this.setData({ |
35 | - showEdit: false | |
177 | + clockShow: true | |
36 | 178 | }) |
37 | 179 | }, |
38 | - // 提交打卡信息,跳转打卡成功页面 | |
39 | - handleSubmit() { | |
180 | + //确定-打卡 | |
181 | + toCardTask() { | |
40 | 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 | 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 | 232 | handleBack() { |
52 | 233 | wx.navigateBack() |
53 | 234 | }, |
... | ... | @@ -56,5 +237,79 @@ Page({ |
56 | 237 | */ |
57 | 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 | 316 | \ No newline at end of file | ... | ... |
pages/index/punchDetail/punchDetail.json
1 | 1 | { |
2 | 2 | "usingComponents": { |
3 | 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 | 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 | 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 | 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 | 51 | </van-popup> |
26 | 52 | </view> |
27 | 53 | \ No newline at end of file | ... | ... |
pages/index/punchDetail/punchDetail.wxss
1 | 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 | 92 | \ No newline at end of file | ... | ... |
pages/index/rank/rank.js
1 | 1 | // pages/index/rank/rank.js |
2 | +import request from '../../../api/request.js' | |
3 | +import moment from 'moment'; | |
2 | 4 | Page({ |
3 | 5 | |
4 | 6 | /** |
5 | 7 | * 页面的初始数据 |
6 | 8 | */ |
7 | 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 | 85 | onLoad(options) { |
14 | - | |
86 | + | |
15 | 87 | }, |
16 | 88 | // 统一返回 |
17 | 89 | handleBack() { |
18 | 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 | 103 | \ No newline at end of file | ... | ... |
pages/index/rank/rank.json
pages/index/rank/rank.wxml
1 | 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 | 40 | </view> |
10 | 41 | \ No newline at end of file | ... | ... |
pages/index/rank/rank.wxss
1 | 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 | 96 | \ No newline at end of file | ... | ... |
pages/login/codeLogin/codeLogin.js
1 | 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 | 6 | var util = require('../../../utils/md5.js') |
4 | 7 | import request from '../../../api/request.js' |
5 | 8 | Page({ |
... | ... | @@ -21,6 +24,7 @@ Page({ |
21 | 24 | path: '', //登录后跳转页面 |
22 | 25 | modelShow: false, //完善信息 |
23 | 26 | phone: '', //getUserInfo获取到的手机号 |
27 | + openId: '' | |
24 | 28 | }, |
25 | 29 | onLoad: function (options) { |
26 | 30 | console.log('登录页options:', options) |
... | ... | @@ -69,20 +73,25 @@ Page({ |
69 | 73 | }) |
70 | 74 | } |
71 | 75 | request({ |
72 | - url: `h5/user/Oneclicklogin`, | |
73 | - method: 'get', | |
76 | + url: `/wx/app/oneClickLogin/`+ appid, | |
77 | + method: 'post', | |
74 | 78 | data: { |
75 | 79 | "encryptedData": this.data.encryptedData, |
76 | - "session_key": this.data.session_key, | |
80 | + "sessionKey": this.data.session_key, | |
77 | 81 | "iv": this.data.iv, |
82 | + "openId": this.data.openId | |
78 | 83 | }, |
79 | 84 | }).then(res => { |
80 | - if (res.success) { | |
85 | + if (res.code == 0) { | |
81 | 86 | if (res.data) { |
82 | 87 | this.setData({ |
83 | 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 | 96 | } else { |
88 | 97 | wx.showToast({ |
... | ... | @@ -107,36 +116,39 @@ Page({ |
107 | 116 | } |
108 | 117 | }, |
109 | 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 | 138 | return request({ |
130 | - url: `h5/MyVoluntary/GetOpenId`, | |
139 | + url: `/wx/app/getOpenId/wx186236fdcd93edcc`, | |
131 | 140 | method: 'get', |
132 | 141 | data: { |
133 | 142 | code: this.data.loginCode |
134 | 143 | }, |
135 | 144 | }).then(res2 => { |
136 | - // console.log(res2.data); | |
137 | 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 | 154 | bindUserName: function (e) { |
... | ... | @@ -181,16 +193,17 @@ Page({ |
181 | 193 | wx.showLoading({ |
182 | 194 | title: '请求中', |
183 | 195 | }) |
184 | - wx.request({ | |
185 | - url: api + 'h5/MyVoluntary/CheckCodeIsRight', | |
196 | + wx.request({ | |
197 | + url: api_card + '/wx/app/loginCode', | |
186 | 198 | data: { |
187 | - captcha: code, | |
188 | - mobile: username | |
199 | + code: code, | |
200 | + phone: username | |
189 | 201 | }, |
190 | - method: 'get', | |
202 | + method: 'post', | |
191 | 203 | success: (res) => { |
192 | 204 | wx.hideLoading(); |
193 | 205 | if (res.data.success) { |
206 | + console.log(res.data) | |
194 | 207 | if (res.data.data) { |
195 | 208 | this.setData({ |
196 | 209 | phone: res.data.data.phone |
... | ... | @@ -306,7 +319,7 @@ Page({ |
306 | 319 | } |
307 | 320 | }, |
308 | 321 | getPhoneNumber(e) { |
309 | - // console.log(e.detail) | |
322 | + console.log(e.detail) | |
310 | 323 | if (e.detail.errMsg == 'getPhoneNumber:ok') { |
311 | 324 | this.setData({ |
312 | 325 | encryptedData: e.detail.encryptedData, |
... | ... | @@ -315,7 +328,6 @@ Page({ |
315 | 328 | this.login() |
316 | 329 | }) |
317 | 330 | } |
318 | - | |
319 | 331 | }, |
320 | 332 | //去查看协议 |
321 | 333 | toProtocol() { |
... | ... | @@ -331,7 +343,7 @@ Page({ |
331 | 343 | }, |
332 | 344 | goIndex() { |
333 | 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 @@ |
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 | 168 | \ No newline at end of file | ... | ... |
... | ... | @@ -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 | 24 | \ No newline at end of file | ... | ... |
... | ... | @@ -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 | 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 | 6 | * 页面的初始数据 |
7 | 7 | */ |
8 | 8 | data: { |
9 | - | |
9 | + user_name: '', | |
10 | + user_phone: '', | |
11 | + user_img: '', | |
10 | 12 | }, |
11 | 13 | // 打卡记录 |
12 | 14 | handleRecord(){ |
... | ... | @@ -14,13 +16,26 @@ Page({ |
14 | 16 | url: '/pages/mine/record/record', |
15 | 17 | }) |
16 | 18 | }, |
17 | -// 退出登录 | |
19 | + // 退出登录 | |
18 | 20 | handleLoginOut(){ |
21 | + wx.clearStorage() | |
22 | + wx.clearStorageSync() | |
19 | 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 | 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 | 22 | </view> | ... | ... |
pages/mine/index.wxss
... | ... | @@ -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 | 60 | \ No newline at end of file | ... | ... |
pages/mine/record/record.js
1 | 1 | // pages/index/record/record.js |
2 | +import request from '../../../api/request.js' | |
2 | 3 | Page({ |
3 | 4 | |
4 | 5 | /** |
5 | 6 | * 页面的初始数据 |
6 | 7 | */ |
7 | 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 | 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 | 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 | 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 | 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 | 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 | 10 | \ No newline at end of file | ... | ... |
pages/mine/record/record.wxml
1 | 1 | <!--pages/index/record/record.wxml--> |
2 | 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 | 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 | 72 | </view> |
21 | 73 | \ No newline at end of file | ... | ... |
pages/mine/record/record.wxss
1 | 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 | 157 | \ No newline at end of file | ... | ... |