Skip to content

Commit

Permalink
feat: 重构useToNow实现
Browse files Browse the repository at this point in the history
  • Loading branch information
bagolo6911 committed Jan 10, 2024
1 parent 60328ce commit c8c9574
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 103 deletions.
1 change: 1 addition & 0 deletions src/boot/app.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '../global'
import { boot } from 'quasar/wrappers'

let app = null
Expand Down
10 changes: 2 additions & 8 deletions src/components/BookCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

<script lang="ts" setup>
import { computed, ref } from 'vue'
import { useToNow } from 'src/composition/useToNow'
import { useToNowRef } from 'src/composition/useToNowRef'
import { BookInList } from 'src/services/book/types'
import { useQuasar } from 'quasar'
import BlurHash from 'src/components/BlurHash.vue'
Expand All @@ -57,13 +57,7 @@ const { generalSetting } = settingStore // 引入setting用于控制图片自定
const $q = useQuasar()
const props = defineProps<{ book: BookInList }>()
const cover = computed(() => props.book.Cover)
const updateTime = computed(() => {
if (+props.book.LastUpdateTime <= 0) {
return ''
}
return useToNow(computed(() => props.book.LastUpdateTime)).value
})
const updateTime = useToNowRef(() => props.book.LastUpdateTime)
const visible = ref(false)
function onIntersection(entry: IntersectionObserverEntry) {
visible.value = entry.isIntersecting
Expand Down
5 changes: 2 additions & 3 deletions src/components/Comment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
</q-item-label>
<q-item-label caption>
<div class="row flex-align-center q-gutter-x-md">
<div>{{ toNow(comment.Commentaries[`${item.Id}`].CreatedTime, baseTime) }}</div>
<div>{{ toNow(comment.Commentaries[`${item.Id}`].CreatedTime) }}</div>
<div>
<q-btn flat dense @click="showReply(item.Id)">回复</q-btn>
<q-btn flat dense v-if="comment.Commentaries[`${item.Id}`].CanEdit" @click="_delete(item.Id)">
Expand Down Expand Up @@ -108,7 +108,7 @@
</q-item-label>
<q-item-label caption>
<div class="row flex-align-center q-gutter-x-md">
<div>{{ toNow(comment.Commentaries[`${replyId}`].CreatedTime, baseTime) }}</div>
<div>{{ toNow(comment.Commentaries[`${replyId}`].CreatedTime) }}</div>
<div>
<q-btn flat dense @click="showReply(item.Id, replyId)">回复</q-btn>
<q-btn
Expand Down Expand Up @@ -191,7 +191,6 @@
<script lang="ts" setup>
import { postComment, replyComment, getComment, deleteComment } from 'src/services/comment'
import { CommentType, GetComment } from 'src/services/comment/types'
import { baseTime } from 'src/composition/useToNow'
import { toNow } from 'src/utils/time'
import { useAppStore } from 'stores/app'
import { computed, ref, watch } from 'vue'
Expand Down
36 changes: 0 additions & 36 deletions src/composition/useTickSource.ts

This file was deleted.

39 changes: 0 additions & 39 deletions src/composition/useToNow.ts

This file was deleted.

81 changes: 81 additions & 0 deletions src/composition/useToNowRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import dayjs, { Dayjs } from 'dayjs'
import { type MaybeRefOrGetter, toValue } from 'vue'
import { parseTime, toNow } from 'src/utils/time'

/**
* 返回一个定时刷新的 'xx天前' 文案
*
* @example
* ```ts
* const book = ref<{ LastUpdateTime: Date }>({ LastUpdateTime: new Date() })
* onMounted(async () => {
* Promise.resolve().then(() => {
* book.value.LastUpdateTime = new Date()
* })
* })
*
* const lastUpdateTimeSourceRef = computed(() => book.value.LastUpdateTime)
* const lastUpdateTime = useToNow(lastUpdateTimeSourceRef)
*
* // 这样合起来写也行↓
* // const lastUpdateTime = useToNow(() => book.value.LastUpdateTime)
*
* return { lastUpdateTime }
* ```
*/
export function useToNowRef(dateGetter: MaybeRefOrGetter<Date | Dayjs | undefined | null>): ComputedRef<string> {
const dateRef = computed<Dayjs | null>(() => {
const dateVal = toValue(dateGetter)
if (!dateVal) {
return null
}

return parseTime(dateVal)
})

const nowRef = shallowRef(dayjs())
// 刷新nowRef
watchEffect((onClean) => {
const date = unref(dateRef)
const now = unref(nowRef)

// 不是同一天的就不更新了
if (!date || !date.isSame(now, 'day')) {
return
}

// 秒级别的差异,每半分钟刷新一次
// => "x秒前"
if (date.diff(now, 'second') < 60) {
const timeout = setTimeout(() => {
nowRef.value = dayjs()
}, 1_000 * 1)

onClean(() => clearTimeout(timeout))
return
}

// 分钟级别的差异,每分钟刷新一次
// => "x分钟前"
if (date.diff(now, 'minute') < 60) {
const timeout = setTimeout(() => {
nowRef.value = dayjs()
}, 1_000 * 60)
onClean(() => clearTimeout(timeout))
return
}

// 小时级别的差异,每半小时刷新一次
// => "x小时前"
const timeout = setTimeout(() => {
nowRef.value = dayjs()
}, 1_000 * 60 * 60)
onClean(() => clearTimeout(timeout))
return
})

return computed(() => {
// console.log('re-calc toNow', dateRef.value.format(), nowRef.value.format())
return dateRef.value ? toNow(dateRef.value, { now: nowRef.value }) : null
})
}
14 changes: 14 additions & 0 deletions src/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 全局初始化内容
import dayjs from 'dayjs'
import zh from 'dayjs/locale/zh'

import relativeTime from 'dayjs/plugin/relativeTime'
import updateLocale from 'dayjs/plugin/updateLocale'
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'

dayjs.extend(relativeTime)
dayjs.extend(isSameOrAfter)
dayjs.extend(updateLocale)

dayjs.locale(zh)
dayjs.updateLocale(zh.name, { relativeTime: { ...zh.relativeTime, s: '%d秒' } })
1 change: 1 addition & 0 deletions src/services/book/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface BookInList {
Id: number
Cover: string
Placeholder?: string
// TODO: 走了二进制解码后自动转Date对象的特性丢失了,就是一个ISO 8601的日期
LastUpdateTime: Date
UserName: string
Title: string
Expand Down
26 changes: 17 additions & 9 deletions src/utils/time.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
import dayjs, { Dayjs } from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
dayjs.extend(relativeTime)

/**
* 解析时间
*
* @param date 接受js时间对象、ISO字符串、luxon对象
* @param date 接受js时间对象、ISO字符串、dayjs对象
*/
export function parseTime(date: Date | Dayjs | string): Dayjs {
// 字符串格式的时间戳会parse成错误的时间,但目前没有这种场景,先注释,省点
// if (typeof date === 'string' && date === (+date).toString()) {
// date = +date
// }

return dayjs(date)
}

/** 获取时间相对目前的文案描述 */
/**
* 获取时间相对目前的文案描述
*
* @url https://day.js.org/docs/en/display/from-now#list-of-breakdown-range
*/
export function toNow(
date: Date | Dayjs,
config: {
base?: Dayjs
locale?: string
now?: Dayjs
notNegative?: boolean
} = {
notNegative: true
}
): string {
const { base, locale, notNegative } = config
if (notNegative && parseTime(date).isAfter(dayjs())) {
const { now = dayjs(), notNegative } = config
const dateObj = parseTime(date)

if (notNegative && dateObj.isSameOrAfter(now, 'second')) {
return '刚刚'
}

return parseTime(date).to(base)
return now.to(dateObj)
}
6 changes: 3 additions & 3 deletions src/views/Announcement/announcementFormat.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useToNow } from 'src/composition/useToNow'
import { computed, Ref } from 'vue'
import { useToNowRef } from 'src/composition/useToNowRef'
import { Ref } from 'vue'
import sanitizerHtml from 'src/utils/sanitizeHtml'
import { Dayjs } from 'dayjs'
import { parseTime } from 'src/utils/time'
Expand All @@ -25,7 +25,7 @@ export function announcementFormat(element): Announcement {
return {
Id: element.Id,
Create: parseTime(element.CreateTime),
Before: useToNow(computed(() => element.CreateTime)),
Before: useToNowRef(() => element.CreateTime),
PreviewContent: getPreview(element.Content),
Content: element.Content,
Title: element.Title
Expand Down
4 changes: 2 additions & 2 deletions src/views/Book/BookInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ import sanitizerHtml from 'src/utils/sanitizeHtml'
import { useRouter } from 'vue-router'
import { Comment } from 'src/components/'
import { getBookInfo } from 'src/services/book'
import { useToNow } from 'src/composition/useToNow'
import { useToNowRef } from 'src/composition/useToNowRef'
import { QGrid, QGridItem } from 'src/components/grid'
import { loadHistory } from 'src/views/Book/Read/history'
import { useInitRequest } from 'src/composition/biz/useInitRequest'
Expand Down Expand Up @@ -195,7 +195,7 @@ const bookInList = computed<BookInList | null>(() =>
} as BookInList)
: null
)
const LastUpdateTimeDesc = useToNow(computed(() => book.value?.LastUpdateTime))
const LastUpdateTimeDesc = useToNowRef(() => book.value?.LastUpdateTime)
const lastReadTitle = computed(() => {
if (position && position.value?.cid) {
let chap = bookInfo.value?.Book?.Chapter?.find((x) => x.Id === position.value.cid)
Expand Down
2 changes: 1 addition & 1 deletion src/views/Book/BookList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const { generalSetting } = settingStore
const request = useTimeoutFn(function (page = currentPage.value, order = props.order) {
return getBookList({ Page: page, Order: order, Size: 24, IgnoreJapanese: generalSetting.ignoreJapanese }).then(
(serverData) => {
bookData.value = serverData.Data
bookData.value = serverData.Data.map((s): typeof s => ({ ...s, LastUpdateTime: new Date() }))
pageData.value.totalPage = serverData.TotalPages
}
)
Expand Down
4 changes: 2 additions & 2 deletions src/views/MyShelf/components/ShelfFolder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

<script lang="ts" setup>
import { computed } from 'vue'
import { useToNow } from 'src/composition/useToNow'
import { useToNowRef } from 'src/composition/useToNowRef'
import { ShelfBookItem, ShelfFolderItem, ShelfItemTypeEnum } from 'src/types/shelf'
import { useShelfStore } from 'stores/shelf'
import { useBookListStore } from 'stores/bookListData'
Expand All @@ -52,7 +52,7 @@ const props = defineProps<{ item: ShelfFolderItem }>()
const shelfStore = useShelfStore()
const settingStore = useSettingStore()
const { generalSetting } = settingStore
const updateTime = useToNow(computed(() => new Date(props.item.updateAt)))
const updateTime = useToNowRef(() => new Date(props.item.updateAt))
const folderIDs = computed(() => [...props.item.parents, props.item.id])
const listDataStore = useBookListStore()
// 限制最多四本书
Expand Down

0 comments on commit c8c9574

Please sign in to comment.