diff --git a/Yi.Ai.Vue3/src/App.vue b/Yi.Ai.Vue3/src/App.vue
index ac1b0a53..3ea0046e 100644
--- a/Yi.Ai.Vue3/src/App.vue
+++ b/Yi.Ai.Vue3/src/App.vue
@@ -1,67 +1,8 @@
-
-
diff --git a/Yi.Ai.Vue3/src/api/cardFlip/types.ts b/Yi.Ai.Vue3/src/api/cardFlip/types.ts
index 4683f9a3..6b0ceab0 100644
--- a/Yi.Ai.Vue3/src/api/cardFlip/types.ts
+++ b/Yi.Ai.Vue3/src/api/cardFlip/types.ts
@@ -7,9 +7,10 @@ export interface CardFlipStatusOutput {
canFlip: boolean; // 是否可以翻牌
myInviteCode?: string; // 用户的邀请码
invitedCount: number; // 本周邀请人数
- isInvited: boolean; // 是否已被邀请
+ // isInvited: boolean; // 是否已被邀请
flipRecords: CardFlipRecord[]; // 翻牌记录
nextFlipTip?: string; // 下次可翻牌提示
+ isFilledInviteCode: boolean;// 当前用户是否已经填写过邀请码
}
// 翻牌记录
diff --git a/Yi.Ai.Vue3/src/api/user/index.ts b/Yi.Ai.Vue3/src/api/user/index.ts
index a19f0073..6b9d6b8d 100644
--- a/Yi.Ai.Vue3/src/api/user/index.ts
+++ b/Yi.Ai.Vue3/src/api/user/index.ts
@@ -22,6 +22,10 @@ export interface PremiumTokenUsageDto {
purchaseAmount: number;
/** 备注 */
remark?: string;
+ /** 创建时间 */
+ creationTime?: string;
+ /** 创建者ID */
+ creatorId?: string;
}
// 查询参数接口 - 匹配后端 PagedAllResultRequestDto
@@ -38,6 +42,10 @@ export interface PremiumTokenUsageQueryParams {
skipCount?: number;
/** 最大返回数量(分页) */
maxResultCount?: number;
+ /** 是否免费 */
+ isFree?: boolean;
+ // 是否为升序排序
+ isAscending?: boolean;
}
// 分页响应接口
diff --git a/Yi.Ai.Vue3/src/components/LoginDialog/components/QrCodeLogin/index.vue b/Yi.Ai.Vue3/src/components/LoginDialog/components/QrCodeLogin/index.vue
index 601387d1..0031b25b 100644
--- a/Yi.Ai.Vue3/src/components/LoginDialog/components/QrCodeLogin/index.vue
+++ b/Yi.Ai.Vue3/src/components/LoginDialog/components/QrCodeLogin/index.vue
@@ -7,6 +7,7 @@ import { getQrCode, getQrCodeResult, getUserInfo } from '@/api';
import { useUserStore } from '@/stores';
import { useSessionStore } from '@/stores/modules/session.ts';
import { WECHAT_QRCODE_TYPE } from '@/utils/user.ts';
+import { useGuideTour } from '@/hooks/useGuideTour';
const props = defineProps({
type: {
@@ -29,6 +30,7 @@ const userStore = useUserStore();
const router = useRouter();
const sessionStore = useSessionStore();
const isQrCodeError = ref(false);
+const { startFullTour } = useGuideTour();
// 二维码倒计时实例
const { start: qrStart, stop: qrStop } = useCountdown(shallowRef(600), {
interval: 1000,
@@ -126,6 +128,11 @@ async function handleLoginSuccess(token: string, refreshToken: string) {
stopPolling();
userStore.setToken(token, refreshToken);
const resUserInfo = await getUserInfo();
+
+ // 判断是否为新用户(注册时间小于1小时)
+ const creationTime = resUserInfo.data.user.creationTime; // 格式: "2024-11-01 12:01:34"
+ const isNewUser = checkIsNewUser(creationTime);
+
userStore.setUserInfo(resUserInfo.data);
// 提示用户
ElMessage.success('登录成功');
@@ -133,6 +140,34 @@ async function handleLoginSuccess(token: string, refreshToken: string) {
await router.replace('/');
await sessionStore.requestSessionList(1, true);
userStore.closeLoginDialog();
+
+ // 如果是新用户,延迟500ms后自动触发新手引导
+ if (isNewUser) {
+ setTimeout(() => {
+ startFullTour();
+ }, 500);
+ }
+}
+
+// 判断是否为新用户(注册时间距离当前时间小于1小时)
+function checkIsNewUser(creationTimeStr: string): boolean {
+ try {
+ // 解析注册时间字符串 "2024-11-01 12:01:34"
+ const creationTime = new Date(creationTimeStr.replace(' ', 'T'));
+ const currentTime = new Date();
+
+ // 计算时间差(毫秒)
+ const timeDiff = currentTime.getTime() - creationTime.getTime();
+
+ // 1小时 = 60分钟 * 60秒 * 1000毫秒 = 3600000毫秒
+ const oneHourInMs = 60 * 60 * 1000;
+
+ return timeDiff < oneHourInMs;
+ }
+ catch (error) {
+ console.error('解析注册时间失败:', error);
+ return false;
+ }
}
// 处理注册授权
diff --git a/Yi.Ai.Vue3/src/components/ModelSelect/index.vue b/Yi.Ai.Vue3/src/components/ModelSelect/index.vue
index f3b482aa..ce697df9 100644
--- a/Yi.Ai.Vue3/src/components/ModelSelect/index.vue
+++ b/Yi.Ai.Vue3/src/components/ModelSelect/index.vue
@@ -2,22 +2,17 @@
-
+
import type { AnnouncementLogDto } from '@/api';
import type { CloseType } from '@/stores/modules/announcement';
+import { getSystemAnnouncements } from '@/api';
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useAnnouncementStore } from '@/stores';
const announcementStore = useAnnouncementStore();
+const isLoadingData = ref(false);
const activeTab = ref('activity');
@@ -52,7 +54,7 @@ function handleClose(type: CloseType) {
announcementStore.closeDialog(type);
const messages = {
- today: '今日内不再显示',
+ today: '一周内不再显示',
permanent: '公告已关闭',
};
@@ -73,6 +75,31 @@ function getActivityStatus(activity: AnnouncementLogDto): 'active' | 'expired' {
const endTime = new Date(activity.endTime);
return now > endTime ? 'expired' : 'active';
}
+
+// 监听弹窗显示状态,每次打开时从后端获取最新数据
+watch(isDialogVisible, async (newValue) => {
+ if (newValue) {
+ // 弹窗打开时,从后端获取最新数据
+ isLoadingData.value = true;
+ try {
+ const res = await getSystemAnnouncements();
+ if (res && res.data && Array.isArray(res.data)) {
+ announcementStore.setAnnouncementData(res.data);
+ }
+ else {
+ announcementStore.setAnnouncementData([]);
+ }
+ }
+ catch (error) {
+ console.error('获取系统公告失败:', error);
+ ElMessage.error('获取公告数据失败,请稍后重试');
+ announcementStore.setAnnouncementData([]);
+ }
+ finally {
+ isLoadingData.value = false;
+ }
+ }
+});
@@ -83,7 +110,7 @@ function getActivityStatus(activity: AnnouncementLogDto): 'active' | 'expired' {
:close-on-click-modal="true"
class="announcement-dialog"
>
-
+
@@ -199,7 +226,7 @@ function getActivityStatus(activity: AnnouncementLogDto): 'active' | 'expired' {