@@ -20,7 +20,18 @@
|
|||||||
"usedAt": 1776163421500,
|
"usedAt": 1776163421500,
|
||||||
"industryId": "all"
|
"industryId": "all"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"95e0ae51ed494505a477abd8137eaf2b": [
|
||||||
|
{
|
||||||
|
"expertId": "BackendArchitect",
|
||||||
|
"name": "Joy",
|
||||||
|
"profession": "后端架构师",
|
||||||
|
"avatarUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/avatars/02-Engineering/BackendArchitect/BackendArchitect.png",
|
||||||
|
"promptUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/experts/02-Engineering/BackendArchitect/BackendArchitect_zh.md",
|
||||||
|
"usedAt": 1776172649908,
|
||||||
|
"industryId": "all"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lastUpdated": 1776167527349
|
"lastUpdated": 1776172717113
|
||||||
}
|
}
|
||||||
+768
@@ -0,0 +1,768 @@
|
|||||||
|
# OPS 后端 API 使用手册
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
- **基础URL**: `/api`
|
||||||
|
- **请求格式**: JSON Body(通过 `userCookieValue` 传cookie,`data` 传业务数据)
|
||||||
|
- **认证方式**: Cookie-based authentication
|
||||||
|
- **响应格式**: JSON
|
||||||
|
|
||||||
|
## 通用请求格式
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie字符串",
|
||||||
|
"data": {
|
||||||
|
// 业务参数
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 通用响应格式
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"err_code": 0,
|
||||||
|
"err_msg": "apiOK",
|
||||||
|
"return": {
|
||||||
|
// 响应数据
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 错误码
|
||||||
|
|
||||||
|
| err_code | err_msg | 说明 |
|
||||||
|
|----------|---------|------|
|
||||||
|
| 0 | apiOK | 成功 |
|
||||||
|
| -1 | apiErr | 服务器错误 |
|
||||||
|
| -2 | postErr | POST请求错误 |
|
||||||
|
| -3 | jsonErr | JSON解析错误 |
|
||||||
|
| -31 | jsonErr_1 | 数据格式错误 |
|
||||||
|
| -4 | userNameDup | 用户名已存在 |
|
||||||
|
| -41 | userNameNoFund | 用户不存在 |
|
||||||
|
| -42 | userPassIncorrect | 密码错误 |
|
||||||
|
| -43 | userEmailFormatError | 邮箱格式错误 |
|
||||||
|
| -44 | userCookieError | Cookie错误/未登录 |
|
||||||
|
| -51 | file_mime_err | 文件类型不允许 |
|
||||||
|
| -52 | file_size_err | 文件大小超限 |
|
||||||
|
| -53 | file_name_err | 文件名错误 |
|
||||||
|
| -54 | file_get_err | 文件获取错误 |
|
||||||
|
| -55 | file_hash_err | 文件哈希计算错误 |
|
||||||
|
| -56 | file_save_err | 文件保存失败 |
|
||||||
|
| -57 | file_not_found | 文件不存在 |
|
||||||
|
| -58 | file_part_err | 文件参数错误 |
|
||||||
|
| -61 | schedule_event_not_find | 日程不存在 |
|
||||||
|
| -62 | schedule_permission_denied | 无权限操作 |
|
||||||
|
| -1001 | order_not_found | 订单不存在 |
|
||||||
|
| -1002 | invalid_status | 无效的订单状态 |
|
||||||
|
| -1003 | status_no_change | 状态未变化 |
|
||||||
|
| -1004 | no_permission | 无权限 |
|
||||||
|
| -1005 | photo_hash_invalid | 图片哈希无效 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 用户模块 `/api/users`
|
||||||
|
|
||||||
|
### 用户登录
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/users/login
|
||||||
|
```
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "",
|
||||||
|
"data": {
|
||||||
|
"username": "用户名",
|
||||||
|
"password": "密码",
|
||||||
|
"remember": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cookie": {
|
||||||
|
"ID": 1,
|
||||||
|
"Value": "32位随机字符串",
|
||||||
|
"ExpiresAt": "过期时间"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 用户注册
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/users/register
|
||||||
|
```
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "",
|
||||||
|
"data": {
|
||||||
|
"username": "用户名",
|
||||||
|
"useremail": "邮箱",
|
||||||
|
"userpass": "密码"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 获取当前用户信息
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/users/getinfo
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"user": {
|
||||||
|
"ID": 1,
|
||||||
|
"Name": "用户名",
|
||||||
|
"Email": "邮箱"
|
||||||
|
},
|
||||||
|
"userInfo": {
|
||||||
|
"UserID": 1,
|
||||||
|
"Username": "显示名",
|
||||||
|
"FirstName": "名",
|
||||||
|
"Birthdate": "生日",
|
||||||
|
"AvatarPath": "头像路径",
|
||||||
|
"Gender": "M/F/U",
|
||||||
|
"Region": "地区",
|
||||||
|
"Language": "语言"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 获取指定用户信息
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/users/getuserinfo/:id
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userinfo": {
|
||||||
|
"UserID": 1,
|
||||||
|
"Username": "显示名"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 修改密码
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/users/changePassword
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"oldpass": "旧密码",
|
||||||
|
"newpass": "新密码"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 修改邮箱
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/users/changeEmail
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"newemail": "新邮箱"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 更新用户信息
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/users/updateInfo
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"username": "用户名",
|
||||||
|
"remark": "备注(作为FirstName)",
|
||||||
|
"birthday": "2006-01-02"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 上传头像
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/users/updateAvatar
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求格式:** `multipart/form-data`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| cookie | string | 认证cookie |
|
||||||
|
| file | file | 图片文件(512字节-1MB) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 测试接口
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/users/test
|
||||||
|
POST /api/users/test
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 订单模块 `/api/purchase`
|
||||||
|
|
||||||
|
### 获取订单列表
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/purchase/getorders
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"search": "搜索关键词(可选)",
|
||||||
|
"status": "pending/ordered/arrived/received/lost/returned(可选)",
|
||||||
|
"entries": 20,
|
||||||
|
"page": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"all_count": 100,
|
||||||
|
"all_orders": [
|
||||||
|
{
|
||||||
|
"ID": 1,
|
||||||
|
"UserID": 1,
|
||||||
|
"Title": "订单标题",
|
||||||
|
"Remark": "备注",
|
||||||
|
"Link": "链接",
|
||||||
|
"Styles": "样式",
|
||||||
|
"OrderStatus": "pending",
|
||||||
|
"CreatedAt": "创建时间",
|
||||||
|
"UpdatedAt": "更新时间"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 获取单个订单详情
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/purchase/getorder
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"order": {
|
||||||
|
"ID": 1,
|
||||||
|
"UserID": 1,
|
||||||
|
"Title": "订单标题",
|
||||||
|
"Remark": "备注",
|
||||||
|
"Link": "链接",
|
||||||
|
"Styles": "样式",
|
||||||
|
"OrderStatus": "pending"
|
||||||
|
},
|
||||||
|
"canModify": true,
|
||||||
|
"costs": [
|
||||||
|
{
|
||||||
|
"ID": 1,
|
||||||
|
"OrderID": 1,
|
||||||
|
"Price": 1000,
|
||||||
|
"Quantity": 2,
|
||||||
|
"CurrencyType": 1,
|
||||||
|
"CostType": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"photos": [
|
||||||
|
{
|
||||||
|
"ID": 1,
|
||||||
|
"Name": "图片名",
|
||||||
|
"Sha256": "哈希值"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commits": [
|
||||||
|
{
|
||||||
|
"ID": 1,
|
||||||
|
"OrderID": 1,
|
||||||
|
"UserID": 1,
|
||||||
|
"Action": "create_status",
|
||||||
|
"Status": "pending",
|
||||||
|
"OldStatus": "",
|
||||||
|
"Comment": "状态变更为: pending",
|
||||||
|
"Photos": [],
|
||||||
|
"CreatedAt": "时间"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 创建订单
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/purchase/addorder
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"title": "订单标题(必填)",
|
||||||
|
"remark": "备注",
|
||||||
|
"link": "链接",
|
||||||
|
"styles": "样式",
|
||||||
|
"costs": [
|
||||||
|
{
|
||||||
|
"cost": 1000,
|
||||||
|
"costt": 2000,
|
||||||
|
"currencytype": 1,
|
||||||
|
"int": 2,
|
||||||
|
"type": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"photos": ["图片sha256哈希"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**字段说明:**
|
||||||
|
- `cost`: 费用(分)
|
||||||
|
- `currencytype`: 货币类型 (1-CNY, 2-MOP, 3-HKD, 4-USD)
|
||||||
|
- `int`: 数量
|
||||||
|
- `type`: 费用类型 (1-单价, 2-运费)
|
||||||
|
- `photos`: 图片SHA256哈希数组
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 更新订单
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/purchase/updateorder
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证** (创建者或管理员)
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"title": "订单标题",
|
||||||
|
"remark": "备注",
|
||||||
|
"link": "链接",
|
||||||
|
"styles": "样式",
|
||||||
|
"costs": [
|
||||||
|
{
|
||||||
|
"cost": 1000,
|
||||||
|
"currencytype": 1,
|
||||||
|
"int": 2,
|
||||||
|
"type": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"photos": ["哈希"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 更新订单状态
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/purchase/updatestatus
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证** (创建者或管理员)
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"status": "ordered",
|
||||||
|
"comment": "备注",
|
||||||
|
"photos": ["变更图片哈希"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**状态值:**
|
||||||
|
| 值 | 说明 |
|
||||||
|
|----|------|
|
||||||
|
| pending | 待处理 |
|
||||||
|
| ordered | 已下单 |
|
||||||
|
| arrived | 已到达 |
|
||||||
|
| received | 已收件 |
|
||||||
|
| lost | 丢件 |
|
||||||
|
| returned | 退件 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 删除订单
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/purchase/deleteorder
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证** (创建者或管理员)
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 获取订单统计
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/purchase/getordercount
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pending": 10,
|
||||||
|
"ordered": 5,
|
||||||
|
"arrived": 3,
|
||||||
|
"received": 20,
|
||||||
|
"lost": 1,
|
||||||
|
"returned": 2,
|
||||||
|
"total": 41
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 日程模块 `/api/schedule`
|
||||||
|
|
||||||
|
### 获取日程列表
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/schedule/getevents
|
||||||
|
```
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"start": "2026-01-01",
|
||||||
|
"end": "2026-12-31"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"ID": 1,
|
||||||
|
"UserID": 1,
|
||||||
|
"Title": "日程标题",
|
||||||
|
"StartDate": "2026-01-01",
|
||||||
|
"EndDate": "2026-01-01",
|
||||||
|
"BgColor": "#3788d9",
|
||||||
|
"Remark": "备注",
|
||||||
|
"edit": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 创建日程
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/schedule/addevent
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"id": 0,
|
||||||
|
"title": "日程标题",
|
||||||
|
"start": "2026-01-01",
|
||||||
|
"end": "2026-01-01",
|
||||||
|
"color": "#3788d9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 编辑日程
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/schedule/editevent
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证** (创建者或管理员)
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"title": "日程标题",
|
||||||
|
"start": "2026-01-01",
|
||||||
|
"end": "2026-01-01",
|
||||||
|
"color": "#3788d9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 删除日程
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/schedule/deleevent
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证** (创建者或管理员)
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"userCookieValue": "cookie",
|
||||||
|
"data": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 文件模块 `/api/files`
|
||||||
|
|
||||||
|
### 上传图片
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/files/upload/image
|
||||||
|
```
|
||||||
|
|
||||||
|
**需要认证**
|
||||||
|
|
||||||
|
**请求格式:** `multipart/form-data`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| cookie | string | 认证cookie |
|
||||||
|
| file | file | 图片文件 |
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"download": "/api/files/download/文件哈希",
|
||||||
|
"get": "/api/files/get/文件哈希",
|
||||||
|
"hash": "sha256哈希值"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 获取/下载文件
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/files/:mode/:hash
|
||||||
|
|
||||||
|
mode: get - 获取(预览)
|
||||||
|
mode: download - 下载
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数说明:**
|
||||||
|
- `get`: 返回文件预览
|
||||||
|
- `download`: 返回文件下载
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 静态资源 `/api/static`
|
||||||
|
|
||||||
|
### 获取头像
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/static/avatar/:filename
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 数据模型
|
||||||
|
|
||||||
|
### TabUser_ (用户表)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| ID | uint | 主键 |
|
||||||
|
| Name | string | 用户名(唯一) |
|
||||||
|
| Email | string | 邮箱 |
|
||||||
|
| Pass | string | 密码(哈希) |
|
||||||
|
| Salt | string | 盐值 |
|
||||||
|
| Type | string | 用户类型 |
|
||||||
|
| Date | datetime | 创建时间 |
|
||||||
|
|
||||||
|
### TabUserInfo_ (用户信息表)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| ID | uint | 主键 |
|
||||||
|
| UserID | uint | 用户ID(唯一) |
|
||||||
|
| Username | string | 显示名 |
|
||||||
|
| FirstName | string | 名 |
|
||||||
|
| Birthdate | datetime | 生日 |
|
||||||
|
| Gender | char | 性别 M/F/U |
|
||||||
|
| AvatarPath | string | 头像路径 |
|
||||||
|
| Region | string | 地区 |
|
||||||
|
| Language | string | 语言 |
|
||||||
|
|
||||||
|
### TabPurchaseOrder (订单表)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| ID | uint | 主键 |
|
||||||
|
| UserID | uint | 创建者ID |
|
||||||
|
| Title | string | 标题 |
|
||||||
|
| Remark | text | 备注 |
|
||||||
|
| Link | string | 链接 |
|
||||||
|
| Styles | text | 样式 |
|
||||||
|
| OrderStatus | string | 状态 |
|
||||||
|
| CreatedAt | datetime | 创建时间 |
|
||||||
|
| UpdatedAt | datetime | 更新时间 |
|
||||||
|
|
||||||
|
### TabPurchaseCosts (订单费用表)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| ID | uint | 主键 |
|
||||||
|
| OrderID | uint | 订单ID |
|
||||||
|
| UserID | uint | 用户ID |
|
||||||
|
| Price | int | 单价(分) |
|
||||||
|
| Quantity | int | 数量 |
|
||||||
|
| CurrencyType | int | 货币类型 |
|
||||||
|
| CostType | int | 费用类型 |
|
||||||
|
|
||||||
|
### TabSchedule (日程表)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| ID | uint | 主键 |
|
||||||
|
| UserID | uint | 创建者ID |
|
||||||
|
| Title | string | 标题 |
|
||||||
|
| StartDate | string | 开始日期 |
|
||||||
|
| EndDate | string | 结束日期 |
|
||||||
|
| BgColor | string | 背景颜色 |
|
||||||
|
| Remark | text | 备注 |
|
||||||
|
|
||||||
|
### TabFileInfo_ (文件表)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| ID | uint | 主键 |
|
||||||
|
| Name | string | 文件名 |
|
||||||
|
| Size | int64 | 文件大小 |
|
||||||
|
| Path | string | 存储路径 |
|
||||||
|
| Sha256 | string | 文件哈希 |
|
||||||
|
| Mime | string | MIME类型 |
|
||||||
|
| Type | string | 文件类型 |
|
||||||
|
| UserID | uint | 上传用户ID |
|
||||||
|
| Date | datetime | 上传时间 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 权限说明
|
||||||
|
|
||||||
|
### 订单权限
|
||||||
|
- 创建者:可修改/删除自己的订单
|
||||||
|
- purchase_admin 用户组成员:可修改/删除所有订单
|
||||||
|
|
||||||
|
### 日程权限
|
||||||
|
- 创建者:可修改/删除自己的日程
|
||||||
|
- schedule_admin 用户组成员:可修改/删除所有日程
|
||||||
@@ -13,5 +13,5 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lastUpdated": 1776172462417
|
"lastUpdated": 1776173744465
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ export default {
|
|||||||
// tabBar
|
// tabBar
|
||||||
tabBar: {
|
tabBar: {
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
|
user: 'Profile',
|
||||||
settings: 'Settings',
|
settings: 'Settings',
|
||||||
},
|
},
|
||||||
// 首页
|
// 首页
|
||||||
@@ -109,5 +110,17 @@ export default {
|
|||||||
failed: 'Operation failed',
|
failed: 'Operation failed',
|
||||||
back: 'Back',
|
back: 'Back',
|
||||||
networkError: 'Network request failed, please check your connection',
|
networkError: 'Network request failed, please check your connection',
|
||||||
|
},
|
||||||
|
// 用户页
|
||||||
|
user: {
|
||||||
|
profile: 'Profile',
|
||||||
|
username: 'Username',
|
||||||
|
firstName: 'Name',
|
||||||
|
birthday: 'Birthday',
|
||||||
|
gender: 'Gender',
|
||||||
|
region: 'Region',
|
||||||
|
male: 'Male',
|
||||||
|
female: 'Female',
|
||||||
|
unknown: 'Unknown',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n, useI18n as _useI18n } from 'vue-i18n'
|
||||||
import zh from './zh.js'
|
import zh from './zh.js'
|
||||||
import en from './en.js'
|
import en from './en.js'
|
||||||
|
|
||||||
|
// 兼容 uni-app 的 useI18n 导出
|
||||||
|
export const useI18n = _useI18n
|
||||||
|
|
||||||
// 获取本地语言设置,默认中文
|
// 获取本地语言设置,默认中文
|
||||||
function getLocale() {
|
function getLocale() {
|
||||||
// 从本地存储读取
|
// 从本地存储读取
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export default {
|
|||||||
// tabBar
|
// tabBar
|
||||||
tabBar: {
|
tabBar: {
|
||||||
home: '首页',
|
home: '首页',
|
||||||
|
user: '我的',
|
||||||
settings: '设置',
|
settings: '设置',
|
||||||
},
|
},
|
||||||
// 首页
|
// 首页
|
||||||
@@ -109,5 +110,17 @@ export default {
|
|||||||
failed: '操作失败',
|
failed: '操作失败',
|
||||||
back: '返回',
|
back: '返回',
|
||||||
networkError: '网络请求失败,请检查网络',
|
networkError: '网络请求失败,请检查网络',
|
||||||
|
},
|
||||||
|
// 用户页
|
||||||
|
user: {
|
||||||
|
profile: '个人资料',
|
||||||
|
username: '用户名',
|
||||||
|
firstName: '姓名',
|
||||||
|
birthday: '生日',
|
||||||
|
gender: '性别',
|
||||||
|
region: '地区',
|
||||||
|
male: '男',
|
||||||
|
female: '女',
|
||||||
|
unknown: '未知',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,12 @@
|
|||||||
"navigationBarTitleText": "首页"
|
"navigationBarTitleText": "首页"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/user/user",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/settings/apiConfig",
|
"path": "pages/settings/apiConfig",
|
||||||
"style": {
|
"style": {
|
||||||
@@ -50,6 +56,12 @@
|
|||||||
"iconPath": "static/tabbar/home.png",
|
"iconPath": "static/tabbar/home.png",
|
||||||
"selectedIconPath": "static/tabbar/home-active.png"
|
"selectedIconPath": "static/tabbar/home-active.png"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/user/user",
|
||||||
|
"text": "我的",
|
||||||
|
"iconPath": "static/tabbar/settings.png",
|
||||||
|
"selectedIconPath": "static/tabbar/settings-active.png"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pagePath": "pages/settings/apiConfig",
|
"pagePath": "pages/settings/apiConfig",
|
||||||
"text": "设置",
|
"text": "设置",
|
||||||
|
|||||||
@@ -134,19 +134,27 @@ const handleLogin = () => {
|
|||||||
uni.request({
|
uni.request({
|
||||||
url: getApp().globalData.BASE_URL + '/users/login',
|
url: getApp().globalData.BASE_URL + '/users/login',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
userCookieValue: '',
|
||||||
data: {
|
data: {
|
||||||
username: form.username,
|
username: form.username,
|
||||||
password: form.password,
|
password: form.password,
|
||||||
remember: form.remember
|
remember: form.remember
|
||||||
|
}
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.data.code === 0 && res.data.data && res.data.data.cookie) {
|
if (res.data.err_code === 0 && res.data.return && res.data.return.cookie) {
|
||||||
const cookie = res.data.data.cookie
|
const cookieData = res.data.return.cookie
|
||||||
uni.setStorageSync('sessionCookie', cookie.Value)
|
// 存储 cookie Value 作为 session 标识
|
||||||
uni.setStorageSync('userInfo', res.data.data)
|
uni.setStorageSync('sessionCookie', cookieData.Value)
|
||||||
|
uni.setStorageSync('cookieExpires', cookieData.ExpiresAt)
|
||||||
|
uni.setStorageSync('userInfo', {
|
||||||
|
userId: cookieData.ID,
|
||||||
|
username: form.username
|
||||||
|
})
|
||||||
|
|
||||||
if (form.remember) {
|
if (form.remember) {
|
||||||
uni.setStorageSync('savedUsername', form.username)
|
uni.setStorageSync('savedUsername', form.username)
|
||||||
@@ -168,13 +176,15 @@ const handleLogin = () => {
|
|||||||
})
|
})
|
||||||
}, 1500)
|
}, 1500)
|
||||||
} else {
|
} else {
|
||||||
|
// 根据 err_code 显示错误信息
|
||||||
|
const errCode = res.data.err_code
|
||||||
const msgMap = {
|
const msgMap = {
|
||||||
userNameNoFund: t('login.usernameNotFound'),
|
'-41': t('login.usernameNotFound'),
|
||||||
userPassIncorrect: t('login.passwordIncorrect'),
|
'-42': t('login.passwordIncorrect'),
|
||||||
jsonErr: t('login.paramError'),
|
'-3': t('login.paramError'),
|
||||||
postErr: t('login.requestFailed')
|
'-2': t('login.requestFailed')
|
||||||
}
|
}
|
||||||
errorMsg.value = msgMap[res.data.code] || t('login.loginFailed')
|
errorMsg.value = msgMap[errCode] || res.data.err_msg || t('login.loginFailed')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
|
|||||||
@@ -160,16 +160,19 @@ const handleRegister = () => {
|
|||||||
uni.request({
|
uni.request({
|
||||||
url: getApp().globalData.BASE_URL + '/users/register',
|
url: getApp().globalData.BASE_URL + '/users/register',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
userCookieValue: '',
|
||||||
data: {
|
data: {
|
||||||
username: form.username,
|
username: form.username,
|
||||||
useremail: form.email,
|
useremail: form.email,
|
||||||
userpass: form.password
|
userpass: form.password
|
||||||
|
}
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.data.code === 0) {
|
if (res.data.err_code === 0) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: t('register.registerSuccess'),
|
title: t('register.registerSuccess'),
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
@@ -179,13 +182,15 @@ const handleRegister = () => {
|
|||||||
uni.navigateBack()
|
uni.navigateBack()
|
||||||
}, 1500)
|
}, 1500)
|
||||||
} else {
|
} else {
|
||||||
|
// 根据 err_code 显示错误信息
|
||||||
|
const errCode = res.data.err_code
|
||||||
const msgMap = {
|
const msgMap = {
|
||||||
userNameDup: t('register.usernameExists'),
|
'-4': t('register.usernameExists'),
|
||||||
userEmailDup: t('register.emailUsed'),
|
'-43': t('register.emailInvalid'),
|
||||||
jsonErr: t('register.paramError'),
|
'-3': t('register.paramError'),
|
||||||
postErr: t('register.requestFailed')
|
'-2': t('register.requestFailed')
|
||||||
}
|
}
|
||||||
errorMsg.value = msgMap[res.data.code] || t('register.registerFailed')
|
errorMsg.value = msgMap[errCode] || res.data.err_msg || t('register.registerFailed')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
|
|||||||
@@ -0,0 +1,319 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<!-- 未登录状态 -->
|
||||||
|
<view v-if="!isLoggedIn" class="login-prompt">
|
||||||
|
<view class="prompt-icon">👤</view>
|
||||||
|
<text class="prompt-text">{{ t('index.pleaseLogin') }}</text>
|
||||||
|
<button class="login-btn" @click="goLogin">{{ t('index.login') }}</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 已登录状态 -->
|
||||||
|
<view v-else class="user-info">
|
||||||
|
<!-- 用户卡片 -->
|
||||||
|
<view class="user-card">
|
||||||
|
<view class="avatar-box">
|
||||||
|
<view class="avatar-placeholder">👤</view>
|
||||||
|
</view>
|
||||||
|
<view class="user-details">
|
||||||
|
<text class="username">{{ userInfo.username || userInfo.Name || 'User' }}</text>
|
||||||
|
<text class="email">{{ userInfo.email || userInfo.Email || '' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<view v-if="loading" class="loading-box">
|
||||||
|
<text>{{ t('common.loading') }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 用户详细信息 -->
|
||||||
|
<view v-else-if="userDetail" class="detail-section">
|
||||||
|
<view class="section-title">{{ t('user.profile') }}</view>
|
||||||
|
<view class="info-list">
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">{{ t('user.username') }}</text>
|
||||||
|
<text class="info-value">{{ userDetail.userInfo.Username || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">{{ t('user.firstName') }}</text>
|
||||||
|
<text class="info-value">{{ userDetail.userInfo.FirstName || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">{{ t('user.birthday') }}</text>
|
||||||
|
<text class="info-value">{{ userDetail.userInfo.Birthdate || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">{{ t('user.gender') }}</text>
|
||||||
|
<text class="info-value">{{ genderText }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">{{ t('user.region') }}</text>
|
||||||
|
<text class="info-value">{{ userDetail.userInfo.Region || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<view class="action-section">
|
||||||
|
<button class="action-btn logout" @click="handleLogout">
|
||||||
|
{{ t('index.logout') }}
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
|
|
||||||
|
const { t, locale } = useI18n()
|
||||||
|
|
||||||
|
const isLoggedIn = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const userInfo = ref({})
|
||||||
|
const userDetail = ref(null)
|
||||||
|
|
||||||
|
// 性别显示文本
|
||||||
|
const genderText = computed(() => {
|
||||||
|
if (!userDetail.value?.userInfo?.Gender) return '-'
|
||||||
|
const map = { M: t('user.male'), F: t('user.female'), U: t('user.unknown') }
|
||||||
|
return map[userDetail.value.userInfo.Gender] || '-'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 检查登录状态
|
||||||
|
const checkLogin = () => {
|
||||||
|
const cookie = uni.getStorageSync('sessionCookie')
|
||||||
|
const info = uni.getStorageSync('userInfo')
|
||||||
|
isLoggedIn.value = !!cookie && !!info
|
||||||
|
if (info) userInfo.value = info
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户详细信息
|
||||||
|
const fetchUserDetail = () => {
|
||||||
|
if (!isLoggedIn.value) return
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
const cookie = uni.getStorageSync('sessionCookie')
|
||||||
|
|
||||||
|
uni.request({
|
||||||
|
url: getApp().globalData.BASE_URL + '/users/getinfo',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
userCookieValue: cookie,
|
||||||
|
data: {}
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
success: (res) => {
|
||||||
|
if (res.data.err_code === 0 && res.data.return) {
|
||||||
|
userDetail.value = res.data.return
|
||||||
|
// 更新本地存储的用户信息
|
||||||
|
const newInfo = {
|
||||||
|
userId: res.data.return.user?.ID,
|
||||||
|
username: res.data.return.user?.Name,
|
||||||
|
email: res.data.return.user?.Email,
|
||||||
|
...res.data.return.userInfo
|
||||||
|
}
|
||||||
|
uni.setStorageSync('userInfo', newInfo)
|
||||||
|
userInfo.value = newInfo
|
||||||
|
} else if (res.data.err_code === -44) {
|
||||||
|
// Cookie 过期,清除登录状态
|
||||||
|
handleLogout()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('Get user info error:', err)
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到登录页
|
||||||
|
const goLogin = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退出登录
|
||||||
|
const handleLogout = () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: t('index.logoutConfirm'),
|
||||||
|
content: t('index.logoutMessage'),
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.removeStorageSync('sessionCookie')
|
||||||
|
uni.removeStorageSync('cookieExpires')
|
||||||
|
uni.removeStorageSync('userInfo')
|
||||||
|
isLoggedIn.value = false
|
||||||
|
userInfo.value = {}
|
||||||
|
userDetail.value = null
|
||||||
|
uni.showToast({
|
||||||
|
title: t('index.logout'),
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面显示时刷新数据
|
||||||
|
onShow(() => {
|
||||||
|
checkLogin()
|
||||||
|
if (isLoggedIn.value) {
|
||||||
|
fetchUserDetail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-prompt {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 200rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-icon {
|
||||||
|
font-size: 120rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn {
|
||||||
|
width: 300rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 40rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-box {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
border-radius: 60rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-placeholder {
|
||||||
|
font-size: 60rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
display: block;
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email {
|
||||||
|
display: block;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-box {
|
||||||
|
text-align: center;
|
||||||
|
padding: 60rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-section {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24rpx 0;
|
||||||
|
border-bottom: 1rpx solid #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section {
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
border: none;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.logout {
|
||||||
|
background: #fff;
|
||||||
|
color: #ff4d4f;
|
||||||
|
border: 2rpx solid #ff4d4f;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="20" cy="20" r="20" fill="#F0F0F0"/>
|
||||||
|
<circle cx="20" cy="15" r="6" fill="#999"/>
|
||||||
|
<path d="M8 36C8 28.268 13.372 22 20 22C26.628 22 32 28.268 32 36" stroke="#999" stroke-width="4" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 323 B |
Reference in New Issue
Block a user