From fa74612c99459a8b4e94121d2d3bfcc42915208b Mon Sep 17 00:00:00 2001
From: tj <1378534974@qq.com>
Date: 星期二, 27 五月 2025 16:08:20 +0800
Subject: [PATCH] loading,wechatLogin
---
pages/home/home.vue | 67 +++++
pages/login/login.vue | 57 +++--
pages.json | 4
plugins/http.js | 8
App.vue | 8
store/index.js | 229 ----------------------
utils/time.ts | 29 ++
types/index.ts | 21 +
store/index.ts | 69 ++++++
manifest.json | 4
main.js | 4
components/tabbar/top-tab-bar.vue | 12
store/index copy.js | 2
store/user.ts | 86 ++++++++
14 files changed, 318 insertions(+), 282 deletions(-)
diff --git a/App.vue b/App.vue
index fa4780f..c6ce853 100644
--- a/App.vue
+++ b/App.vue
@@ -1,7 +1,12 @@
<script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
-
+import { useUserStore } from '@/store/user'
+const userStore = useUserStore()
onLaunch(async (options: any) => {
+
+ // 初始化用户状态
+ userStore.initLoginState()
+
const query = options.q ? decodeURIComponent(options.q) : ''
const querydto: Record<string, string> = {}
@@ -37,7 +42,6 @@
uni.getSystemSetting({
success: (e: any) => {
- debugger;
try {
const custom = uni.getMenuButtonBoundingClientRect()
uni.setStorageSync('StatusBar', e.statusBarHeight)
diff --git a/components/tabbar/top-tab-bar.vue b/components/tabbar/top-tab-bar.vue
index 0ba089b..82f73e1 100644
--- a/components/tabbar/top-tab-bar.vue
+++ b/components/tabbar/top-tab-bar.vue
@@ -21,7 +21,7 @@
<!-- 右侧按钮 -->
<view class="right">
- <view class="login-view" @click="goLogin">
+ <view class="login-view" @click="goLogin" v-if="!isLoggedIn">
<up-icon name="/static/images/tabbar/user.png" size="30rpx" />
<text class="login-text">登录</text>
</view>
@@ -33,10 +33,12 @@
</template>
<script setup lang="ts">
-import { ref, onMounted } from 'vue'
-
-const CustomBar = ref<number>(uni.getStorageSync('CustomBar') || 0)
-const StatusBar = ref<number>(uni.getStorageSync('StatusBar') || 0)
+import { ref, onMounted ,computed} from 'vue'
+import { useUserStore } from '@/store/user'
+const userStore = useUserStore()
+const isLoggedIn = computed(() => userStore.hasLogin)
+console.log("登录状态")
+console.log(isLoggedIn.value)
// 可选:自动获取系统信息进行替代
onMounted(() => {
diff --git a/main.js b/main.js
index d2d448c..226f769 100644
--- a/main.js
+++ b/main.js
@@ -4,7 +4,7 @@
import { createPinia } from 'pinia'
import message from './plugins/message'
import http from './plugins/http.js'
-import store from './store'
+// import store from './store/index.js'
// #ifndef VUE3
import Vue from 'vue'
@@ -53,7 +53,7 @@
// 全局属性
app.config.globalProperties.$message = message
app.config.globalProperties.$http = http
- app.config.globalProperties.$store = store
+ // app.config.globalProperties.$store = store
// uni.$u.setConfig({
// config: {
diff --git a/manifest.json b/manifest.json
index 54fb740..82d8aa6 100644
--- a/manifest.json
+++ b/manifest.json
@@ -50,8 +50,8 @@
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
- // "appid" : "wx1441324401626290",
- "appid" : "wxede6e3ad8e89693a",
+ "appid" : "wx1441324401626290",
+ // "appid" : "wxede6e3ad8e89693a",
"setting" : {
"urlCheck" : false
},
diff --git a/pages.json b/pages.json
index a092c37..ab98945 100644
--- a/pages.json
+++ b/pages.json
@@ -12,7 +12,9 @@
{
"path": "pages/home/home",
"style": {
- "navigationBarTitleText": "片场"
+ "navigationBarTitleText": "片场",
+ "enablePullDownRefresh": true,
+ "onReachBottomDistance": 50
}
},
{
diff --git a/pages/home/home.vue b/pages/home/home.vue
index a71e374..5288e11 100644
--- a/pages/home/home.vue
+++ b/pages/home/home.vue
@@ -43,7 +43,11 @@
<Community v-for="(item, index) in communitys" :key="index" :avatar="item.avatar" :nickname="item.nickname"
:time="formatRelativeTime(item.createTime)" :image="item.coverUrl" :content="item.coverAlt"
:likeCount="item.likeCount" :commentCount="item.commentCount" />
-
+ <view class="more">
+ <!-- <view v-if="loadingCommunity">加载中...</view>
+ <view v-if="noMoreCommunity">没有更多了</view> -->
+ <up-loadmore :status="communityStatus" />
+ </view>
<view style="height: 300rpx;"></view>
</view>
@@ -53,7 +57,7 @@
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
-import { onShow } from '@dcloudio/uni-app'
+import { onShow, onPullDownRefresh,onReachBottom } from '@dcloudio/uni-app'
import HomeMain from './home-main.vue'
import TripCard from './trip-card.vue'
@@ -67,6 +71,7 @@
import { FilmWorks } from '@/types/index'
import { formatRelativeTime } from '@/utils/time'
import { FilmWorksCategory } from '@/enums/dict'
+
// 主题
const theme = ref('light')
@@ -135,22 +140,68 @@
getCommunitys()
});
-async function getContentSelected() {
- tripCardList.value = await getFilmWorks(FilmWorksCategory.CONTENT_SELECTED, 20);
- console.log('内容精选', tripCardList.value);
+
+onPullDownRefresh(async () => {
+ console.log('用户下拉刷新了')
+ // 内容精选
+ getContentSelected()
+ // 光影社区
+ communityPage.value=1
+ getCommunitys()
+ uni.stopPullDownRefresh() // 停止下拉刷新动画
+})
+
+onReachBottom(()=>{
+ console.log('用户触底了')
+ getCommunitys()
+})
+
+const getContentSelected = async () => {
+ tripCardList.value = await getFilmWorks(FilmWorksCategory.CONTENT_SELECTED, 20,1);
}
-async function getCommunitys() {
- communitys.value = await getFilmWorks(FilmWorksCategory.COMMUNITY, 10);
+
+const communityPage = ref(1)
+const communitySize = 10
+const communityStatus = ref('loading')
+
+
+const getCommunitys = async () => {
+ if (communityStatus.value==='nomore') return
+
+ communityStatus.value = 'loading'
+
+ const records = await getFilmWorks(FilmWorksCategory.COMMUNITY, communitySize, communityPage.value)
+
+ if (records && records.length > 0) {
+ // 使用 Set 进行去重
+ const existingIds = new Set(communitys.value.map(item => item.id))
+ const uniqueRecords = records.filter(item => !existingIds.has(item.id))
+
+ communitys.value = [...communitys.value, ...uniqueRecords]
+
+ // 如果返回的记录数少于请求的 size,说明没有更多数据
+ if (records.length < communitySize) {
+ communityStatus.value = 'noMore'
+ }
+
+ communityPage.value++
+ } else {
+ communityStatus.value = 'noMore'
+ }
+}
+const getCommunitys_bak = async () => {
+ communitys.value = await getFilmWorks(FilmWorksCategory.COMMUNITY, 10,1);
}
// 内容精选
-const getFilmWorks = async (type: String, pageSize: Number) => {
+const getFilmWorks = async (type: String, pageSize: Number,currentPage: Number) => {
const {
code, data
} = await $http.request('get', '/api/filmWorks/list', {
params: {
classify: type,
size: pageSize,
+ current: currentPage
}
})
if (code == 0) {
diff --git a/pages/login/login.vue b/pages/login/login.vue
index 7434365..a926a9a 100644
--- a/pages/login/login.vue
+++ b/pages/login/login.vue
@@ -50,8 +50,11 @@
import { onShow } from '@dcloudio/uni-app'
import { useGlobal } from '@/composables/useGlobal'
import { usePlatformLoginType } from '@/composables/usePlatformLoginType'
+import { useUserStore } from '@/store/user'
+
const { apitype } = usePlatformLoginType()
-const { $http, $message,$store } = useGlobal()
+const { $http, $message, $store } = useGlobal()
+const userStore = useUserStore()
const isChecked = ref(false)
const toggleCheck = () => {
@@ -64,8 +67,29 @@
uni.showToast({ title: '请先同意协议', icon: 'none' });
return;
}
- // 微信登录逻辑
- uni.showToast({ title: '微信登录', icon: 'success' });
+ // 微信登录
+ uni.login({
+ "provider": "weixin",
+ "onlyAuthorize": true, // 微信登录仅请求授权认证
+ success: async function (event:any) {
+ const { code } = event
+ $message.showLoading();
+ const resp = await userStore.loginwx({ code, phoneNumber: wxUser.value.phoneNumber, purePhoneNumber: wxUser.value.purePhoneNumber })
+ if (resp && resp.data) {
+ // that.$forceUpdate()
+ uni.reLaunch({
+ url: '/pages/home/home'
+ })
+ }
+ $message.hideLoading();
+ },
+ fail: function (err:any) {
+ // 登录授权失败
+ // err.code是错误码
+ }
+ })
+
+
};
onShow(() => {
@@ -77,13 +101,8 @@
"provider": "weixin",
"onlyAuthorize": true, // 微信登录仅请求授权认证
success: async function (event: any) {
- console.log("aaaa")
- console.log(event)
const { code } = event
let openIdExistFlag = await getExistUserByOpenId(code);
- console.log(openIdExistFlag)
- console.log(wxUser.value)
-
},
fail: function (err: any) {
// 登录授权失败
@@ -101,8 +120,6 @@
}
})
if (code == 0) {
- console.log("查看当前用户是否已经绑定过")
- console.log(data)
wxUser.value = data
if (wxUser && wxUser.user) {
return true
@@ -113,16 +130,13 @@
}
}
-const handleGetPhoneNumber = async (e:any) => {
+const handleGetPhoneNumber = async (e: any) => {
+
if (!isChecked.value) {
$message.showToast('请同意用户协议')
return
}
- debugger;
- console.log(e)
- console.log(e.detail.code) // 动态令牌
- console.log(e.detail.errMsg) // 回调信息(成功失败都会返回)
- console.log(e.detail.errno) // 错误码(失败时返回)
+
if (e.detail.errMsg == 'getPhoneNumber:ok') {
console.log('获取成功')
const {
@@ -134,13 +148,13 @@
}
})
if (code == 0) {
+ debugger;
// 获取手机号码后,实现微信登录
- console.log(data)
const phoneNumber = data.phone_info.phoneNumber;
const purePhoneNumber = data.phone_info.purePhoneNumber;
wxUser.value.phoneNumber = phoneNumber
wxUser.value.purePhoneNumber = purePhoneNumber
- // that.handleWechatClick()
+ handleWechatClick()
} else {
}
@@ -153,10 +167,11 @@
uni.login({
"provider": "weixin",
"onlyAuthorize": true, // 微信登录仅请求授权认证
- success: async function (event) {
+ success: async function (event: any) {
const { code } = event
$message.showLoading();
- const resp = await $store.dispatch('loginwx', { code, phoneNumber: wxUser.phoneNumber, purePhoneNumber: wxUser.purePhoneNumber })
+ console.log("获取到的微信用户信息是:", wxUser.value)
+ const resp = await userStore.loginwx({ code, phoneNumber: wxUser.value.phoneNumber, purePhoneNumber: wxUser.value.purePhoneNumber })
if (resp && resp.data) {
// $forceUpdate()
uni.reLaunch({
@@ -165,7 +180,7 @@
}
$message.hideLoading();
},
- fail: function (err) {
+ fail: function (err: any) {
// 登录授权失败
// err.code是错误码
}
diff --git a/plugins/http.js b/plugins/http.js
index 412254e..9d895af 100644
--- a/plugins/http.js
+++ b/plugins/http.js
@@ -1,7 +1,7 @@
import environments from '@/environments'
import message from './message'
import storage from './storage'
-import store from '../store'
+// import store from '../store'
import utils from './util.js'
let pre = 'api'
@@ -107,7 +107,8 @@
console.log('resp', res)
// storage.removeItem('token')
// await store.dispatch('logout')
- store.commit('updateLogin', false)
+ // TODO
+ // store.commit('updateLogin', false)
await message.showToast('登录信息失效')
@@ -152,7 +153,8 @@
console.log('401', res)
// storage.removeItem('token')
// await store.dispatch('logout')
- store.commit('updateLogin', false)
+ // TODO
+ // store.commit('updateLogin', false)
await message.showToast('登录信息失效')
diff --git a/store/index copy.js b/store/index copy.js
index 0cb7d8c..9ef1829 100644
--- a/store/index copy.js
+++ b/store/index copy.js
@@ -1,4 +1,4 @@
-import http from '../plugins/http'
+import http from '../plugins/http.js'
import storage from '../plugins/storage.js'
import message from '../plugins/message.js'
import Vue from 'vue'
diff --git a/store/index.js b/store/index.js
index 42843e1..e69de29 100644
--- a/store/index.js
+++ b/store/index.js
@@ -1,229 +0,0 @@
-// store/index.js
-import { createStore } from 'vuex'
-import http from '../plugins/http'
-import storage from '../plugins/storage.js'
-import message from '../plugins/message.js'
-
-const store = createStore({
- state() {
- return {
- hasLogin: false,
- isUniverifyLogin: false,
- loginProvider: '',
- openid: null,
- testvuex: false,
- colorIndex: 0,
- colorList: ['#FF0000', '#00FF00', '#0000FF'],
- noMatchLeftWindow: true,
- active: 'componentPage',
- leftWinActive: '/pages/component/view/view',
- activeOpen: '',
- menu: [],
- appMenu: [],
- univerifyErrorMsg: '',
- currentInfo: {},
- cache_address: {},
- sign: {
- enterprise: 0,
- info: 0,
- flower: 0,
- shopping: 0,
- follow: 0,
- delivery: 0,
- order: 0,
- shopnum: 0,
- coupon: 0,
- cache_topay: 0,
- },
- cache: {
- coupon: {},
- goods: [],
- cache_coupon_select_cancel: 0,
- },
- defaultaddress: {},
- addressDesc: '',
- }
- },
- mutations: {
- updateLogin(state, provider) {
- state.hasLogin = !!provider
- if (!state.hasLogin) {
- state.currentInfo = {}
- storage.removeItem('token')
- }
- },
- login(state, provider) {
- state.hasLogin = true
- state.loginProvider = provider
- },
- logout(state) {
- state.hasLogin = false
- state.openid = null
- state.currentInfo = {}
- state.appMenu = []
- storage.removeItem('token')
- storage.removeItem('appMenu')
- message.showToast('退出登录成功')
- },
- setOpenid(state, openid) {
- state.openid = openid
- },
- setDefaultAddress(state, defaultaddress) {
- state.defaultaddress = defaultaddress
- },
- setAddressDesc(state, addressDesc) {
- state.addressDesc = addressDesc
- storage.setItem('defaultaddress', addressDesc || '')
- },
- setTestTrue(state) {
- state.testvuex = true
- },
- setTestFalse(state) {
- state.testvuex = false
- },
- setColorIndex(state, index) {
- state.colorIndex = index
- },
- setActive(state, tabPage) {
- state.active = tabPage
- },
- setActiveOpen(state, activeOpen) {
- state.activeOpen = activeOpen
- },
- setMenu(state, menu) {
- state.menu = menu
- },
- setUniverifyLogin(state, payload) {
- state.isUniverifyLogin = !!payload
- },
- setUniverifyErrorMsg(state, payload = '') {
- state.univerifyErrorMsg = payload
- }
- },
- getters: {
- currentColor(state) {
- return state.colorList[state.colorIndex]
- }
- },
- actions: {
- async sign_add({ state }, key) {
- state.sign[key] = 1
- },
- async sign_clear({ state }, key) {
- state.sign[key] = 0
- },
- async cache_coupon_select({ state }, dto) {
- state.cache.coupon = dto || {}
- },
- async cache_coupon_select_cancel({ state }, val) {
- state.cache.cache_coupon_select_cancel = val || 0
- },
- async cache_goods_select({ state }, goods) {
- state.cache.goods = goods || []
- },
- async logout({ commit }) {
- commit('logout')
- },
- async getUserOpenId({ state, commit }) {
- if (state.openid) return state.openid
- return new Promise((resolve, reject) => {
- uni.login({
- success(data) {
- commit('login')
- setTimeout(() => {
- const openid = '123456789'
- commit('setOpenid', openid)
- resolve(openid)
- }, 1000)
- },
- fail(err) {
- reject(err)
- }
- })
- })
- },
- async getCurrentInfo({ commit, state }) {
- const currentInfo = await http.request('get', '/api/current/user', {})
- if (currentInfo && currentInfo.code === 0) {
- state.currentInfo = currentInfo.data || {}
- state.type = currentInfo.data.type || ''
- state.spacecode = currentInfo.data.spacecode || ''
- commit('updateLogin', true)
- } else {
- commit('updateLogin', false)
- }
- },
- async getSwitchSubAccount({ commit, state }, payload) {
- const currentInfo = await http.request('get', '/api/supplierSub/getSwitchById', {
- params: {
- id: payload.id,
- type: payload.type
- }
- })
- if (currentInfo && currentInfo.code === 0) {
- state.currentInfo = currentInfo.data || {}
- state.type = currentInfo.data.type || ''
- state.spacecode = currentInfo.data.spacecode || ''
- commit('updateLogin', true)
- } else {
- commit('updateLogin', false)
- }
- return currentInfo
- },
- async getAppMenu({ state }) {
- const menu = await http.request('get', '/api/app/menu/permission/menu', {})
- storage.setItem('appMenu', [])
- if (menu && menu.code === 0) {
- const appMenu = menu.data || []
- storage.setItem('appMenu', appMenu)
- }
- },
- async getAppMenuSupplier({ state }) {
- const menu = await http.request('get', '/api/app/menu/supplier/permission/menu', {})
- storage.setItem('appMenu', [])
- if (menu && menu.code === 0) {
- const appMenu = menu.data || []
- storage.setItem('appMenu', appMenu)
- }
- },
- async getAppMenuPartner({ state }) {
- const menu = await http.request('get', '/api/app/menu/partner/permission/menu', {})
- storage.setItem('appMenu', [])
- if (menu && menu.code === 0) {
- const appMenu = menu.data || []
- storage.setItem('appMenu', appMenu)
- }
- },
- async loginwx({ dispatch, state }, data) {
- const resp = await http.request('post', '/api/login/wechat', {
- data: {
- code: data.code,
- imgurl: data.imgurl || '',
- nickname: data.nickname || '',
- inviter: data.inviter || '',
- phoneNumber: data.phoneNumber || '',
- purePhoneNumber: data.purePhoneNumber || '',
- }
- })
- if (resp && resp.code === 0) {
- state.isBind = true
- storage.setItem('token', resp.data.access_token || '')
- state.hasLogin = true
- if (data.inviter) {
- storage.removeItem('inviter')
- storage.removeItem('inviterTime')
- storage.removeItem('inviterName')
- }
- await dispatch('getCurrentInfo')
- } else {
- message.showToast('登录失败: ' + (resp && resp.msg))
- storage.removeItem('openid')
- storage.removeItem('tel')
- storage.removeItem('token')
- }
- return resp
- }
- }
-})
-
-export default store
diff --git a/store/index.ts b/store/index.ts
new file mode 100644
index 0000000..9ea779f
--- /dev/null
+++ b/store/index.ts
@@ -0,0 +1,69 @@
+// stores/user.ts
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+import http from '@/plugins/http.js' // 请替换成你实际的 http 封装路径
+import storage from '@/plugins/storage' // 同样替换为你的封装路径
+import message from '@/plugins/message' // 你使用的消息组件封装
+import { WechatLoginData } from '@/types/index'
+
+
+export const useUserStore = defineStore('user', () => {
+ const hasLogin = ref(false)
+ const isBind = ref(false)
+
+ async function getCurrentInfo() {
+ // 模拟请求用户信息
+ console.log('获取当前用户信息')
+ // 这里你可以请求 /api/user/info 等接口获取用户数据
+ }
+
+ async function loginwx(data: WechatLoginData) {
+ const {
+ code,
+ imgurl = '',
+ nickname = '',
+ inviter = '',
+ phoneNumber = '',
+ purePhoneNumber = ''
+ } = data
+
+ const resp = await http.request('post', '/api/login/wechat', {
+ data: {
+ code,
+ imgurl,
+ nickname,
+ inviter,
+ phoneNumber,
+ purePhoneNumber
+ }
+ })
+
+ if (resp && resp.code === 0) {
+ isBind.value = true
+ storage.setItem('token', resp.data.access_token || '')
+ hasLogin.value = true
+
+ if (inviter) {
+ storage.removeItem('inviter')
+ storage.removeItem('inviterTime')
+ storage.removeItem('inviterName')
+ }
+
+ await getCurrentInfo()
+ } else {
+ message.showToast('登录失败:' + (resp?.msg || '未知错误'))
+ storage.removeItem('openid')
+ storage.removeItem('tel')
+ storage.removeItem('token')
+ }
+
+ return resp
+ }
+
+ return {
+ hasLogin,
+ isBind,
+ loginwx,
+ getCurrentInfo
+ }
+})
diff --git a/store/user.ts b/store/user.ts
index c95eed2..61a39ea 100644
--- a/store/user.ts
+++ b/store/user.ts
@@ -1,6 +1,88 @@
+// stores/user.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
+import http from '@/plugins/http.js' // 请替换成你实际的 http 封装路径
+import storage from '@/plugins/storage' // 同样替换为你的封装路径
+import message from '@/plugins/message' // 你使用的消息组件封装
+import { WechatLoginData } from '@/types/index'
+
export const useUserStore = defineStore('user', () => {
-
-})
\ No newline at end of file
+ const hasLogin = ref(false)
+ const isBind = ref(false)
+ const userInfo = ref<any>(null)
+
+ async function getCurrentInfo() {
+ const currentInfo = await http.request('get', '/api/current/user', {})
+ if (currentInfo && currentInfo.code == 0) {
+ console.log('当前用户信息', currentInfo)
+ userInfo.value = currentInfo.data // 赋值到 store
+ } else {
+ message.showToast('获取用户信息失败')
+ }
+ }
+
+ async function loginwx(data: WechatLoginData) {
+ const {
+ code,
+ imgurl = '',
+ nickname = '',
+ inviter = '',
+ phoneNumber = '',
+ purePhoneNumber = ''
+ } = data
+
+ const resp = await http.request('post', '/api/login/wechat', {
+ data: {
+ code,
+ imgurl,
+ nickname,
+ inviter,
+ phoneNumber,
+ purePhoneNumber
+ }
+ })
+
+ if (resp && resp.code === 0) {
+
+ isBind.value = true
+ storage.setItem('token', resp.data.access_token || '')
+ hasLogin.value = true
+ await getCurrentInfo()
+ } else {
+ message.showToast('登录失败:' + (resp?.msg || '未知错误'))
+ storage.removeItem('openid')
+ storage.removeItem('tel')
+ storage.removeItem('token')
+ }
+
+ return resp
+ }
+
+
+ function initLoginState() {
+ const token = storage.getItem('token')
+ if (token) {
+ hasLogin.value = true
+
+ const savedUserInfo = storage.getItem('userInfo')
+ if (savedUserInfo) {
+ userInfo.value = savedUserInfo
+ } else {
+ getCurrentInfo()
+ }
+ } else {
+ hasLogin.value = false
+ }
+ }
+
+
+ return {
+ hasLogin,
+ isBind,
+ userInfo,
+ loginwx,
+ getCurrentInfo,
+ initLoginState,
+ }
+})
diff --git a/types/index.ts b/types/index.ts
index 3f1ff30..0aa5aff 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -1,9 +1,3 @@
-export interface ProtocolData {
- id: number;
- title: string;
- content: string;
-}
-
export interface WxUser {
openId: String;
sessionKey: String;
@@ -13,6 +7,21 @@
purePhoneNumber: String;
}
+export interface WechatLoginData {
+ code: string
+ imgurl?: string
+ nickname?: string
+ inviter?: string
+ phoneNumber?: string
+ purePhoneNumber?: string
+}
+
+export interface ProtocolData {
+ id: number;
+ title: string;
+ content: string;
+}
+
export interface FilmWorks{
id?: number;
diff --git a/utils/time.ts b/utils/time.ts
index 8affc77..731a4a9 100644
--- a/utils/time.ts
+++ b/utils/time.ts
@@ -1,6 +1,35 @@
// utils/time.ts
export function formatRelativeTime(inputTime: string | Date): string {
+ const now = new Date()
+
+ // 如果是字符串格式,先进行兼容性处理
+ let time: Date
+ if (typeof inputTime === 'string') {
+ // 替换中间的空格为 'T' 或替换 '-' 为 '/'
+ const compatibleStr = inputTime.replace(/-/g, '/')
+ time = new Date(compatibleStr)
+ } else {
+ time = inputTime
+ }
+
+ const diffMs = now.getTime() - time.getTime()
+
+ const minutes = Math.floor(diffMs / (1000 * 60))
+ const hours = Math.floor(minutes / 60)
+ const days = Math.floor(hours / 24)
+ const months = Math.floor(days / 30)
+ const years = Math.floor(days / 365)
+
+ if (years > 0) return `${years} 年前`
+ if (months > 0) return `${months} 个月前`
+ if (days > 0) return `${days} 天前`
+ if (hours > 0) return `${hours} 小时前`
+ if (minutes > 0) return `${minutes} 分钟前`
+ return '刚刚'
+}
+
+export function formatRelativeTime2(inputTime: string | Date): string {
const now = new Date()
const time = typeof inputTime === 'string' ? new Date(inputTime) : inputTime
const diffMs = now.getTime() - time.getTime()
--
Gitblit v1.9.3