feat: apply senior-friendly portal theme and document UX guidelines

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-02-06 14:20:51 +08:00
parent 1782f64417
commit f3e10256a8
13 changed files with 356 additions and 268 deletions

View File

@@ -16,7 +16,7 @@ Token = ""
# =========================
[Http]
# HTTP服务监听端口
Port = 8080
Port = 18080
# 监听地址(可选,默认 0.0.0.0
# Host = "0.0.0.0"

View File

@@ -1,144 +1,155 @@
# Portal 全局设计准则 (Global Design Guidelines)
# Portal 适老化 UI/UX 与配色落地规范v1
> **适用范围**: PC 端 Portal 站点
> **核心风格**: 内容型(浅灰背景 + 白色卡片),强调信息层级与阅读体验。
> 适用范围`frontend/portal`PC 优先)
>
> 目标在保持简约风格的前提下提升中老年用户50+)的可读性、可操作性与安全感。
## 1. 全局布局 (Layout & Container)
## 1. 设计目标与原则
采用经典的垂直分布布局,确保内容区域聚焦且具备良好的扩展性。
### 1.1 设计目标
### 1.1 页面结构 (DOM Structure)
- **Root**: `min-h-screen flex flex-col bg-slate-50` (浅灰背景hex: `#F8FAFC`)
- **Header**: `fixed top-0 w-full z-50` (固定顶部)
- **Main**: `flex-grow pt-16` (内容自适应填充,顶部留出 Header 高度)
- **Footer**: `mt-auto` (页脚沉底)
1. **简约**:减少视觉噪音与无关装饰,突出主任务路径。
2. **适老**:强化文字对比、按钮可见性、操作反馈。
3. **可信**:降低“误触焦虑”,让界面更稳重、更可预期。
### 1.2 核心容器 (Main Container)
所有页面核心内容需包裹在标准容器内,以保证视觉统一。
- **宽度限制**: `max-w-screen-xl` (Tailwind default: 1280px)
- **对齐方式**: `mx-auto` (水平居中)
- **内边距**: `px-4 sm:px-6 lg:px-8` (响应式呼吸感)
- **示例代码**:
```html
<main class="flex-grow pt-16">
<div class="mx-auto max-w-screen-xl px-4 sm:px-6 lg:px-8 py-8">
<!-- Page Content Here -->
</div>
</main>
```
### 1.2 设计原则
### 1.3 基础色彩规范 (Basic Colors)
- **背景色**: `bg-slate-50` (页面底色)
- **卡片色**: `bg-white` (内容承载)
- **边框色**: `border-slate-200` (轻微分割线)
- **文字色**:
- 主要: `text-slate-900` (标题、正文)
- 次要: `text-slate-500` (描述、辅助信息)
- 链接: `text-primary-600 hover:text-primary-700`
1. **一屏一主动作**:每屏突出 1 个主任务(查、填、确认)。
2. **显性导航**:始终明确当前所在位置与可返回路径。
3. **高对比优先**:关键文字和交互区优先保障可读性。
4. **状态不靠颜色单独表达**:需配合图标与文案。
5. **可切换高对比模式**:满足低视力/高敏感场景。
---
## 2. 顶部导航栏 (TopNavbar)
## 2. 颜色系统Design Tokens
全局常驻入口,承载品牌认知与核心路径导航。
实际实现文件:`frontend/portal/src/assets/main.css`
### 2.1 外观 (Appearance)
- **尺寸**: 高度 `h-16` (64px)
- **背景**: `bg-white` (纯白背景)
- **质感**: `border-b border-slate-200` 或 `shadow-sm` (轻微投影,提升层级)
### 2.1 语义 Token默认主题
### 2.2 布局 (Flex Grid)
`flex items-center justify-between` + `Container`
- `--color-bg-base`:页面底色
- `--color-bg-surface`:卡片/容器底色
- `--color-bg-surface-highlight`:弱强调底色
- `--color-text-main`:主文字
- `--color-text-muted`:次文字
- `--color-text-inverted`:反白文字
- `--color-border-base`:默认边框
- `--color-border-highlight`:强调边框
- `--color-primary-50...950`:品牌主色梯度
| 区域 | 元素 | 交互/样式 |
| --- | --- | --- |
| **Left** | **Logo** | 图片/SVG + 文字,点击回首页 (`/`)。高度控制在 32-40px。 |
| **Center-Left** | **Nav Links** | 首页、分类、标签等。间距 `space-x-8`。<br>Default: `text-slate-600 font-medium`<br>Hover: `text-primary-600`<br>Active: `text-primary-600` |
| **Center-Right** | **Global Search** | 圆角矩形输入框 `rounded-full` 或 `rounded-lg`。<br>`bg-slate-100 focus:bg-white focus:ring`。<br>宽度:默认 `w-64`,聚焦时可伸展。 |
| **Right** | **User Actions** | **未登录**: <br>- [登录]: Ghost Button (`text-slate-600 hover:bg-slate-50`)<br>- [注册]: Primary Button (`bg-primary-600 text-white`)<br>**已登录**: <br>- [通知]: **Bell Icon** (h-10 w-10 flex items-center justify-center rounded-full hover:bg-slate-100 relative)。<br> - **Badge**: 右上角红色圆点或数字,表示未读。<br> - **交互**: 点击直接跳转至 `/me/notifications`。<br>- [头像]: Avatar + Dropdown Menu |
### 2.2 高对比主题
切换选择器:`[data-theme='senior-high-contrast']`
高对比主题目标:
- 背景更纯净(白底)
- 文本更深(黑字)
- 重点更醒目(黄色强调)
- 边框更明确(黑色边框)
### 2.3 PrimeVue 语义映射
已通过全局变量映射统一第三方组件视觉:
- `--p-content-background`
- `--p-content-color`
- `--p-content-border-color`
- `--p-primary-color`
- `--p-primary-contrast-color`
- `--p-inputtext-background`
- `--p-inputtext-color`
- `--p-inputtext-border-color`
---
## 3. 页脚 (Footer)
## 3. 组件与页面层应用规范
全局底部信息区,采用深色风格以稳定视觉重心。
### 3.1 全局布局(已落地)
### 3.1 外观 (Appearance)
- **背景**: `bg-slate-900` (深色)
- **文字**: `text-slate-400` (灰色文本,避免纯白刺眼)
- **链接**: Hover 时变亮 `hover:text-white`
- 页面容器:`bg-base text-content`
- 卡片容器:`bg-surface border border-line`
- 弱强调区:`bg-surface-highlight`
### 3.2 内容结构
- **Upper Section (Links)**: `py-12`
- Grid 布局 (3-4 列)
- 栏目:关于我们、帮助中心、法律条款、关注我们 (Social Icons)
- **Bottom Section (Copyright)**: `border-t border-slate-800 py-6`
- 版权声明 (© 2025 Quyun)
- ICP 备案号 / 公安网备
### 3.2 导航栏TopNavbar
- 背景:`bg-surface`
- 边框:`border-line`
- 主文案:`text-content`
- 次级文案/图标:`text-muted`
- 焦点反馈:`focus:ring` + 高对比 outline
### 3.3 页脚AppFooter
- 背景:`bg-surface-highlight`
- 文案:`text-muted`
- 标题:`text-content`
- 交互 hover`hover:text-primary-600`
### 3.4 用户/创作者侧边栏
- 容器:`bg-surface border border-line`
- 非激活菜单:`text-muted`
- hover`hover:bg-surface-highlight hover:text-content`
- 激活态:`bg-primary-600 text-white`
---
## 4. 通用 UI 元素 (Common Components)
## 4. 交互与文案建议(执行级)
### 4.1 内容卡片 (Content Card)
用于承载列表项、详情块等。
- **样式**: `bg-white rounded-lg border border-slate-100 shadow-sm transition-shadow hover:shadow-md`
- **内边距**: `p-4` 或 `p-6`
### 4.2 按钮 (Buttons)
*针对中老年用户优化:增大点击区域与文字标签*
- **Primary**: `bg-primary-600 text-white hover:bg-primary-700 rounded-lg px-6 py-3 text-lg h-12 flex items-center justify-center`
- **Secondary/Outline**: `border-2 border-slate-300 text-slate-800 hover:bg-slate-50 rounded-lg px-6 py-3 text-lg h-12 flex items-center justify-center`
- **Ghost**: `text-slate-700 hover:bg-slate-100 rounded-lg px-4 py-3 text-lg h-12 flex items-center justify-center`
- **说明**: 按钮高度至少 `48px` (`h-12`),边框适当加粗以便识别。
### 4.3 标题与文字 (Typography)
*针对中老年用户优化:提升基准字号与行高*
- **Root Font Size**: PC 端默认 `16px`,允许用户浏览器缩放。
- **Body Text**: `text-base` (16px) 或 `text-lg` (18px),行高 `leading-relaxed` (1.625)。
- **H1 (页面主标题)**: `text-3xl sm:text-4xl font-bold text-slate-900 mb-6`
- **H2 (区块标题)**: `text-2xl font-bold text-slate-900 mb-5`
- **H3 (小标题)**: `text-xl font-semibold text-slate-900 mb-3`
- **辅助文字**: 避免使用小于 `14px` 的文字。辅助色最低为 `text-slate-600` (保证 4.5:1 对比度)。
### 4.4 输入框 (Inputs)
- **尺寸**: 高度 `h-12` (48px) 或 `h-14` (56px)。
- **样式**: `text-lg px-4 border-slate-300 focus:border-primary-600 focus:ring-2`。
- **Label**: 必须显示 Label字号 `text-base` 或 `text-lg`,不建议仅用 placeholder。
### 4.5 交互反馈 (Interactive Feedback)
- **鼠标手势**: 所有可点击元素(卡片、按钮、链接、自定义交互区)必须明确指定 `cursor: pointer`。
- **视觉反馈**:
- Hover 时应伴随背景色微调、阴影加深或缩放效果 (`transition-all`)。
- Active 时应有轻微的按下缩放效果 (`active:scale-[0.98]`),增强操作确认感。
1. 关键按钮文案使用动词开头:如“确认支付”“保存设置”。
2. 失败文案避免术语:
- ❌ 参数错误
- ✅ 信息未填写完整,请检查后重试
3. 重要状态展示采用“图标 + 颜色 + 文案”三重表达。
4. 表单错误提示紧贴字段,不只在顶部汇总。
---
## 5. 响应式与可访问性 (Responsive & Accessibility)
## 5. 前端落地文件清单(本次)
确保站点在移动端具备良好体验,并符合 WCAG 可访问性标准,**特别关注中老年用户体验**。
- `frontend/portal/src/assets/main.css`
- `frontend/portal/src/main.js`
- `frontend/portal/src/layout/LayoutMain.vue`
- `frontend/portal/src/layout/LayoutUser.vue`
- `frontend/portal/src/layout/LayoutCreator.vue`
- `frontend/portal/src/layout/LayoutAuth.vue`
- `frontend/portal/src/components/TopNavbar.vue`
- `frontend/portal/src/components/AppFooter.vue`
### 5.1 TopNavbar 响应式策略 (Mobile Adaptation)
当视口宽度小于 `md` (768px) 时,导航栏需进行自适应折叠。
---
- **导航链接**: 收纳至左侧或右侧的 **汉堡菜单 (Hamburger Menu)**。
- 菜单图标需显著,加文字标签 "菜单" 辅助识别。
- 抽屉内菜单项字号 `text-lg`,行高宽松。
- **全局搜索**:
- **默认状态**: 仅展示搜索图标 (Magnifying Glass)。
- **交互状态**: 点击图标后,展开全宽搜索栏覆盖 Logo 或 弹出模态搜索框。
- **用户区**:
- 若空间允许,保留头像/登录按钮;若空间不足,并入汉堡菜单底部。
## 6. 验收标准(视觉评审)
### 5.2 键盘导航与焦点 (Keyboard & Focus)
- **Focus Visible**: 所有交互元素(链接、按钮、输入框)在键盘聚焦时必须有清晰的可见轮廓。
- 推荐样式: `focus-visible:ring-4 focus-visible:ring-primary-400 focus-visible:outline-none` (加宽 Ring 宽度)。
- **Skip Link**: 页面首个可聚焦元素应为 "跳转至主要内容 (Skip to main content)"。
### 6.1 基础检查
### 5.3 触控目标 (Touch Targets)
- **最小点击面积**: 移动端交互元素的可点击区域必须 $\ge 48 \times 48$ px (Tailwind `min-h-[48px] min-w-[48px]`)
- 按钮间距 `gap-4` 以上,防止误触
1. 首页、登录页、用户中心、创作者中心色彩风格一致。
2. 主操作按钮在 3 秒内可被识别
3. 次级文字在普通显示器下可清晰阅读
### 5.4 ARIA 与语义化 (Semantics)
- **表单标签**: 所有 `<input>` 必须有对应的可视 `<label>`。
- **高对比度**: 文本与背景对比度至少 **4.5:1** (WCAG AA),关键信息追求 **7:1** (WCAG AAA)。避免使用浅灰文字
### 6.2 无障碍检查
1. 高对比模式可切换并立即生效
2. 聚焦态可视(键盘 Tab 导航清晰)。
3. 状态提示不依赖单一颜色表达。
### 6.3 快速切换方式(调试)
```js
document.documentElement.setAttribute('data-theme', 'senior-high-contrast')
```
恢复默认:
```js
document.documentElement.removeAttribute('data-theme')
```
---
## 7. 后续优化建议v2
1. 将高对比模式入口显式放到导航栏设置中(非仅调试)。
2. 增加“标准/适老”主题切换并持久化到本地。
3. 做 55+ 用户可用性走查(任务完成率、误触率、求助率)。
4. 对支付/实名认证等高风险流程增加更明确的安全确认文案。

View File

@@ -1,29 +1,30 @@
# Implementation Plan: full-lint-remediation
# Implementation Plan: portal-senior-color-redesign
**Branch**: `[chore/full-lint-remediation]` | **Date**: 2026-02-05 | **Spec**: `N/A`
**Input**: Full repo lint remediation covering backend and frontend lint/build steps.
**Branch**: `[feat/portal-senior-color-redesign]` | **Date**: 2026-02-06 | **Spec**: `N/A`
**Input**: User request to redesign Portal color system for minimal, senior-friendly UX and provide a branch for visual validation.
## Summary
Remediate all existing lint failures across the backend and frontend by systematically addressing security warnings, de-duplication, complexity, formatting, naming/style violations, and frontend lint/build issues, while preserving behavior and following project constraints.
Implement a senior-friendly, minimal color system for `frontend/portal` by introducing semantic design tokens (default + high-contrast), applying them to shared shells/components (layouts, navbar, footer), and adding PrimeVue-friendly global styling so visual changes are broad, consistent, and easy to validate by product stakeholders.
## Technical Context
**Language/Version**: Go 1.x
**Primary Dependencies**: Fiber, GORM-Gen, River, golangci-lint
**Storage**: PostgreSQL
**Testing**: `make lint` in `backend/`, `go test ./...`, `npm -C frontend/superadmin run lint`, `npm -C frontend/superadmin run build`, `npm -C frontend/portal run lint`, `npm -C frontend/portal run build`
**Target Platform**: Linux server
**Project Type**: Web application (backend + frontend)
**Performance Goals**: N/A
**Constraints**: Follow `backend/llm.txt`; do not edit generated files; avoid behavior changes while refactoring
**Scale/Scope**: Backend lint errors plus frontend lint/build issues in portal/superadmin
**Language/Version**: Vue 3 (ESM), JavaScript, CSS (Tailwind v4)
**Primary Dependencies**: Vite, TailwindCSS v4, PrimeVue 4 (`@primevue/themes/aura`), PrimeIcons
**Storage**: N/A
**Testing**: `npm -C frontend/portal run lint`, `npm -C frontend/portal run build`
**Target Platform**: Web browser (Portal tenant-facing frontend)
**Project Type**: Web frontend module (`frontend/portal`)
**Performance Goals**: No regressions in initial render and interactivity; preserve current bundle behavior
**Constraints**: Keep changes focused on styling/theme surfaces; no route/business-logic changes; avoid generated files; maintain readability and accessibility contrast goals
**Scale/Scope**: Global portal style tokens + shared layout/component surfaces for meaningful visual review
## Constitution Check
- Follow `backend/llm.txt` (controller thin, services handle DB, Chinese comments for business logic).
- Do not edit generated files (`*.gen.go`, `backend/docs/docs.go`).
- Fix lint issues without behavior changes or API surface drift.
- Conforms to repository planning rule: complete plan defined before non-trivial implementation.
- Scope limited to `frontend/portal` styling/theme layers and shared UI shell.
- No generated files are modified.
- Verification includes frontend lint/build checks before handoff.
## Project Structure
@@ -37,74 +38,67 @@ docs/
### Source Code (repository root)
```text
backend/
├── app/services/super.go
├── app/services/creator_report.go
├── app/services/content.go
├── app/services/creator.go
├── app/services/coupon.go
├── app/services/common.go
├── app/commands/seed/seed.go
── app/commands/storage_migrate/migrate.go
├── app/jobs/media_process_job.go
├── providers/http/swagger/config.go
├── providers/http/swagger/template.go
├── providers/http/engine.go
├── providers/jwt/jwt.go
├── providers/postgres/config.go
└── providers/postgres/postgres.go
frontend/
├── superadmin/
│ ├── src/
│ └── package.json
└── portal/
├── src/
└── package.json
frontend/portal/
├── src/assets/main.css
├── src/main.js
├── src/layout/LayoutMain.vue
├── src/layout/LayoutUser.vue
├── src/layout/LayoutCreator.vue
├── src/layout/LayoutAuth.vue
├── src/components/TopNavbar.vue
── src/components/AppFooter.vue
```
**Structure Decision**: Web application; full repo lint remediation (backend + frontend).
**Structure Decision**: Apply color redesign through centralized tokens and shared shell/components to maximize consistency and minimize page-level edits.
## Plan Phases
1. **Security & correctness**: Address gosec issues (weak crypto, weak random, unsafe conversions) and errcheck/errorlint/wrapcheck failures.
2. **De-duplication & complexity**: Reduce dupl/gocognit/gocyclo/funlen by extracting helpers and simplifying large service methods (especially `services/super.go`).
3. **Style & formatting**: Resolve revive naming issues, line-length (lll), prealloc, nilerr, and other style violations.
4. **Frontend lint/build**: Resolve frontend lint/build issues for portal/superadmin.
5. **Verification**: Run backend and frontend lint/build/test commands until clean.
1. **Token Foundation**
- Define semantic color tokens for senior-light and high-contrast modes.
- Map tokens for Tailwind and global CSS usage.
2. **Shared Surface Application**
- Update shared layouts/navbar/footer from hardcoded slate/dark palette to semantic tokens.
- Remove distracting decorative backgrounds and improve contrast/focus cues.
3. **PrimeVue Alignment + Verification**
- Add global PrimeVue color overrides for button/input/panel/readability consistency.
- Run lint/build verification and prepare branch handoff for visual QA.
## Tasks
1. Capture baseline lint outputs (save `cd backend && make lint` output; run `npm -C frontend/superadmin run lint` / `npm -C frontend/portal run lint`) and group errors by category/file; establish remediation order (security → complexity → style).
2. Fix gosec issues: choose between (a) keep MD5 for non-security hashing with explicit `//nolint:gosec` justification, or (b) migrate to SHA-256 with any required backfill; switch weak random to crypto/rand where required; guard integer conversions.
3. Fix errcheck/errorlint/wrapcheck issues in providers and error handling.
4. Remove duplicated blocks (dupl) by extracting shared helper functions in `services/super.go` and `services/creator_report.go`.
5. Reduce high cognitive/cyclomatic complexity by helper extraction only; keep inputs/outputs and query semantics unchanged.
6. Address revive naming and lll formatting (split long lines, rename variables/types as needed).
7. Run backend verification (`cd backend && make lint`, `go test ./...`).
8. Run frontend lint/build (`npm -C frontend/superadmin run lint`, `npm -C frontend/superadmin run build`, `npm -C frontend/portal run lint`, `npm -C frontend/portal run build`). Review ESLint `--fix` diffs carefully.
9. Re-run all lint/build/test commands until clean.
1. Create and verify a dedicated feature branch for this redesign.
2. Rebuild `src/assets/main.css` with:
- semantic palette tokens,
- default + high-contrast variable sets,
- global base styles (body/link/focus),
- PrimeVue global color overrides.
3. Ensure `src/main.js` imports and theme setup remain compatible after token changes.
4. Refactor shared shells to semantic colors and reduced visual noise:
- `LayoutMain.vue`, `LayoutUser.vue`, `LayoutCreator.vue`, `LayoutAuth.vue`.
5. Refactor shared navigation/footer surfaces to semantic tokens:
- `TopNavbar.vue`, `AppFooter.vue`.
6. Run portal checks (`lint`, `build`) and resolve any regressions caused by this change set.
7. Provide branch name and reviewer instructions for visual validation.
## Dependencies
- Security fixes precede refactors to ensure safe baselines.
- De-duplication/complexity refactors should precede style fixes to avoid rework.
- Backend verification depends on remediation tasks; frontend verification depends on frontend lint/build tasks.
- Phase 2 depends on semantic token completion from Phase 1.
- Phase 3 depends on Phase 2 to verify final visual consistency and avoid rework.
- Reviewer validation depends on successful lint/build completion.
## Acceptance Criteria
- Backend lint passes with no errors (`cd backend && make lint`).
- Frontend lint/build passes (`npm -C frontend/superadmin run lint`, `npm -C frontend/superadmin run build`, `npm -C frontend/portal run lint`, `npm -C frontend/portal run build`).
- `go test ./...` passes (or failures are documented as pre-existing and approved).
- No generated files modified manually.
- No functional/API behavior changes observed during lint fixes.
- A new branch exists containing only portal color-system redesign changes.
- Portal shared shells/components use semantic color tokens instead of ad-hoc hardcoded palette where modified.
- High-contrast mode token set is available for accessibility-forward validation.
- `npm -C frontend/portal run lint` passes.
- `npm -C frontend/portal run build` passes.
- User can run portal and visually compare revised palette/readability across login, home shell, user shell, and creator shell.
## Risks
- Large refactors in `services/super.go` may inadvertently change behavior; must keep refactors minimal and covered by tests.
- Security fixes may require signature changes (e.g., hash algorithm changes); need careful review for backward compatibility.
- Volume of lint violations may require staged remediation; ensure each stage keeps lint green where possible.
- Broad visual changes may impact component contrast unexpectedly in edge views not directly edited.
- PrimeVue internal styles can override utility classes; requires targeted global overrides.
- Overly aggressive recolor could reduce brand recognition; keep primary brand hue stable while improving accessibility.
## Complexity Tracking

View File

@@ -2,6 +2,7 @@
@plugin "tailwindcss-animate";
:root {
/* Existing Primary Scale (Preserved) */
--color-primary-50: #eff6ff;
--color-primary-100: #dbeafe;
--color-primary-200: #bfdbfe;
@@ -13,6 +14,57 @@
--color-primary-800: #1e40af;
--color-primary-900: #1e3a8a;
--color-primary-950: #172554;
/* Senior-Friendly Semantic Base (Light Mode) */
/* Warm, low-glare backgrounds */
--color-bg-base: #f9fafb; /* gray-50 equivalent but semantic */
--color-bg-surface: #ffffff;
--color-bg-surface-highlight: #f3f4f6; /* gray-100 */
/* High contrast text */
--color-text-main: #0f172a; /* slate-900 */
--color-text-muted: #334155; /* slate-700 - Darker than typical muted for readability */
--color-text-inverted: #ffffff;
/* Borders */
--color-border-base: #cbd5e1; /* slate-300 - Higher contrast border */
--color-border-highlight: #94a3b8; /* slate-400 */
/* Status */
--color-status-success: #166534; /* green-800 for text readability */
--color-status-danger: #991b1b; /* red-800 */
/* PrimeVue Global Semantic Map */
--p-content-background: var(--color-bg-surface);
--p-content-color: var(--color-text-main);
--p-content-border-color: var(--color-border-base);
--p-primary-color: var(--color-primary-600);
--p-primary-contrast-color: #ffffff;
/* PrimeVue Form/Input adjustments */
--p-inputtext-background: var(--color-bg-surface);
--p-inputtext-color: var(--color-text-main);
--p-inputtext-border-color: var(--color-border-base);
}
/* High Contrast Mode for Seniors */
[data-theme='senior-high-contrast'] {
--color-bg-base: #ffffff;
--color-bg-surface: #ffffff;
--color-bg-surface-highlight: #ffff00; /* Yellow highlight for emphasis */
--color-text-main: #000000;
--color-text-muted: #000000;
--color-text-inverted: #ffff00; /* Yellow text on dark backgrounds */
--color-border-base: #000000;
--color-border-highlight: #000000;
--color-primary-500: #0000ee; /* Standard accessible link blue */
--color-primary-600: #0000ee;
/* Force borders to be visible */
--border-width-base: 2px;
}
@theme {
@@ -27,4 +79,37 @@
--color-primary-800: var(--color-primary-800);
--color-primary-900: var(--color-primary-900);
--color-primary-950: var(--color-primary-950);
/* Semantic Map */
--color-base: var(--color-bg-base);
--color-surface: var(--color-bg-surface);
--color-surface-highlight: var(--color-bg-surface-highlight);
--color-content: var(--color-text-main);
--color-muted: var(--color-text-muted);
--color-inverted: var(--color-text-inverted);
--color-line: var(--color-border-base);
--color-line-highlight: var(--color-border-highlight);
}
/* Global Senior Base Styles */
body {
background-color: var(--color-bg-base);
color: var(--color-text-main);
font-size: 18px; /* Slightly larger base font size */
line-height: 1.6;
}
/* Improve focus visibility */
:focus-visible {
outline: 3px solid var(--color-primary-600);
outline-offset: 2px;
}
a {
text-decoration-thickness: 1px;
}
a:hover {
text-decoration: underline;
}

View File

@@ -1,16 +1,16 @@
<template>
<footer class="bg-slate-900 text-slate-400 mt-auto">
<footer class="bg-surface-highlight text-muted mt-auto border-t border-line">
<div class="mx-auto max-w-screen-xl py-12">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<!-- Brand -->
<div class="col-span-1">
<div class="flex items-center gap-2 mb-4">
<div
class="w-8 h-8 bg-white/10 rounded-lg flex items-center justify-center text-white font-bold text-xl"
class="w-8 h-8 bg-primary-600 rounded-lg flex items-center justify-center text-white font-bold text-xl"
>
Q
</div>
<span class="text-xl font-bold text-white">Quyun</span>
<span class="text-xl font-bold text-content">Quyun</span>
</div>
<p class="text-sm leading-relaxed mb-6">
专业的租户管理与内容交付平台连接创作者与用户探索内容的无限可能
@@ -18,17 +18,17 @@
<div class="flex gap-4">
<a
href="#"
class="w-8 h-8 rounded-full bg-white/5 flex items-center justify-center hover:bg-white/20 hover:text-white transition-all"
class="w-8 h-8 rounded-full bg-surface border border-line flex items-center justify-center hover:bg-primary-50 hover:text-primary-600 transition-all"
><i class="pi pi-twitter"></i
></a>
<a
href="#"
class="w-8 h-8 rounded-full bg-white/5 flex items-center justify-center hover:bg-white/20 hover:text-white transition-all"
class="w-8 h-8 rounded-full bg-surface border border-line flex items-center justify-center hover:bg-primary-50 hover:text-primary-600 transition-all"
><i class="pi pi-github"></i
></a>
<a
href="#"
class="w-8 h-8 rounded-full bg-white/5 flex items-center justify-center hover:bg-white/20 hover:text-white transition-all"
class="w-8 h-8 rounded-full bg-surface border border-line flex items-center justify-center hover:bg-primary-50 hover:text-primary-600 transition-all"
><i class="pi pi-discord"></i
></a>
</div>
@@ -36,25 +36,25 @@
<!-- Links -->
<div>
<h3 class="text-white font-bold mb-4">关于我们</h3>
<h3 class="text-content font-bold mb-4">关于我们</h3>
<ul class="space-y-3 text-sm">
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>平台介绍</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>加入我们</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>联系方式</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>合作伙伴</a
>
</li>
@@ -62,25 +62,25 @@
</div>
<div>
<h3 class="text-white font-bold mb-4">帮助中心</h3>
<h3 class="text-content font-bold mb-4">帮助中心</h3>
<ul class="space-y-3 text-sm">
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>用户指南</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>创作者手册</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>常见问题</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>反馈建议</a
>
</li>
@@ -88,25 +88,25 @@
</div>
<div>
<h3 class="text-white font-bold mb-4">法律条款</h3>
<h3 class="text-content font-bold mb-4">法律条款</h3>
<ul class="space-y-3 text-sm">
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>用户协议</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>隐私政策</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>知识产权</a
>
</li>
<li>
<a href="#" class="hover:text-white transition-colors"
<a href="#" class="hover:text-primary-600 transition-colors"
>社区规范</a
>
</li>
@@ -115,7 +115,7 @@
</div>
<div
class="border-t border-slate-800 mt-12 pt-8 flex flex-col md:flex-row justify-between items-center text-xs"
class="border-t border-line mt-12 pt-8 flex flex-col md:flex-row justify-between items-center text-xs"
>
<p>© 2025 Quyun Platform. All rights reserved.</p>
<p class="mt-2 md:mt-0">

View File

@@ -38,7 +38,9 @@ const logout = () => {
</script>
<template>
<nav class="fixed top-0 w-full z-50 bg-white border-b border-slate-200 h-16">
<nav
class="fixed top-0 w-full z-50 bg-surface border-b border-line h-16 text-content"
>
<div
class="mx-auto max-w-screen-xl h-full flex items-center justify-between"
>
@@ -49,7 +51,7 @@ const logout = () => {
>
Q
</div>
<span class="text-xl font-bold text-slate-900 hidden sm:block"
<span class="text-xl font-bold text-content hidden sm:block"
>Quyun</span
>
</router-link>
@@ -58,19 +60,19 @@ const logout = () => {
<div class="hidden md:flex items-center space-x-8">
<router-link
:to="tenantRoute('/')"
class="text-slate-600 font-medium hover:text-primary-600"
class="text-muted font-medium hover:text-primary-600"
active-class="text-primary-600"
>首页</router-link
>
<router-link
:to="tenantRoute('/explore')"
class="text-slate-600 font-medium hover:text-primary-600"
class="text-muted font-medium hover:text-primary-600"
active-class="text-primary-600"
>发现</router-link
>
<router-link
:to="tenantRoute('/topics')"
class="text-slate-600 font-medium hover:text-primary-600"
class="text-muted font-medium hover:text-primary-600"
active-class="text-primary-600"
>专题</router-link
>
@@ -80,12 +82,12 @@ const logout = () => {
<div class="hidden sm:flex flex-1 max-w-md mx-8">
<div class="relative w-full">
<i
class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-slate-400"
class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-muted"
></i>
<input
type="text"
placeholder="搜索感兴趣的内容..."
class="w-full h-10 pl-10 pr-4 rounded-full bg-slate-100 border-none focus:bg-white focus:ring-2 focus:ring-primary-100 text-sm transition-all"
class="w-full h-10 pl-10 pr-4 rounded-full bg-surface-highlight border border-transparent focus:border-primary-300 focus:bg-surface focus:ring-2 focus:ring-primary-100 text-sm transition-all text-content placeholder:text-muted"
/>
</div>
</div>
@@ -96,18 +98,18 @@ const logout = () => {
<!-- Notification -->
<router-link
:to="tenantRoute('/me/notifications')"
class="relative w-10 h-10 flex items-center justify-center rounded-full hover:bg-slate-50 text-slate-600"
class="relative w-10 h-10 flex items-center justify-center rounded-full hover:bg-surface-highlight text-muted"
>
<i class="pi pi-bell text-xl"></i>
<span
class="absolute top-2 right-2 w-2 h-2 bg-red-500 rounded-full border border-white"
class="absolute top-2 right-2 w-2 h-2 bg-red-600 rounded-full border border-surface"
></span>
</router-link>
<!-- Creator Entry -->
<router-link
:to="tenantRoute('/creator/apply')"
class="hidden sm:flex items-center gap-1 px-3 py-1.5 text-sm font-medium text-slate-600 hover:bg-slate-50 rounded-lg border border-slate-200"
class="hidden sm:flex items-center gap-1 px-3 py-1.5 text-sm font-medium text-muted hover:bg-surface-highlight rounded-lg border border-line"
>
<i class="pi pi-pencil"></i>
<span>创作</span>
@@ -116,7 +118,7 @@ const logout = () => {
<!-- Avatar Dropdown -->
<div class="relative group h-full flex items-center">
<button
class="w-9 h-9 rounded-full overflow-hidden border border-slate-200 focus:ring-2 ring-primary-100"
class="w-9 h-9 rounded-full overflow-hidden border border-line focus:ring-2 ring-primary-100"
>
<img
:src="
@@ -132,27 +134,27 @@ const logout = () => {
class="absolute right-0 top-full pt-2 w-48 hidden group-hover:block"
>
<div
class="bg-white rounded-xl shadow-lg border border-slate-100 py-1"
class="bg-surface rounded-xl shadow-lg border border-line py-1"
>
<div class="px-4 py-3 border-b border-slate-50">
<p class="text-sm font-bold text-slate-900">
<div class="px-4 py-3 border-b border-line">
<p class="text-sm font-bold text-content">
{{ user.nickname }}
</p>
<p class="text-xs text-slate-500 truncate">
<p class="text-xs text-muted truncate">
{{ user.phone }}
</p>
</div>
<router-link
:to="tenantRoute('/me')"
class="block px-4 py-2 text-sm text-slate-700 hover:bg-slate-50"
class="block px-4 py-2 text-sm text-content hover:bg-surface-highlight"
>个人中心</router-link
>
<router-link
:to="tenantRoute('/creator')"
class="block px-4 py-2 text-sm text-slate-700 hover:bg-slate-50"
class="block px-4 py-2 text-sm text-content hover:bg-surface-highlight"
>创作者中心</router-link
>
<div class="border-t border-slate-50 mt-1"></div>
<div class="border-t border-line mt-1"></div>
<button
@click="logout"
class="block w-full text-left px-4 py-2 text-sm text-red-600 hover:bg-red-50"
@@ -174,7 +176,7 @@ const logout = () => {
<!-- Mobile Menu Button -->
<button
class="md:hidden w-10 h-10 flex items-center justify-center text-slate-600"
class="md:hidden w-10 h-10 flex items-center justify-center text-muted"
>
<i class="pi pi-bars text-xl"></i>
</button>

View File

@@ -1,5 +1,7 @@
<template>
<div class="min-h-screen bg-slate-50 flex items-center justify-center p-4">
<div
class="min-h-screen bg-base text-content flex items-center justify-center p-4"
>
<router-view />
</div>
</template>

View File

@@ -15,7 +15,7 @@ const isFullWidth = computed(() => {
<template>
<div
class="flex flex-col bg-slate-50"
class="flex flex-col bg-base text-content"
:class="isFullWidth ? 'h-screen overflow-hidden' : 'min-h-screen'"
>
<TopNavbar v-if="!isFullWidth" />
@@ -33,21 +33,21 @@ const isFullWidth = computed(() => {
v-if="!isFullWidth"
>
<div
class="bg-slate-900 rounded-2xl shadow-sm overflow-hidden sticky top-24 text-slate-300 min-h-[600px] flex flex-col"
class="bg-surface rounded-2xl shadow-sm overflow-hidden sticky top-24 text-muted min-h-[600px] flex flex-col border border-line"
>
<!-- Header -->
<div class="p-6 border-b border-slate-800">
<div class="p-6 border-b border-line">
<div class="flex items-center gap-3">
<div
class="w-10 h-10 bg-gradient-to-br from-primary-500 to-primary-700 rounded-lg flex items-center justify-center text-white font-bold text-lg shadow-lg"
class="w-10 h-10 bg-primary-600 rounded-lg flex items-center justify-center text-white font-bold text-lg shadow-lg"
>
<i class="pi pi-palette"></i>
</div>
<div>
<div class="font-bold text-white leading-tight">
<div class="font-bold text-content leading-tight">
创作者中心
</div>
<div class="text-xs text-slate-500 mt-1">Creator Studio</div>
<div class="text-xs text-muted mt-1">Creator Studio</div>
</div>
</div>
</div>
@@ -57,7 +57,7 @@ const isFullWidth = computed(() => {
<router-link
:to="tenantRoute('/creator')"
exact-active-class="bg-primary-600 text-white shadow-md shadow-primary-900/20"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-slate-800 hover:text-white transition-all group"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-surface-highlight hover:text-content transition-all group"
>
<i
class="pi pi-th-large text-lg group-hover:scale-110 transition-transform"
@@ -66,7 +66,7 @@ const isFullWidth = computed(() => {
</router-link>
<div
class="px-4 py-2 text-xs font-bold text-slate-500 uppercase tracking-wider mt-4"
class="px-4 py-2 text-xs font-bold text-muted uppercase tracking-wider mt-4"
>
内容与交易
</div>
@@ -74,7 +74,7 @@ const isFullWidth = computed(() => {
<router-link
:to="tenantRoute('/creator/contents')"
active-class="bg-primary-600 text-white shadow-md shadow-primary-900/20"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-slate-800 hover:text-white transition-all group"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-surface-highlight hover:text-content transition-all group"
>
<i
class="pi pi-file-edit text-lg group-hover:scale-110 transition-transform"
@@ -84,7 +84,7 @@ const isFullWidth = computed(() => {
<router-link
:to="tenantRoute('/creator/orders')"
active-class="bg-primary-600 text-white shadow-md shadow-primary-900/20"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-slate-800 hover:text-white transition-all group"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-surface-highlight hover:text-content transition-all group"
>
<i
class="pi pi-shopping-cart text-lg group-hover:scale-110 transition-transform"
@@ -94,7 +94,7 @@ const isFullWidth = computed(() => {
<router-link
:to="tenantRoute('/creator/coupons')"
active-class="bg-primary-600 text-white shadow-md shadow-primary-900/20"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-slate-800 hover:text-white transition-all group"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-surface-highlight hover:text-content transition-all group"
>
<i
class="pi pi-ticket text-lg group-hover:scale-110 transition-transform"
@@ -103,7 +103,7 @@ const isFullWidth = computed(() => {
</router-link>
<div
class="px-4 py-2 text-xs font-bold text-slate-500 uppercase tracking-wider mt-4"
class="px-4 py-2 text-xs font-bold text-muted uppercase tracking-wider mt-4"
>
配置
</div>
@@ -111,7 +111,7 @@ const isFullWidth = computed(() => {
<router-link
:to="tenantRoute('/creator/members')"
active-class="bg-primary-600 text-white shadow-md shadow-primary-900/20"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-slate-800 hover:text-white transition-all group"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-surface-highlight hover:text-content transition-all group"
>
<i
class="pi pi-users text-lg group-hover:scale-110 transition-transform"
@@ -121,7 +121,7 @@ const isFullWidth = computed(() => {
<router-link
:to="tenantRoute('/creator/settings')"
active-class="bg-primary-600 text-white shadow-md shadow-primary-900/20"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-slate-800 hover:text-white transition-all group"
class="flex items-center gap-3 px-4 py-3 rounded-lg hover:bg-surface-highlight hover:text-content transition-all group"
>
<i
class="pi pi-cog text-lg group-hover:scale-110 transition-transform"
@@ -131,10 +131,10 @@ const isFullWidth = computed(() => {
</nav>
<!-- Footer Link -->
<div class="p-4 border-t border-slate-800">
<div class="p-4 border-t border-line">
<router-link
:to="tenantRoute('/')"
class="flex items-center gap-2 px-4 py-2 text-sm text-slate-400 hover:text-white transition-colors"
class="flex items-center gap-2 px-4 py-2 text-sm text-muted hover:text-content transition-colors"
>
<i class="pi pi-external-link"></i> 预览我的主页
</router-link>

View File

@@ -4,15 +4,9 @@ import AppFooter from "../components/AppFooter.vue";
</script>
<template>
<div class="min-h-screen flex flex-col bg-slate-50 relative overflow-hidden">
<!-- Background Decor Blobs -->
<div
class="fixed top-[-10%] right-[-10%] w-[40%] h-[40%] bg-blue-100/40 rounded-full blur-[120px] -z-0"
></div>
<div
class="fixed bottom-[-10%] left-[-10%] w-[30%] h-[40%] bg-purple-50/50 rounded-full blur-[100px] -z-0"
></div>
<div
class="min-h-screen flex flex-col bg-base text-content relative overflow-hidden"
>
<TopNavbar class="relative z-10" />
<main class="flex-grow pt-16 relative z-10">
<router-view />

View File

@@ -11,30 +11,30 @@ const tenantRoute = (path) => tenantPath(path, route);
</script>
<template>
<div class="min-h-screen flex flex-col bg-slate-50">
<div class="min-h-screen flex flex-col bg-base text-content">
<TopNavbar />
<main class="flex-grow pt-16">
<div class="mx-auto max-w-screen-xl py-8 flex gap-8">
<!-- Sidebar -->
<aside class="w-[280px] flex-shrink-0 hidden lg:block">
<div
class="bg-white rounded-2xl shadow-sm border border-slate-100 overflow-hidden sticky top-24"
class="bg-surface rounded-2xl shadow-sm border border-line overflow-hidden sticky top-24"
>
<!-- User Brief -->
<div class="p-6 border-b border-slate-100 bg-slate-50/50">
<div class="p-6 border-b border-line bg-surface-highlight">
<div class="flex items-center gap-4">
<img
:src="
user.avatar ||
`https://api.dicebear.com/7.x/avataaars/svg?seed=${user.id || 'default'}`
"
class="w-12 h-12 rounded-full border-2 border-white shadow-sm"
class="w-12 h-12 rounded-full border-2 border-surface shadow-sm"
/>
<div class="overflow-hidden">
<div class="font-bold text-slate-900 truncate">
<div class="font-bold text-content truncate">
{{ user.nickname || "用户" }}
</div>
<div class="text-xs text-slate-500">ID: {{ user.id }}</div>
<div class="text-xs text-muted">ID: {{ user.id }}</div>
</div>
</div>
</div>
@@ -44,7 +44,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me')"
exact-active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-home text-lg"></i>
<span>概览</span>
@@ -52,7 +52,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/orders')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-shopping-bag text-lg"></i>
<span>我的订单</span>
@@ -60,7 +60,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/wallet')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-wallet text-lg"></i>
<span>我的钱包</span>
@@ -68,7 +68,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/coupons')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-ticket text-lg"></i>
<span>我的优惠券</span>
@@ -76,7 +76,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/library')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-book text-lg"></i>
<span>已购内容</span>
@@ -84,7 +84,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/favorites')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-heart text-lg"></i>
<span>我的收藏</span>
@@ -92,7 +92,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/likes')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-thumbs-up text-lg"></i>
<span>我的点赞</span>
@@ -100,16 +100,16 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/notifications')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-bell text-lg"></i>
<span>消息中心</span>
</router-link>
<div class="my-2 border-t border-slate-100"></div>
<div class="my-2 border-t border-line"></div>
<router-link
:to="tenantRoute('/me/profile')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-user text-lg"></i>
<span>个人资料</span>
@@ -117,7 +117,7 @@ const tenantRoute = (path) => tenantPath(path, route);
<router-link
:to="tenantRoute('/me/security')"
active-class="bg-primary-50 text-primary-600 font-semibold"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-slate-600 hover:bg-slate-50 transition-colors"
class="flex items-center gap-3 px-4 py-3 rounded-lg text-muted hover:bg-surface-highlight hover:text-content transition-colors"
>
<i class="pi pi-shield text-lg"></i>
<span>账号安全</span>

View File

@@ -21,7 +21,7 @@ app.use(PrimeVue, {
preset: Aura,
options: {
prefix: "p",
darkModeSelector: ".my-app-dark",
darkModeSelector: "[data-theme='senior-high-contrast']",
cssLayer: false,
},
},

View File

@@ -11,7 +11,7 @@ export default defineConfig({
strictPort: true,
proxy: {
"/v1": {
target: "http://localhost:8080",
target: "http://localhost:18080",
changeOrigin: true,
},
},

View File

@@ -16,11 +16,11 @@ export default defineConfig({
host: '0.0.0.0',
proxy: {
'/super/v1': {
target: 'http://localhost:8080',
target: 'http://localhost:18080',
changeOrigin: true
},
'/v1': {
target: 'http://localhost:8080',
target: 'http://localhost:18080',
changeOrigin: true
}
}