sh-view 2.6.5 → 2.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh-view",
3
- "version": "2.6.5",
3
+ "version": "2.6.6",
4
4
  "description": "基于vxe-table二次封装",
5
5
  "main": "packages/index.js",
6
6
  "scripts": {
@@ -27,6 +27,7 @@
27
27
  "exceljs": "^4.3.0",
28
28
  "jspdf": "^2.5.1",
29
29
  "jszip": "^3.10.1",
30
+ "lunar-javascript": "^1.6.4",
30
31
  "popper.js": "^1.16.1",
31
32
  "sh-tools": "^2.1.6",
32
33
  "tinymce": "^5.10.5",
@@ -0,0 +1,502 @@
1
+ <template>
2
+ <div class="sh-calendar">
3
+ <div v-if="header" class="sh-calendar-row sh-calendar-head">
4
+ <div class="info">{{ monthInfo }}</div>
5
+ <div class="extra">
6
+ <template v-for="item in headerHandles" :key="item.code">
7
+ <span class="sh-calendar-btn" @click="handleBtn(item)"><i :class="item.icon"></i></span>
8
+ </template>
9
+ </div>
10
+ </div>
11
+ <table class="sh-calendar-table" v-bind="tableConfig">
12
+ <thead>
13
+ <tr>
14
+ <template v-for="(head, headIndex) in headers" :key="headIndex">
15
+ <th>{{ head.label }}</th>
16
+ </template>
17
+ </tr>
18
+ </thead>
19
+ <tbody @mouseleave="dateMouseleaveEvent">
20
+ <template v-for="(row, rowIndex) in dayDatas" :key="rowIndex">
21
+ <tr>
22
+ <template v-for="(item, itemIndex) in row" :key="itemIndex">
23
+ <td :class="getCellClass(item)" @mouseenter="dateMouseenterEvent(item)" @click="dateSelectEvent(item)">
24
+ <slot name="cell" v-bind="item">
25
+ <div class="sh-calendar-cell" :style="{ textAlign: align }">
26
+ <div class="sh-calendar-cell-head">{{ item.label }}</div>
27
+ <div v-if="note" class="sh-calendar-cell-body" :style="{ height: noteHeight }">{{ noteMethod(item) }}</div>
28
+ <div v-if="festival" class="sh-calendar-cell-foot">{{ getLunarDate(item.date) }}</div>
29
+ </div>
30
+ </slot>
31
+ </td>
32
+ </template>
33
+ </tr>
34
+ </template>
35
+ </tbody>
36
+ </table>
37
+ <div v-if="footer" class="sh-calendar-foot">
38
+ <div class="sh-calendar-row">
39
+ <div class="info">
40
+ <div>{{ lunarInfo.day }}</div>
41
+ <div class="sh-calendar-title">{{ lunarInfo.lunarMonth }}月 {{ lunarInfo.lunarDay }}</div>
42
+ <div class="sh-calendar-title">{{ lunarInfo.jq }}</div>
43
+ </div>
44
+ <div class="info right">
45
+ <div class="sh-calendar-title">{{ lunarInfo.yearGanZhi }}年 {{ lunarInfo.yearShengXiao }}</div>
46
+ <div>{{ lunarInfo.monthGanZhi }}月 {{ lunarInfo.dayGanZhi }}</div>
47
+ </div>
48
+ </div>
49
+ <div class="sh-calendar-row">
50
+ <div class="extra"><span class="sh-calendar-tag yi">宜</span></div>
51
+ <div class="info">
52
+ <template v-for="(y, yIndex) in lunarInfo.yi" :key="yIndex">
53
+ <span class="sh-calendar-span">{{ y }}</span>
54
+ </template>
55
+ </div>
56
+ </div>
57
+ <div class="sh-calendar-row">
58
+ <div class="extra"><span class="sh-calendar-tag ji">忌</span></div>
59
+ <div class="info">
60
+ <template v-for="(j, jIndex) in lunarInfo.ji" :key="jIndex">
61
+ <span class="sh-calendar-span">{{ j }}</span>
62
+ </template>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </template>
68
+
69
+ <script>
70
+ import { computed, defineComponent, getCurrentInstance, ref, reactive, onBeforeMount, PropType, watch } from 'vue'
71
+ import { Lunar, HolidayUtil } from 'lunar-javascript'
72
+ export default defineComponent({
73
+ name: 'ShCalendar',
74
+ props: {
75
+ modelValue: [String, Number, Date],
76
+ type: { type: String, default: 'day' }, // day, month, year 暂时只支持day
77
+ startDay: { type: [String, Number], default: 1 },
78
+ align: { type: String, default: 'center' },
79
+ header: { type: Boolean, default: true },
80
+ footer: { type: Boolean, default: false },
81
+ note: { type: Boolean, default: false }, // 是否备注
82
+ noteHeight: { type: String, default: '22px' }, // 备注高度
83
+ noteMethod: { type: Function, default() {} },
84
+ festival: { type: Boolean, default: false }, // 是否显示农历
85
+ valueFormat: { type: String, default: '' },
86
+ weeks: {
87
+ type: Array,
88
+ default() {
89
+ return ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
90
+ }
91
+ }
92
+ },
93
+ emits: ['update:modelValue', 'change'],
94
+ setup(props, context) {
95
+ const { proxy } = getCurrentInstance()
96
+ const { $vUtils } = proxy
97
+ const { emit, slots } = context
98
+
99
+ const headerHandles = [
100
+ { code: 'prev', icon: 'vxe-icon-caret-left' },
101
+ { code: 'current', icon: 'vxe-icon-dot' },
102
+ { code: 'next', icon: 'vxe-icon-caret-right' }
103
+ ]
104
+ const reactData = reactive({
105
+ inputValue: props.modelValue,
106
+ panelValue: null,
107
+ panelLabel: '',
108
+ selectMonth: null,
109
+ currentDate: null
110
+ })
111
+ const computeFirstDayOfWeek = computed(() => {
112
+ const { startDay, startWeek } = props
113
+ return $vUtils.toNumber($vUtils.isNumber(startDay) || $vUtils.isString(startDay) ? startDay : startWeek)
114
+ })
115
+ const computeWeekDatas = computed(() => {
116
+ const weeks = []
117
+ let sWeek = computeFirstDayOfWeek.value
118
+ weeks.push(sWeek)
119
+ for (let index = 0; index < 6; index++) {
120
+ if (sWeek >= 6) {
121
+ sWeek = 0
122
+ } else {
123
+ sWeek++
124
+ }
125
+ weeks.push(sWeek)
126
+ }
127
+ return weeks
128
+ })
129
+ const computeDateHMSTime = computed(() => {
130
+ const dateValue = computeDateValue.value
131
+ return dateValue ? (dateValue.getHours() * 3600 + dateValue.getMinutes() * 60 + dateValue.getSeconds()) * 1000 : 0
132
+ })
133
+ const computeDayList = computed(() => {
134
+ const { selectMonth, currentDate } = reactData
135
+ const days = []
136
+ if (selectMonth && currentDate) {
137
+ const dateHMSTime = computeDateHMSTime.value
138
+ const weekDatas = computeWeekDatas.value
139
+ const currFullYear = currentDate.getFullYear()
140
+ const currMonth = currentDate.getMonth()
141
+ const currDate = currentDate.getDate()
142
+ const selFullYear = selectMonth.getFullYear()
143
+ const selMonth = selectMonth.getMonth()
144
+ const selDay = selectMonth.getDay()
145
+ const prevOffsetDate = -weekDatas.indexOf(selDay)
146
+ const startDayDate = new Date($vUtils.getWhatDay(selectMonth, prevOffsetDate).getTime() + dateHMSTime)
147
+ for (let index = 0; index < 42; index++) {
148
+ const date = $vUtils.getWhatDay(startDayDate, index)
149
+ const itemFullYear = date.getFullYear()
150
+ const itemMonth = date.getMonth()
151
+ const itemDate = date.getDate()
152
+ const isPrev = date < selectMonth
153
+ days.push({
154
+ date,
155
+ isPrev,
156
+ isCurrent: itemFullYear === selFullYear && itemMonth === selMonth,
157
+ isNow: itemFullYear === currFullYear && itemMonth === currMonth && itemDate === currDate,
158
+ isNext: !isPrev && selMonth !== itemMonth,
159
+ label: itemDate
160
+ })
161
+ }
162
+ }
163
+ return days
164
+ })
165
+
166
+ // 以下为日历需要
167
+ const tableConfig = computed(() => ({ cellspacing: 0, cellpadding: 0, border: 0 }))
168
+ const headers = computed(() => {
169
+ const weekDatas = computeWeekDatas.value
170
+ return weekDatas.map(day => {
171
+ return { value: day, label: props.weeks[day] }
172
+ })
173
+ })
174
+ const dayDatas = computed(() => {
175
+ const dayList = computeDayList.value
176
+ return $vUtils.chunk(dayList, 7)
177
+ })
178
+ const computeDateValue = computed(() => {
179
+ const { inputValue } = reactData
180
+ let val = null
181
+ if (inputValue) {
182
+ const date = $vUtils.toStringDate(inputValue, props.valueFormat)
183
+ if ($vUtils.isValidDate(date)) {
184
+ val = date
185
+ }
186
+ }
187
+ return val
188
+ })
189
+ const monthInfo = computed(() => $vUtils.toDateString(reactData.selectMonth, 'yyyy 年 MM 月'))
190
+ const dayInfo = computed(() => $vUtils.toDateString(reactData.currentDate, 'yyyyMMdd'))
191
+ const lunarInfo = computed(() => {
192
+ let dayDate = reactData.inputValue || reactData.currentDate
193
+ let lunarDate = Lunar.fromDate(dayDate)
194
+ return {
195
+ day: $vUtils.toDateString(dayDate, 'yyyy 年 MM 月 dd 日'),
196
+ lunarMonth: lunarDate.getMonthInChinese(),
197
+ lunarDay: lunarDate.getDayInChinese(),
198
+ yearGanZhi: lunarDate.getYearInGanZhi(),
199
+ yearShengXiao: lunarDate.getYearShengXiao(),
200
+ monthGanZhi: lunarDate.getMonthInGanZhi(),
201
+ dayGanZhi: lunarDate.getDayInGanZhi(),
202
+ yi: lunarDate.getDayYi(),
203
+ ji: lunarDate.getDayJi(),
204
+ jq: lunarDate.getJieQi()
205
+ }
206
+ })
207
+ const isDateDisabled = item => {
208
+ const { disabledMethod } = props
209
+ return disabledMethod && disabledMethod({ type: props.type, date: item.date })
210
+ }
211
+ const dateChange = date => {
212
+ emitValue(date)
213
+ emit('change', date)
214
+ }
215
+ const dateSelectItem = date => {
216
+ const { type } = props
217
+ if (type === 'month') {
218
+ } else if (type === 'year') {
219
+ } else {
220
+ dateChange(date)
221
+ }
222
+ }
223
+ const dateCheckMonth = date => {
224
+ const month = $vUtils.getWhatMonth(date, 0, 'first')
225
+ if (!$vUtils.isEqual(month, reactData.selectMonth)) {
226
+ reactData.selectMonth = month
227
+ }
228
+ }
229
+ const dateMoveDay = date => {
230
+ if (isDateDisabled(date)) return
231
+ const dayList = computeDayList.value
232
+ if (!dayList.some(item => $vUtils.isDateSame(item.date, date.date, 'yyyyMMdd'))) {
233
+ dateCheckMonth(date.date)
234
+ }
235
+ dateParseValue(date.date)
236
+ }
237
+ const dateSelectEvent = item => {
238
+ if (isDateDisabled(item)) return
239
+ dateSelectItem(item.date)
240
+ }
241
+ const dateMouseenterEvent = item => {
242
+ if (isDateDisabled(item)) return
243
+ const { datePanelType } = reactData
244
+ if (datePanelType === 'month') {
245
+ // dateMoveMonth(item.date)
246
+ } else if (datePanelType === 'year') {
247
+ // dateMoveYear(item.date)
248
+ } else {
249
+ dateMoveDay(item)
250
+ }
251
+ }
252
+ const dateMouseleaveEvent = () => {
253
+ dateParseValue()
254
+ }
255
+ const dateParseValue = value => {
256
+ let dValue = null
257
+ if (value) {
258
+ dValue = $vUtils.toStringDate(value, props.valueFormat)
259
+ }
260
+ if (dValue && !$vUtils.isValidDate(dValue)) {
261
+ dValue = null
262
+ }
263
+ reactData.panelValue = dValue
264
+ }
265
+ const getLunarDate = day => {
266
+ let lunarDate = Lunar.fromDate(day)
267
+ let lunarText = lunarDate.getDayInChinese()
268
+ const jq = lunarDate.getJieQi()
269
+ const solarFestivals = lunarDate.getFestivals()
270
+ if (jq) {
271
+ lunarText = jq
272
+ } else if (lunarDate.getDay() === 1) {
273
+ lunarText = lunarDate.getMonthInChinese() + '月'
274
+ } else if (solarFestivals.length > 0) {
275
+ const f = solarFestivals[0]
276
+ if (f.length < 4) {
277
+ lunarText = f
278
+ }
279
+ }
280
+ return lunarText
281
+ }
282
+ const getCellClass = item => {
283
+ const { panelValue } = reactData
284
+ const dateValue = computeDateValue.value
285
+ const matchFormat = 'yyyyMMdd'
286
+ const ymd = $vUtils.toDateString(item.date, matchFormat)
287
+ const lunarDate = Lunar.fromDate(item.date)
288
+ const holiday = HolidayUtil.getHoliday(ymd)
289
+ let rest = false
290
+ if ([0, 6].includes(lunarDate.getWeek())) {
291
+ rest = true
292
+ }
293
+ if (holiday) rest = !holiday.isWork()
294
+ return {
295
+ 'is--prev': item.isPrev,
296
+ 'is--current': item.isCurrent,
297
+ 'is--now': item.isNow,
298
+ 'is--next': item.isNext,
299
+ 'is--holiday': holiday,
300
+ 'is--rest': rest,
301
+ 'is--disabled': isDateDisabled(item),
302
+ 'is--selected': $vUtils.isDateSame(dateValue, item.date, matchFormat),
303
+ 'is--hover': $vUtils.isDateSame(panelValue, item.date, matchFormat)
304
+ }
305
+ }
306
+ const handleBtn = ({ code }) => {
307
+ try {
308
+ const { currentDate, selectMonth } = reactData
309
+ switch (code) {
310
+ case 'prev':
311
+ reactData.selectMonth = $vUtils.getWhatMonth(selectMonth, -1, 'first')
312
+ break
313
+ case 'next':
314
+ reactData.selectMonth = $vUtils.getWhatMonth(selectMonth, 1, 'first')
315
+ break
316
+ case 'current':
317
+ reactData.selectMonth = $vUtils.getWhatMonth(currentDate, 0, 'first')
318
+ break
319
+ default:
320
+ break
321
+ }
322
+ } catch (e) {
323
+ proxy.msgwarning(e.message)
324
+ }
325
+ }
326
+ const emitValue = (value, evnt) => {
327
+ reactData.inputValue = value
328
+ emit('update:modelValue', value)
329
+ }
330
+
331
+ // 初始化
332
+ const initValue = () => {
333
+ reactData.currentDate = $vUtils.getWhatDay(Date.now(), 0, 'first')
334
+ reactData.selectMonth = $vUtils.getWhatMonth(reactData.currentDate, 0, 'first')
335
+ }
336
+
337
+ onBeforeMount(() => {
338
+ initValue()
339
+ })
340
+
341
+ watch(
342
+ () => props.modelValue,
343
+ val => {
344
+ reactData.inputValue = val
345
+ }
346
+ )
347
+
348
+ return {
349
+ tableConfig,
350
+ headers,
351
+ dayDatas,
352
+ monthInfo,
353
+ dayInfo,
354
+ lunarInfo,
355
+ headerHandles,
356
+ getLunarDate,
357
+ getCellClass,
358
+ handleBtn,
359
+ dateSelectEvent,
360
+ dateMouseenterEvent,
361
+ dateMouseleaveEvent
362
+ }
363
+ }
364
+ })
365
+ </script>
366
+
367
+ <style scoped lang="scss">
368
+ .sh-calendar {
369
+ overflow: auto;
370
+ .sh-calendar-title {
371
+ font-size: 18px;
372
+ font-weight: bold;
373
+ }
374
+ .sh-calendar-span {
375
+ margin-right: 5px;
376
+ }
377
+ .sh-calendar-tag {
378
+ border-radius: 30px;
379
+ padding: 5px;
380
+ display: inline-flex;
381
+ vertical-align: top;
382
+ line-height: 1;
383
+ margin-right: 10px;
384
+ &.yi {
385
+ background-color: var(--vxe-success-color);
386
+ color: #fff;
387
+ }
388
+ &.ji {
389
+ background-color: var(--vxe-danger-color);
390
+ color: #fff;
391
+ }
392
+ }
393
+ .sh-calendar-row {
394
+ display: flex;
395
+ justify-content: space-between;
396
+ align-items: center;
397
+ .info {
398
+ flex: 1;
399
+ &.right {
400
+ text-align: right;
401
+ }
402
+ }
403
+ .extra {
404
+ display: inline-flex;
405
+ flex-wrap: nowrap;
406
+ }
407
+ & + .sh-calendar-row {
408
+ margin-top: 5px;
409
+ }
410
+ }
411
+ .sh-calendar-head,
412
+ .sh-calendar-foot {
413
+ padding: 8px;
414
+ border: 1px solid var(--vxe-table-border-color);
415
+ }
416
+ .sh-calendar-head {
417
+ border-bottom: none;
418
+ line-height: 1;
419
+ }
420
+ .sh-calendar-foot {
421
+ border-top: none;
422
+ }
423
+ .sh-calendar-btn {
424
+ padding: 5px;
425
+ border-radius: var(--vxe-border-radius);
426
+ border: 1px solid var(--vxe-table-border-color);
427
+ margin-left: 5px;
428
+ &:hover {
429
+ color: var(--vxe-primary-color);
430
+ }
431
+ }
432
+ .sh-calendar-cell {
433
+ display: block;
434
+ &-head {
435
+ padding: 3px 5px;
436
+ & + .sh-calendar-cell-foot {
437
+ padding-top: 0;
438
+ }
439
+ }
440
+ &-body {
441
+ overflow: auto;
442
+ }
443
+ &-foot {
444
+ padding: 3px 5px;
445
+ font-size: 0.8em;
446
+ }
447
+ }
448
+ table {
449
+ border: 0;
450
+ width: 100%;
451
+ border-spacing: 0;
452
+ border-collapse: collapse;
453
+ table-layout: fixed;
454
+ height: 100%;
455
+ }
456
+ th,
457
+ td {
458
+ font-weight: normal;
459
+ position: relative;
460
+ border: 1px solid var(--vxe-table-border-color);
461
+ height: 36px;
462
+ }
463
+ td {
464
+ &.is--prev,
465
+ &.is--next {
466
+ color: var(--vxe-font-disabled-color);
467
+ }
468
+ //&.is--rest {
469
+ // .sh-calendar-cell-head {
470
+ // color: var(--vxe-danger-color);
471
+ // }
472
+ //}
473
+ &.is--now {
474
+ &:not(.is--selected) {
475
+ color: var(--vxe-primary-color);
476
+ &.is--current {
477
+ background-color: var(--primary-weak-color);
478
+ }
479
+ }
480
+ }
481
+ &.is--hover {
482
+ background-color: var(--vxe-input-date-picker-hover-background-color);
483
+ }
484
+ &.is--selected {
485
+ color: var(--vxe-input-date-picker-selected-color);
486
+ background-color: var(--vxe-primary-color);
487
+ &.is--prev,
488
+ &.is--next {
489
+ background-color: var(--vxe-primary-lighten-color);
490
+ }
491
+ }
492
+ &:not(.is--disabled) {
493
+ cursor: pointer;
494
+ }
495
+ &.is--disabled {
496
+ cursor: no-drop;
497
+ color: var(--vxe-input-disabled-color);
498
+ background-color: var(--vxe-input-disabled-background-color);
499
+ }
500
+ }
501
+ }
502
+ </style>
@@ -86,8 +86,8 @@ export default function (props, context, proxy, isGrid) {
86
86
  const tablePrevColumns = computed(() => {
87
87
  let prevColumns = []
88
88
  const { seq, selectType } = tableGlobalConfig.value
89
- if (seq) prevColumns.push(columnsMapDefault.seq)
90
89
  if (selectType) prevColumns.push(columnsMapDefault[selectType])
90
+ if (seq) prevColumns.push(columnsMapDefault.seq)
91
91
  return prevColumns
92
92
  })
93
93
  const tableColumns = computed(() => {
@@ -1,6 +1,7 @@
1
1
  // 全局公共封装组件
2
2
  import ShAlert from './global-components/sh-alert/index.vue'
3
3
  import ShBadge from './global-components/sh-badge/index.vue'
4
+ import ShCalendar from './global-components/sh-calendar/index.vue'
4
5
  import ShCard from './global-components/sh-card/index.vue'
5
6
  import ShCodeEditor from './global-components/sh-code-editor/index.vue'
6
7
  import ShCol from './global-components/sh-col/index.vue'
@@ -37,6 +38,7 @@ import { VxeButton, VxeInput, VxeTextarea, VxeSelect } from 'vxe-table'
37
38
  const components = {
38
39
  ShAlert,
39
40
  ShBadge,
41
+ ShCalendar,
40
42
  ShCard,
41
43
  ShCodeEditor,
42
44
  ShCol,