Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions examples/sites/demos/apis/calendar-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,20 @@ export default {
mode: ['pc', 'mobile-first'],
pcDemo: 'basic-usage',
mfDemo: 'basic-usage'
},
{
name: 'show-back-today',
type: 'boolean',
defaultValue: 'true',
desc: {
'zh-CN': '是否展示左上侧按钮显示,默认展示',
'en-US': 'Should the upper left button be displayed, Default Display'
},
meta: {
stable: '3.22.0'
},
mode: ['mobile-first'],
mfDemo: 'calendar-mode'
}
],
events: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<template>
<tiny-calendar-view :events="eventslist" :year="2023" :month="6" :modes="['month', 'timeline', 'schedule']">
<tiny-calendar-view
:show-back-today="false"
:events="eventslist"
:year="2023"
:month="6"
:modes="['month', 'timeline', 'schedule']"
>
</tiny-calendar-view>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export default {
},
desc: {
'zh-CN':
'<p>通过 <code>mode</code> 属性指定以年的形式显示,将展示当年的每个月份。可选值有 <code>month</code> / <code>timeline</code> / <code>schedule</code>。</p>\n',
'<p>通过 <code>mode</code> 属性指定以年的形式显示,将展示当年的每个月份。可选值有 <code>month</code> / <code>timeline</code> / <code>schedule</code>。通过<code>show-back-today</code> 属性控制左侧按钮显示。</p>\n',
'en-US':
'<p>The <code>mode</code> attribute specifies that each month of the current year is displayed. The options are <code>month</code> / <code>timeline</code> / <code>schedule</code>. </p>\n'
'<p>The <code>mode</code> attribute specifies that each month of the current year is displayed. The options are <code>month</code> / <code>timeline</code> / <code>schedule</code>. Control the display of the left button through the<code>show back today</code>attribute.</p>\n'
},
codeFiles: ['calendar-mode.vue']
},
Expand Down
83 changes: 69 additions & 14 deletions packages/renderless/src/calendar-view/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,31 @@ export const parseDate = (time) => {
} else {
date = new Date()
}

return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds()
// 识别无时分秒的日期时间
const timeParts = hasNoTime(time)
let timesPartsOne = {}
let timesPartsTwo = {}
if (!timeParts.hours) {
timesPartsOne = {
year: timeParts.year,
month: timeParts.month,
day: timeParts.day,
hours: 0,
minutes: 0,
seconds: 0
}
} else {
timesPartsTwo = {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds()
}
}
const timePartsList = Object.assign(timesPartsOne, timesPartsTwo)
return timePartsList
}

export const computedCalendar =
Expand Down Expand Up @@ -160,6 +176,36 @@ const getCalendarItem = function (item, props, isFunction, type, isNext, isLast)
return res
}

const hasNoTime = (date) => {
const datetimeStr = date
let hoursTime = 0
let minutesTime = 0
let secondsTime = 0
const [datePart, timePart] = datetimeStr.split(' ')
const [year, month, day] = datePart && datePart.split('-')
if (timePart) {
const [hours, minutes, seconds] = timePart && timePart.split(':')
hoursTime = hours
minutesTime = minutes
secondsTime = seconds
}
// 提取时间
return {
year: Number(year),
month: Number(month),
day: Number(day),
hours: hoursTime,
minutes: minutesTime,
seconds: secondsTime
}
}
Comment on lines +179 to +201
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation and type safety to hasNoTime function.

The function needs better error handling and type safety:

  1. Missing input validation
  2. Potential null/undefined issues with split operations
  3. No TypeScript type definitions

Consider this safer implementation:

-const hasNoTime = (date) => {
+const hasNoTime = (date: string): DateTimeParts => {
+  if (!date || typeof date !== 'string') {
+    throw new Error('Invalid date string provided');
+  }
+
   const datetimeStr = date
   let hoursTime = 0
   let minutesTime = 0
   let secondsTime = 0
-  const [datePart, timePart] = datetimeStr.split(' ')
+  const [datePart = '', timePart] = datetimeStr.split(' ')
-  const [year, month, day] = datePart && datePart.split('-')
+  const [year = '0', month = '0', day = '0'] = datePart?.split('-') ?? []
   if (timePart) {
-    const [hours, minutes, seconds] = timePart && timePart.split(':')
+    const [hours = '0', minutes = '0', seconds = '0'] = timePart?.split(':') ?? []
     hoursTime = hours
     minutesTime = minutes
     secondsTime = seconds
   }
   return {
     year: Number(year),
     month: Number(month),
     day: Number(day),
     hours: hoursTime,
     minutes: minutesTime,
     seconds: secondsTime
   }
}

+interface DateTimeParts {
+  year: number;
+  month: number;
+  day: number;
+  hours: number;
+  minutes: number;
+  seconds: number;
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const hasNoTime = (date) => {
const datetimeStr = date
let hoursTime = 0
let minutesTime = 0
let secondsTime = 0
const [datePart, timePart] = datetimeStr.split(' ')
const [year, month, day] = datePart && datePart.split('-')
if (timePart) {
const [hours, minutes, seconds] = timePart && timePart.split(':')
hoursTime = hours
minutesTime = minutes
secondsTime = seconds
}
// 提取时间
return {
year: Number(year),
month: Number(month),
day: Number(day),
hours: hoursTime,
minutes: minutesTime,
seconds: secondsTime
}
}
const hasNoTime = (date: string): DateTimeParts => {
if (!date || typeof date !== 'string') {
throw new Error('Invalid date string provided');
}
const datetimeStr = date
let hoursTime = 0
let minutesTime = 0
let secondsTime = 0
const [datePart = '', timePart] = datetimeStr.split(' ')
const [year = '0', month = '0', day = '0'] = datePart?.split('-') ?? []
if (timePart) {
const [hours = '0', minutes = '0', seconds = '0'] = timePart?.split(':') ?? []
hoursTime = hours
minutesTime = minutes
secondsTime = seconds
}
// 提取时间
return {
year: Number(year),
month: Number(month),
day: Number(day),
hours: hoursTime,
minutes: minutesTime,
seconds: secondsTime
}
}
interface DateTimeParts {
year: number;
month: number;
day: number;
hours: number;
minutes: number;
seconds: number;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 185-187: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 187-188: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

// 时间转GMT8
const timesToGMT8 = (date) => {
const originalDate = new Date(date)
const gmt8 = new Date(originalDate.getTime() + 15 * 60 * 60 * 1000)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conversion to GMT+8 seems incorrect. The offset should be 8 hours, not 15. Please verify the logic for time zone conversion.

return gmt8
}
Comment on lines +203 to +207
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve timezone handling in timesToGMT8 function.

The function has several issues:

  1. Hardcoded magic number for hour offset
  2. No type definitions
  3. Potential timezone conversion issues

Consider this improved implementation:

-const timesToGMT8 = (date) => {
+const timesToGMT8 = (date: string | number | Date): Date => {
+  const GMT_8_OFFSET = 8; // Hours
+  const HOURS_TO_MS = 60 * 60 * 1000;
+
   const originalDate = new Date(date)
-  const gmt8 = new Date(originalDate.getTime() + 15 * 60 * 60 * 1000)
+  const utcOffset = originalDate.getTimezoneOffset() / 60;
+  const offsetHours = GMT_8_OFFSET + utcOffset;
+  const gmt8 = new Date(originalDate.getTime() + offsetHours * HOURS_TO_MS)
   return gmt8
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const timesToGMT8 = (date) => {
const originalDate = new Date(date)
const gmt8 = new Date(originalDate.getTime() + 15 * 60 * 60 * 1000)
return gmt8
}
const timesToGMT8 = (date: string | number | Date): Date => {
const GMT_8_OFFSET = 8; // Hours
const HOURS_TO_MS = 60 * 60 * 1000;
const originalDate = new Date(date)
const utcOffset = originalDate.getTimezoneOffset() / 60;
const offsetHours = GMT_8_OFFSET + utcOffset;
const gmt8 = new Date(originalDate.getTime() + offsetHours * HOURS_TO_MS)
return gmt8
}


export const handleEvents =
({ props, state }) =>
() => {
Expand Down Expand Up @@ -197,14 +243,23 @@ export const handleEvents =
([lastYear, +state.activeYear, nextYear].includes(endYear) &&
[lastMon, +state.activeMonth, nextMon].includes(endMonth))
) {
item.start = getTime(item.start)
item.end = getTime(item.end)
item.startTime = makeUpZero(startHours) + ':' + makeUpZero(startMinutes) + ':' + makeUpZero(startSeconds)
item.endTime = makeUpZero(endHours) + ':' + makeUpZero(endMinutes) + ':' + makeUpZero(endSeconds)
const timeStartPart = hasNoTime(item.start)
const timeEndPart = hasNoTime(item.end)

item.start = timeStartPart.hours ? getTime(item.start) : timesToGMT8(item.start)
item.end = timeEndPart.hours ? getTime(item.end) : timesToGMT8(item.end)

item.startTime = timeStartPart.hours
? makeUpZero(startHours) + ':' + makeUpZero(startMinutes) + ':' + makeUpZero(startSeconds)
: ''
item.endTime = timeEndPart.hours
? makeUpZero(endHours) + ':' + makeUpZero(endMinutes) + ':' + makeUpZero(endSeconds)
: ''

item.startDay = startYear + '-' + startMonth + '-' + startDay
item.endDay = endYear + '-' + endMonth + '-' + endDay
const startTimestamp = getTime(startYear + '-' + startMonth + '-' + startDay)
const endTimestamp = getTime(endYear + '-' + endMonth + '-' + endDay)
const startTimestamp = getTime(item.startDay)
const endTimestamp = getTime(item.endDay)
const days = Math.abs(endTimestamp - startTimestamp) / dayMillisecond
item.dayNumber = days >= 1 ? days + 1 : 1

Expand Down
4 changes: 4 additions & 0 deletions packages/vue/src/calendar-view/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export const calendarViewProps = {
multiSelect: {
type: Boolean,
default: false
},
showBackToday: {
type: Boolean,
default: true
}
}

Expand Down
9 changes: 5 additions & 4 deletions packages/vue/src/calendar-view/src/mobile-first.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
</template>
</tiny-tooltip>
<div data-tag="tiny-calendar-view-today" class="flex justify-around items-center mb-3">
<tiny-button @click="toToday">{{ t('ui.calendarView.backToday') }}</tiny-button>
<tiny-button v-if="showBackToday" @click="toToday">{{ t('ui.calendarView.backToday') }}</tiny-button>
<tiny-date-picker
v-model="state.currentDate"
class="ml-5 shrink-0"
:class="[showBackToday ? 'ml-5' : '', 'shrink-0']"
shape="filter"
type="month"
:clearable="false"
Expand Down Expand Up @@ -292,7 +292,7 @@
:key="idx"
class="py-1.5 h-auto border border-color-border-separator rounded mb-2 shadow-sm"
>
<div class="px-1.5 mb-1.5 border-l-2 border-color-brand">{{ event.title }}</div>
<div class="px-1.5 mb-1.5 border-l-2 border-color-brand break-all">{{ event.title }}</div>
<div class="mb-1.5 px-2 text-color-text-placeholder">
{{ getEventShowTime('start', event, date.value) }} - {{ getEventShowTime('end', event, date.value) }}
</div>
Expand Down Expand Up @@ -376,7 +376,8 @@ export default defineComponent({
'events',
'height',
'mark-color',
'multi-select'
'multi-select',
'showBackToday'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Define prop type and default value for showBackToday.

The prop is added without type checking or a default value, which could lead to runtime issues.

Add type definition and default value:

-    'showBackToday'
+    {
+      name: 'showBackToday',
+      type: Boolean,
+      default: true
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'showBackToday'
{
name: 'showBackToday',
type: Boolean,
default: true
}

],
setup(props, context) {
return setup({
Expand Down
Loading