diff --git a/components.d.ts b/components.d.ts index affcc3d..152f21a 100644 --- a/components.d.ts +++ b/components.d.ts @@ -7,6 +7,7 @@ export {} declare module 'vue' { export interface GlobalComponents { + Auth: typeof import('./src/components/Auth/index.vue')['default'] CuDateQuery: typeof import('./src/components/cu-date-query/index.vue')['default'] CuPicker: typeof import('./src/components/cu-picker/index.vue')['default'] CustomNavbar: typeof import('./src/components/custom-navbar/index.vue')['default'] @@ -18,7 +19,9 @@ declare module 'vue' { QiunDataCharts: typeof import('./src/components/qiun-data-charts/qiun-data-charts.vue')['default'] QiunError: typeof import('./src/components/qiun-error/qiun-error.vue')['default'] QiunLoading: typeof import('./src/components/qiun-loading/qiun-loading.vue')['default'] + WdBadge: typeof import('wot-design-uni/components/wd-badge/wd-badge.vue')['default'] WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default'] + WdCalendar: typeof import('wot-design-uni/components/wd-calendar/wd-calendar.vue')['default'] WdCard: typeof import('wot-design-uni/components/wd-card/wd-card.vue')['default'] WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default'] WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default'] @@ -26,6 +29,9 @@ declare module 'vue' { WdCollapse: typeof import('wot-design-uni/components/wd-collapse/wd-collapse.vue')['default'] WdCollapseItem: typeof import('wot-design-uni/components/wd-collapse-item/wd-collapse-item.vue')['default'] WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default'] + WdDropMenu: typeof import('wot-design-uni/components/wd-drop-menu/wd-drop-menu.vue')['default'] + WdDropMenuItem: typeof import('wot-design-uni/components/wd-drop-menu-item/wd-drop-menu-item.vue')['default'] + WdFab: typeof import('wot-design-uni/components/wd-fab/wd-fab.vue')['default'] WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default'] WdFormItem: typeof import('wot-design-uni/components/wd-form-item/wd-form-item.vue')['default'] WdGrid: typeof import('wot-design-uni/components/wd-grid/wd-grid.vue')['default'] @@ -34,20 +40,26 @@ declare module 'vue' { WdImg: typeof import('wot-design-uni/components/wd-img/wd-img.vue')['default'] WdImgCropper: typeof import('wot-design-uni/components/wd-img-cropper/wd-img-cropper.vue')['default'] WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default'] + WdInputNumber: typeof import('wot-design-uni/components/wd-input-number/wd-input-number.vue')['default'] WdLoading: typeof import('wot-design-uni/components/wd-loading/wd-loading.vue')['default'] + WdLoadmore: typeof import('wot-design-uni/components/wd-loadmore/wd-loadmore.vue')['default'] WdMessageBox: typeof import('wot-design-uni/components/wd-message-box/wd-message-box.vue')['default'] WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default'] WdNotify: typeof import('wot-design-uni/components/wd-notify/wd-notify.vue')['default'] + WdPicker: typeof import('wot-design-uni/components/wd-picker/wd-picker.vue')['default'] WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default'] WdProgress: typeof import('wot-design-uni/components/wd-progress/wd-progress.vue')['default'] WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default'] WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default'] WdSearch: typeof import('wot-design-uni/components/wd-search/wd-search.vue')['default'] + WdSelectPicker: typeof import('wot-design-uni/components/wd-select-picker/wd-select-picker.vue')['default'] WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default'] WdSwiper: typeof import('wot-design-uni/components/wd-swiper/wd-swiper.vue')['default'] WdSwitch: typeof import('wot-design-uni/components/wd-switch/wd-switch.vue')['default'] + WdTab: typeof import('wot-design-uni/components/wd-tab/wd-tab.vue')['default'] WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default'] WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default'] + WdTabs: typeof import('wot-design-uni/components/wd-tabs/wd-tabs.vue')['default'] WdTag: typeof import('wot-design-uni/components/wd-tag/wd-tag.vue')['default'] WdText: typeof import('wot-design-uni/components/wd-text/wd-text.vue')['default'] WdTextarea: typeof import('wot-design-uni/components/wd-textarea/wd-textarea.vue')['default'] diff --git a/src/api/config.ts b/src/api/config.ts new file mode 100644 index 0000000..d1c97a9 --- /dev/null +++ b/src/api/config.ts @@ -0,0 +1,104 @@ +import request from "@/utils/request"; + +const CONFIG_BASE_URL = "/api/v1/configs"; + +const ConfigAPI = { + /** 获取系统配置分页数据 */ + getPage(queryParams: ConfigPageQuery) { + return request({ + url: `${CONFIG_BASE_URL}`, + method: "GET", + data: queryParams, + }); + }, + /** + * 获取系统配置表单数据 + * + * @param id ConfigID + * @returns Config表单数据 + */ + getFormData(id: number) { + return request({ + url: `${CONFIG_BASE_URL}/${id}/form`, + method: "GET", + }); + }, + + /** 添加系统配置*/ + add(data: ConfigForm) { + return request({ + url: `${CONFIG_BASE_URL}`, + method: "POST", + data: data, + }); + }, + + /** + * 更新系统配置 + * + * @param id ConfigID + * @param data Config表单数据 + */ + update(id: number, data: ConfigForm) { + return request({ + url: `${CONFIG_BASE_URL}/${id}`, + method: "PUT", + data: data, + }); + }, + + /** + * 删除系统配置 + * + * @param ids 系统配置ID + */ + deleteById(id: number) { + return request({ + url: `${CONFIG_BASE_URL}/${id}`, + method: "DELETE", + }); + }, + + refreshCache() { + return request({ + url: `${CONFIG_BASE_URL}/refresh`, + method: "PUT", + }); + }, +}; + +export default ConfigAPI; + +/** $系统配置分页查询参数 */ +export interface ConfigPageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; +} + +/** 系统配置表单对象 */ +export interface ConfigForm { + /** 主键 */ + id?: number; + /** 配置名称 */ + configName?: string; + /** 配置键 */ + configKey?: string; + /** 配置值 */ + configValue?: string; + /** 描述、备注 */ + remark?: string; +} + +/** 系统配置分页对象 */ +export interface ConfigPageVO { + /** 主键 */ + id?: number; + /** 配置名称 */ + configName?: string; + /** 配置键 */ + configKey?: string; + /** 配置值 */ + configValue?: string; + /** 描述、备注 */ + remark?: string; +} diff --git a/src/api/dept.ts b/src/api/dept.ts new file mode 100644 index 0000000..cdbd165 --- /dev/null +++ b/src/api/dept.ts @@ -0,0 +1,130 @@ +import request from "@/utils/request"; + +const DEPT_BASE_URL = "/api/v1/dept"; + +const DeptAPI = { + /** + * 获取部门列表 + * + * @param queryParams 查询参数(可选) + * @returns 部门树形表格数据 + */ + getList(queryParams?: DeptQuery) { + return request({ + url: `${DEPT_BASE_URL}`, + method: "GET", + data: queryParams, + }); + }, + + /** 获取部门下拉列表 */ + getOptions() { + return request({ + url: `${DEPT_BASE_URL}/options`, + method: "GET", + }); + }, + + /** + * 获取部门表单数据 + * + * @param id 部门ID + * @returns 部门表单数据 + */ + getFormData(id: number) { + return request({ + url: `${DEPT_BASE_URL}/${id}/form`, + method: "GET", + }); + }, + + /** + * 新增部门 + * + * @param data 部门表单数据 + * @returns 请求结果 + */ + add(data: DeptForm) { + return request({ + url: `${DEPT_BASE_URL}`, + method: "POST", + data: data, + }); + }, + + /** + * 修改部门 + * + * @param id 部门ID + * @param data 部门表单数据 + * @returns 请求结果 + */ + update(id: number, data: DeptForm) { + return request({ + url: `${DEPT_BASE_URL}/${id}`, + method: "PUT", + data: data, + }); + }, + + /** + * 删除部门 + * + * @param ids 部门ID,多个以英文逗号(,)分隔 + * @returns 请求结果 + */ + deleteByIds(ids: string) { + return request({ + url: `${DEPT_BASE_URL}/${ids}`, + method: "DELETE", + }); + }, +}; + +export default DeptAPI; + +/** 部门查询参数 */ +export interface DeptQuery { + /** 搜索关键字 */ + keywords?: string; + /** 状态 */ + status?: number; +} + +/** 部门类型 */ +export interface DeptVO { + /** 子部门 */ + children?: DeptVO[]; + /** 创建时间 */ + createTime?: Date; + /** 部门ID */ + id?: number; + /** 部门名称 */ + name?: string; + /** 部门编号 */ + code?: string; + /** 父部门ID */ + parentId?: number; + /** 排序 */ + sort?: number; + /** 状态(1:启用;0:禁用) */ + status?: number; + /** 修改时间 */ + updateTime?: Date; +} + +/** 部门表单类型 */ +export interface DeptForm { + /** 部门ID(新增不填) */ + id?: number; + /** 部门名称 */ + name?: string; + /** 部门编号 */ + code?: string; + /** 父部门ID */ + parentId: number; + /** 排序 */ + sort?: number; + /** 状态(1:启用;0:禁用) */ + status?: number; +} diff --git a/src/api/log.ts b/src/api/log.ts new file mode 100644 index 0000000..5e17546 --- /dev/null +++ b/src/api/log.ts @@ -0,0 +1,123 @@ +import request from "@/utils/request"; + +const LOG_BASE_URL = "/api/v1/logs"; +const STATISTICS_BASE_URL = "/api/v1/statistics"; + +const LogAPI = { + /** + * 获取日志分页列表 + * + * @param queryParams 查询参数 + */ + getPage(queryParams?: LogPageQuery) { + return request({ + url: `${LOG_BASE_URL}`, + method: "GET", + data: queryParams, + }); + }, + + /** + * 获取访问趋势统计 + * + * @param queryParams 查询参数 + * @returns 访问趋势数据 + */ + getVisitTrend(queryParams: VisitTrendQuery) { + return request({ + url: `${STATISTICS_BASE_URL}/visits/trend`, + method: "GET", + data: queryParams, + }); + }, + + /** + * 获取访问概览统计 + * + * @returns 访问概览数据 + */ + getVisitStats() { + return request({ + url: `${STATISTICS_BASE_URL}/visits/overview`, + method: "GET", + }); + }, +}; + +export default LogAPI; + +/** + * 日志分页查询对象 + */ +export interface LogPageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; + /** 操作时间 */ + createTime?: [string, string] | string; +} + +/** + * 系统日志分页VO + */ +export interface LogVO { + /** 主键 */ + id?: number; + /** 日志模块 */ + module?: string; + /** 日志内容 */ + content?: string; + /** 请求路径 */ + requestUri?: string; + /** 请求方法 */ + method?: string; + /** IP 地址 */ + ip?: string; + /** 地区 */ + region?: string; + /** 浏览器 */ + browser?: string; + /** 终端系统 */ + os?: string; + /** 执行时间(毫秒) */ + executionTime?: number; + /** 操作人 */ + operator?: string; + /** 操作时间 */ + createTime?: string; +} + +/** 访问趋势视图对象 */ +export interface VisitTrendVO { + /** 日期列表 */ + dates: string[]; + /** 浏览量(PV) */ + pvList: number[]; + /** 访客数(UV) */ + uvList: number[]; + /** IP数 */ + ipList: number[]; +} + +/** 访问趋势查询参数 */ +export interface VisitTrendQuery { + /** 开始日期 */ + startDate: string; + /** 结束日期 */ + endDate: string; +} + +/** 访问统计 */ +export interface VisitStatsVO { + /** 今日访客数(UV) */ + todayUvCount: number; + /** 总访客数 */ + totalUvCount: number; + /** 访客数同比增长率(相对于昨天同一时间段的增长率) */ + uvGrowthRate: number; + /** 今日浏览量(PV) */ + todayPvCount: number; + /** 总浏览量 */ + totalPvCount: number; + /** 同比增长率(相对于昨天同一时间段的增长率) */ + pvGrowthRate: number; +} diff --git a/src/api/notice.ts b/src/api/notice.ts new file mode 100644 index 0000000..b02cfbb --- /dev/null +++ b/src/api/notice.ts @@ -0,0 +1,202 @@ +import request from "@/utils/request"; + +const NOTICE_BASE_URL = "/api/v1/notices"; + +const NoticeAPI = { + /** 获取通知公告分页数据 */ + getPage(queryParams?: NoticePageQuery) { + return request({ + url: `${NOTICE_BASE_URL}`, + method: "GET", + data: queryParams, + }); + }, + + /** + * 获取通知公告表单数据 + * + * @param id NoticeID + * @returns Notice表单数据 + */ + getFormData(id: number) { + return request({ + url: `${NOTICE_BASE_URL}/${id}/form`, + method: "GET", + }); + }, + + /** + * 添加通知公告 + * + * @param data Notice表单数据 + * @returns + */ + add(data: NoticeForm) { + return request({ + url: `${NOTICE_BASE_URL}`, + method: "POST", + data: data, + }); + }, + + /** + * 更新通知公告 + * + * @param id NoticeID + * @param data Notice表单数据 + */ + update(id: number, data: NoticeForm) { + return request({ + url: `${NOTICE_BASE_URL}/${id}`, + method: "PUT", + data: data, + }); + }, + + /** + * 批量删除通知公告,多个以英文逗号(,)分割 + * + * @param ids 通知公告ID字符串,多个以英文逗号(,)分割 + */ + deleteByIds(ids: string) { + return request({ + url: `${NOTICE_BASE_URL}/${ids}`, + method: "DELETE", + }); + }, + + /** + * 发布通知 + * + * @param id 被发布的通知公告id + * @returns + */ + publish(id: number) { + return request({ + url: `${NOTICE_BASE_URL}/${id}/publish`, + method: "PUT", + }); + }, + + /** + * 撤回通知 + * + * @param id 撤回的通知id + * @returns + */ + revoke(id: number) { + return request({ + url: `${NOTICE_BASE_URL}/${id}/revoke`, + method: "PUT", + }); + }, + + /** + * 查看通知 + * + * @param id + */ + getDetail(id: string) { + return request({ + url: `${NOTICE_BASE_URL}/${id}/detail`, + method: "GET", + }); + }, + + /* 全部已读 */ + readAll() { + return request({ + url: `${NOTICE_BASE_URL}/read-all`, + method: "PUT", + }); + }, + + /** 获取我的通知分页列表 */ + getMyNoticePage(queryParams?: NoticePageQuery) { + return request({ + url: `${NOTICE_BASE_URL}/my`, + method: "GET", + data: queryParams, + }); + }, +}; + +export default NoticeAPI; + +/** 通知公告分页查询参数 */ +export interface NoticePageQuery extends PageQuery { + /** 标题 */ + title?: string; + /** 发布状态(0:未发布,1:已发布,-1:已撤回) */ + publishStatus?: number; + + isRead?: number; +} + +/** 通知公告表单对象 */ +export interface NoticeForm { + id?: number; + /** 通知标题 */ + title?: string; + /** 通知内容 */ + content?: string; + /** 通知类型 */ + type?: number; + /** 优先级(L:低,M:中,H:高) */ + level?: string; + /** 目标类型(1-全体 2-指定) */ + targetType?: number; + /** 目标ID合集,以,分割 */ + targetUserIds?: string; +} + +/** 通知公告分页对象 */ +export interface NoticePageVO { + id: string; + /** 通知标题 */ + title?: string; + /** 通知内容 */ + content?: string; + /** 通知类型 */ + type?: number; + /** 发布人 */ + publisherName?: string; + /** 优先级(0-低 1-中 2-高) */ + priority?: number; + /** 目标类型(0-全体 1-指定) */ + targetType?: number; + /** 发布状态(0-未发布 1已发布 2已撤回) */ + publishStatus?: number; + /** 发布时间 */ + publishTime?: Date; + /** 撤回时间 */ + revokeTime?: Date; + /** 优先级(L-低 M-中 H-高) */ + level?: string | number; +} + +export interface NoticeDetailVO { + /** 通知ID */ + id?: string; + + /** 通知标题 */ + title?: string; + + /** 通知内容 */ + content?: string; + + /** 通知类型 */ + type?: number; + + /** 发布人 */ + publisherName?: string; + + /** 优先级(L-低 M-中 H-高) */ + level?: string; + + /** 发布时间 */ + publishTime?: Date; + + /** 发布状态 */ + publishStatus?: number; +} diff --git a/src/api/role.ts b/src/api/role.ts new file mode 100644 index 0000000..f4e7ea0 --- /dev/null +++ b/src/api/role.ts @@ -0,0 +1,139 @@ +import request from "@/utils/request"; + +const ROLE_BASE_URL = "/api/v1/roles"; + +const RoleAPI = { + /** 获取角色分页数据 */ + getPage(queryParams?: RolePageQuery) { + return request({ + url: `${ROLE_BASE_URL}`, + method: "GET", + data: queryParams, + }); + }, + + /** 获取角色下拉数据源 */ + getOptions() { + return request({ + url: `${ROLE_BASE_URL}/options`, + method: "GET", + }); + }, + + /** + * 获取角色的菜单ID集合 + * + * @param roleId 角色ID + * @returns 角色的菜单ID集合 + */ + getRoleMenuIds(roleId: number) { + return request({ + url: `${ROLE_BASE_URL}/${roleId}/menuIds`, + method: "GET", + }); + }, + + /** + * 分配菜单权限 + * + * @param roleId 角色ID + * @param data 菜单ID集合 + */ + updateRoleMenus(roleId: number, data: number[]) { + return request({ + url: `${ROLE_BASE_URL}/${roleId}/menus`, + method: "PUT", + data: data, + }); + }, + + /** + * 获取角色表单数据 + * + * @param id 角色ID + * @returns 角色表单数据 + */ + getFormData(id: number) { + return request({ + url: `${ROLE_BASE_URL}/${id}/form`, + method: "GET", + }); + }, + + /** 添加角色 */ + add(data: RoleForm) { + return request({ + url: `${ROLE_BASE_URL}`, + method: "POST", + data: data, + }); + }, + + /** + * 更新角色 + * + * @param id 角色ID + * @param data 角色表单数据 + */ + update(id: number, data: RoleForm) { + return request({ + url: `${ROLE_BASE_URL}/${id}`, + method: "PUT", + data: data, + }); + }, + + /** + * 批量删除角色,多个以英文逗号(,)分割 + * + * @param ids 角色ID字符串,多个以英文逗号(,)分割 + */ + deleteByIds(ids: string) { + return request({ + url: `${ROLE_BASE_URL}/${ids}`, + method: "DELETE", + }); + }, +}; + +export default RoleAPI; + +/** 角色分页查询参数 */ +export interface RolePageQuery extends PageQuery { + /** 搜索关键字 */ + keywords?: string; +} + +/** 角色分页对象 */ +export interface RolePageVO { + /** 角色编码 */ + code?: string; + /** 角色ID */ + id: number; + /** 角色名称 */ + name?: string; + /** 排序 */ + sort?: number; + /** 角色状态 */ + status?: number; + /** 创建时间 */ + createTime?: string; + /** 修改时间 */ + updateTime?: string; +} + +/** 角色表单对象 */ +export interface RoleForm { + /** 角色ID */ + id?: number; + /** 角色编码 */ + code?: string; + /** 数据权限 */ + dataScope: number; + /** 角色名称 */ + name?: string; + /** 排序 */ + sort: number; + /** 角色状态(1-正常;0-停用) */ + status?: number; +} diff --git a/src/components/Auth/index.vue b/src/components/Auth/index.vue new file mode 100644 index 0000000..8acd07a --- /dev/null +++ b/src/components/Auth/index.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/constants/index.ts b/src/constants/index.ts index 2bf58bf..eed0c48 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -17,3 +17,9 @@ export const USER_INFO_KEY = "user_info"; // 🎨 主题相关 export const THEME_MODE_KEY = "app-theme"; export const THEME_COLOR_KEY = "app-theme-color"; + +// 🔑 权限相关 +/** 超级管理员角色标识 */ +export const ROLE_ROOT = "ROOT"; +/** 全部权限标识 */ +export const PERM_ALL = "*:*:*"; diff --git a/src/pages.json b/src/pages.json index a6305fa..e056a25 100644 --- a/src/pages.json +++ b/src/pages.json @@ -14,7 +14,8 @@ "type": "page", "name": "login", "style": { - "navigationStyle": "custom" + "navigationStyle": "custom", + "navigationBarTitleText": "" } }, { @@ -43,17 +44,6 @@ "path": "pages/mine/account/index", "type": "page" }, - { - "path": "pages/mine/feedback/index", - "type": "page", - "name": "feedback", - "style": { - "navigationBarTitleText": "意见反馈" - }, - "meta": { - "requireAuth": true - } - }, { "path": "pages/mine/official/index", "type": "page", @@ -70,14 +60,6 @@ "path": "pages/mine/profile/index", "type": "page" }, - { - "path": "pages/mine/settings/index", - "type": "page", - "name": "settings", - "style": { - "navigationBarTitleText": "设置" - } - }, { "path": "pages/work/config/index", "type": "page", @@ -118,14 +100,6 @@ "navigationBarTitleText": "通知公告" } }, - { - "path": "pages/work/permission/index", - "type": "page", - "name": "permission", - "style": { - "navigationBarTitleText": "权限管理" - } - }, { "path": "pages/work/role/index", "type": "page", diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue index 641c60a..d232454 100644 --- a/src/pages/login/index.vue +++ b/src/pages/login/index.vue @@ -129,13 +129,12 @@ - diff --git a/src/pages/mine/index.vue b/src/pages/mine/index.vue index 91c704b..3c1d663 100644 --- a/src/pages/mine/index.vue +++ b/src/pages/mine/index.vue @@ -17,7 +17,7 @@ @@ -27,12 +27,12 @@ - {{ userInfo!.nickname || "匿名用户" }} + {{ userInfo?.nickname || "匿名用户" }} - {{ userInfo?.username || "0000000" }} + {{ userInfo?.username || "未设置" }} @@ -56,16 +56,31 @@ - 2 + + {{ notificationCount }} + - + - + + + + + 有来技术 + 技术干货 · 开源社区 · 交流群 + + + + + + + + @@ -86,35 +101,79 @@ + - - 帮助与支持 + + 设置 - - - 问题反馈 + + + 主题设置 + + + + + 用户协议 + + + + + 隐私政策 + + + + + 关于我们 - - - - - 有来技术 - 技术干货 · 开源社区 · 交流群 + + + + + + 系统工具 - - + + + + + 网络测试 + + + + + 清空缓存 + {{ cacheSize }} + + + + 退出登录 + + + + + v{{ appVersion }} + + + + @@ -132,14 +191,17 @@ import { onLoad } from "@dcloudio/uni-app"; import { useUserStore, useThemeStore } from "@/store"; import { useRouter } from "uni-mini-router"; import { useNavbar } from "@/composables/useNavbar"; +import { getAccessToken } from "@/utils/auth"; const userStore = useUserStore(); const themeStore = useThemeStore(); const currentThemeColor = computed(() => themeStore.themeVars.colorTheme); const userInfo = computed(() => userStore.userInfo); -const isLogin = computed(() => !!userInfo.value); const defaultAvatar = "/static/images/default-avatar.png"; +const hasToken = computed(() => !!getAccessToken()); +const isLogin = computed(() => hasToken.value); + const headerBackground = computed(() => { const color = currentThemeColor.value || "#4d80f0"; const colorWithAlpha = color.length === 7 ? `${color}E6` : color; @@ -149,6 +211,11 @@ const headerBackground = computed(() => { const router = useRouter(); +const notificationCount = computed(() => 0); + +// 版本号 +const appVersion = ref("1.0.0"); + // 使用导航栏 Hook(TabBar 页面) const navbar = useNavbar({ hasTabbar: true }); @@ -177,7 +244,22 @@ const genderIconClass = computed(() => { return ""; }); -onLoad(() => {}); +onLoad(async () => { + const token = getAccessToken(); + if (token && !userStore.userInfo) { + try { + await userStore.getInfo(); + } catch { + // ignore + } + } + + getCacheSize(); + + // #ifdef MP-WEIXIN + appVersion.value = uni.getAccountInfoSync().miniProgram.version || "1.0.0"; + // #endif +}); // 登录 const navigateToLoginPage = () => { @@ -206,20 +288,128 @@ const navigateToAccount = () => { }; const navigateToNotifications = () => { + if (!isLogin.value) { + navigateToLoginPage(); + return; + } uni.showToast({ title: "功能开发中", icon: "none", }); }; -// 设置 -const navigateToSettings = () => { - router.push({ path: "/pages/mine/settings/index" }); +// 主题设置 +const navigateToTheme = () => { + router.push({ path: "/pages/mine/settings/theme/index" }); }; -// 问题反馈 -const handleQuestionFeedback = () => { - router.push({ path: "/pages/mine/feedback/index" }); +// 用户协议 +const navigateToUserAgreement = () => { + router.push({ path: "/pages/mine/settings/agreement/index" }); +}; + +// 隐私政策 +const navigateToPrivacy = () => { + router.push({ path: "/pages/mine/settings/privacy/index" }); +}; + +// 关于我们 +const navigateToAbout = () => { + router.push({ path: "/pages/mine/about/index" }); +}; + +// 网络测试 +const navigateToNetworkTest = () => { + router.push({ path: "/pages/mine/settings/network/index" }); +}; + +const clearing = ref(false); +const cacheSize = ref("计算中..."); + +const formatSize = (size: number) => { + if (size < 1024) { + return size + "B"; + } else if (size < 1024 * 1024) { + return (size / 1024).toFixed(2) + "KB"; + } else { + return (size / 1024 / 1024).toFixed(2) + "MB"; + } +}; + +const getCacheSize = async () => { + try { + // #ifdef MP-WEIXIN + const res = await uni.getStorageInfo(); + cacheSize.value = formatSize(res.currentSize); + // #endif + // #ifdef H5 + cacheSize.value = formatSize( + Object.keys(localStorage).reduce((size, key) => size + localStorage[key].length, 0) + ); + // #endif + if (!cacheSize.value) { + cacheSize.value = "0B"; + } + } catch (error) { + console.error("获取缓存大小失败:", error); + cacheSize.value = "获取失败"; + } +}; + +const handleClearCache = async () => { + if (cacheSize.value === "获取失败") { + uni.showToast({ + title: "获取缓存信息失败,请稍后重试", + icon: "none", + duration: 2000, + }); + return; + } + if (cacheSize.value === "0B") { + uni.showToast({ + title: "暂无缓存需要清理", + icon: "none", + duration: 2000, + }); + return; + } + if (clearing.value) { + return; + } + + try { + clearing.value = true; + await new Promise((resolve) => setTimeout(resolve, 1500)); + await uni.clearStorage(); + await getCacheSize(); + uni.showToast({ + title: "清理成功", + icon: "success", + }); + } catch { + uni.showToast({ + title: "清理失败", + icon: "error", + }); + } finally { + clearing.value = false; + } +}; + +const handleLogout = () => { + uni.showModal({ + title: "提示", + content: "确定要退出登录吗?", + success: function (res) { + if (res.confirm) { + userStore.logout(); + uni.showToast({ + title: "已退出登录", + icon: "success", + }); + } + }, + }); }; // 有来技术公众号 @@ -435,52 +625,57 @@ const navigateToOfficialAccount = () => { color: #9ca3af; } -.official-section { - margin-top: 16rpx; -} - -.official-card { +// 公众号入口(简洁卡片风格) +.official-capsule { display: flex; align-items: center; - padding: 32rpx 28rpx; + margin: -24rpx 28rpx 24rpx; + padding: 20rpx 24rpx; background: #fff; border-radius: 20rpx; - box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04); + box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04); } .official-avatar { - width: 100rpx; - height: 100rpx; - border-radius: 24rpx; + width: 72rpx; + height: 72rpx; + border-radius: 16rpx; } .official-body { flex: 1; min-width: 0; - margin-left: 28rpx; + margin-left: 18rpx; } .official-title { - font-size: 32rpx; + font-size: 28rpx; font-weight: 600; - color: #1f2937; + color: #374151; } .official-desc { - margin-top: 12rpx; - font-size: 24rpx; + margin-top: 4rpx; + font-size: 22rpx; color: #9ca3af; - letter-spacing: 1rpx; } .official-action { display: flex; align-items: center; justify-content: center; - width: 56rpx; - height: 56rpx; - background: #f3f4f6; - border-radius: 50%; + padding-left: 8rpx; +} + +// 底部版本号 +.footer-version { + padding: 40rpx 0 60rpx; + text-align: center; + + text { + font-size: 24rpx; + color: #9ca3af; + } } // 退出登录 diff --git a/src/pages/work/config/index.vue b/src/pages/work/config/index.vue index 9489d89..d740c84 100644 --- a/src/pages/work/config/index.vue +++ b/src/pages/work/config/index.vue @@ -1,10 +1,297 @@ - + { @@ -15,4 +302,33 @@ } - + diff --git a/src/pages/work/index.vue b/src/pages/work/index.vue index 387ee2a..8f0aaf6 100644 --- a/src/pages/work/index.vue +++ b/src/pages/work/index.vue @@ -1,14 +1,13 @@