diff --git a/.trae/documents/协议管理页面实现计划.md b/.trae/documents/协议管理页面实现计划.md
new file mode 100644
index 0000000..f76cb8c
--- /dev/null
+++ b/.trae/documents/协议管理页面实现计划.md
@@ -0,0 +1,95 @@
+# 协议管理页面实现计划
+
+## 1. 需求分析
+根据 `index.js` 中的 API 功能,需要实现以下功能:
+- 协议列表展示
+- 协议状态修改
+- 协议删除
+- 协议详情查看
+- 协议创建
+- 协议更新
+
+## 2. 页面设计
+遵循 Element Plus 企业级管理系统设计风格,页面包含:
+- 卡片式布局
+- 表格展示协议列表
+- 状态标签显示协议状态
+- 操作按钮(编辑、删除、启用/禁用)
+- 表单用于创建/编辑协议
+- 弹窗用于详情查看和表单操作
+
+## 3. 实现步骤
+
+### 3.1 页面结构设计
+- 使用 `el-card` 包裹主要内容
+- 卡片头部包含标题和创建按钮
+- 表格展示协议列表,包含协议类型、版本、状态、语言、创建时间等字段
+- 操作列包含查看详情、编辑、删除、启用/禁用按钮
+
+### 3.2 功能实现
+- **列表查询**:调用 `getAgreementList` API 获取协议列表
+- **状态修改**:点击启用/禁用按钮,调用 `updateAgreementStatus` API
+- **删除协议**:点击删除按钮,调用 `deleteAgreement` API,带确认提示
+- **查看详情**:点击详情按钮,弹窗展示协议详情
+- **创建协议**:点击创建按钮,弹窗显示表单,调用 `createAgreement` API
+- **编辑协议**:点击编辑按钮,弹窗显示表单,调用 `updateAgreement` API
+
+### 3.3 路由配置
+在 `permissionRoutes` 数组中添加协议管理路由:
+- 路径:`agreement-management`
+- 名称:`AdminAgreement`
+- 组件:`AdminAgreement`
+- 标题:`admin.layout.agreementManagement`
+- 图标:`Document`
+- 菜单顺序:合理位置
+
+### 3.4 响应式设计
+- 表格在移动端自动调整布局
+- 弹窗在移动端自适应宽度
+- 表单元素在不同屏幕尺寸下保持良好的用户体验
+
+## 4. 代码实现
+
+### 4.1 创建 `index.vue` 文件
+- 使用 Composition API
+- 导入必要的组件和 API 类
+- 实现数据响应式
+- 实现方法逻辑
+- 实现模板结构
+- 添加样式
+
+### 4.2 Vue3 属性绑定语法
+所有属性绑定严格使用 Vue3 语法:
+- 错误:`label="{{label}}"`
+- 正确:`:label="label"`
+- 示例:
+ - `:data="tableData"`
+ - `:loading="loading"`
+ - `:visible.sync="dialogVisible"`
+ - `:type="scope.row.status === 1 ? 'success' : 'warning'"`
+ - `@click="handleEdit(scope.row)"`
+
+### 4.3 具体实现细节
+- **表格配置**:使用 `:data` 绑定表格数据,`:loading` 绑定加载状态
+- **弹窗配置**:使用 `:visible.sync` 控制弹窗显示/隐藏
+- **表单配置**:使用 `v-model` 绑定表单数据,`:rules` 绑定验证规则
+- **按钮配置**:使用 `@click` 绑定点击事件,`:type` 绑定按钮类型
+- **状态标签**:使用 `:type` 绑定标签类型,动态根据状态值变化
+
+### 4.4 更新路由配置
+在 `router/index.js` 中添加协议管理路由
+
+## 5. 预期效果
+- 页面布局符合设计风格指南
+- 所有功能正常工作
+- 响应式设计适配不同设备
+- 交互流畅,反馈清晰
+- 严格遵循 Vue3 属性绑定语法
+
+## 6. 技术要点
+- Vue3 Composition API
+- Element Plus 组件库
+- API 异步调用
+- 响应式设计
+- 中英文切换支持
+- 严格的 Vue3 属性绑定语法
\ No newline at end of file
diff --git a/apps/FrontendDesigner/package.json b/apps/FrontendDesigner/package.json
index 9808da6..59fc908 100644
--- a/apps/FrontendDesigner/package.json
+++ b/apps/FrontendDesigner/package.json
@@ -16,6 +16,8 @@
"@element-plus/icons-vue": "^2.3.2",
"@google/genai": "^1.27.0",
"@types/three": "^0.180.0",
+ "@wangeditor/editor": "^5.1.23",
+ "@wangeditor/editor-for-vue": "^5.1.12",
"element-china-area-data": "^6.1.0",
"element-plus": "^2.11.7",
"konva": "^10.0.12",
diff --git a/apps/FrontendDesigner/src/components/common/RichTextEditor.vue b/apps/FrontendDesigner/src/components/common/RichTextEditor.vue
new file mode 100644
index 0000000..82672fb
--- /dev/null
+++ b/apps/FrontendDesigner/src/components/common/RichTextEditor.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/FrontendDesigner/src/locales/lang/en-US.js b/apps/FrontendDesigner/src/locales/lang/en-US.js
index 1412ae8..a471746 100644
--- a/apps/FrontendDesigner/src/locales/lang/en-US.js
+++ b/apps/FrontendDesigner/src/locales/lang/en-US.js
@@ -21,6 +21,7 @@ export default {
back: 'Back',
submit: 'Submit',
all: 'All',
+ operation:'Operation',
},
// Shop Management
@@ -115,6 +116,7 @@ export default {
pointsList: 'Points List'
}
},
+
// Employee Management
employee: {
idCardImageTip: 'Please upload ID card image',
@@ -422,7 +424,8 @@ export default {
adminAgent: 'Admin Agent',
logout: 'Logout',
profile: 'Profile',
- settings: 'Settings'
+ settings: 'Settings',
+ agreementManagement: 'Agreement Management',
},
roleManagement: {
title: 'Role Management',
@@ -1195,6 +1198,30 @@ export default {
userPhone: 'Enter user phone',
userNickname: 'Enter user nickname'
}
+ },
+ agreementManagement: {
+ title: 'Agreement Management',
+ create: 'Create Agreement',
+ agreementType: 'Agreement Type',
+ selectType: 'Please select agreement type',
+ userAgreement: 'User Agreement',
+ privacyPolicy: 'Privacy Policy',
+ serviceTerms: 'Service Terms',
+ status: 'Status',
+ selectStatus: 'Please select status',
+ enabled: 'Enabled',
+ disabled: 'Disabled',
+ disable: 'Disable',
+ enable: 'Enable',
+ lang: 'Language',
+ selectLang: 'Please select language',
+ version: 'Version',
+ enterVersion: 'Please enter version',
+ content: 'Content',
+ enterContent: 'Please enter content',
+ createdAt: 'Created At',
+ updatedAt: 'Updated At',
+ deleteConfirm: 'Are you sure you want to delete this agreement?',
}
},
modelUpload: {
diff --git a/apps/FrontendDesigner/src/locales/lang/zh-CN.js b/apps/FrontendDesigner/src/locales/lang/zh-CN.js
index 7db5a7f..a8e8b5b 100644
--- a/apps/FrontendDesigner/src/locales/lang/zh-CN.js
+++ b/apps/FrontendDesigner/src/locales/lang/zh-CN.js
@@ -1,30 +1,5 @@
// 中文语言包
export default {
- // 通用
- common: {
- confirm: '确认',
- cancel: '取消',
- save: '保存',
- delete: '删除',
- edit: '编辑',
- add: '添加',
- search: '搜索',
- reset: '重置',
- loading: '加载中...',
- noData: '暂无数据',
- error: '出错了',
- success: '操作成功',
- warning: '警告',
- info: '提示',
- active: '活跃',
- inactive: '非活跃',
- detail: '详情',
- saveSuccess: '保存成功',
- saveFailed: '保存失败',
- deleteSuccess: '删除成功',
- deleteFailed: '删除失败',
- all: '全部',
- },
orderManagement: {
title: '订单',
description: '查看和管理您的购买和订阅信息',
@@ -194,6 +169,33 @@ orderManagement: {
// 管理后台
admin: {
title: '管理后台',
+ layout: {
+ agreementManagement: '协议管理',
+ },
+ agreementManagement: {
+ title: '协议管理',
+ create: '创建协议',
+ agreementType: '协议类型',
+ selectType: '请选择协议类型',
+ userAgreement: '用户协议',
+ privacyPolicy: '隐私政策',
+ serviceTerms: '服务条款',
+ status: '状态',
+ selectStatus: '请选择状态',
+ enabled: '启用',
+ disabled: '禁用',
+ disable: '禁用',
+ enable: '启用',
+ lang: '语言',
+ selectLang: '请选择语言',
+ version: '版本',
+ enterVersion: '请输入版本号',
+ content: '内容',
+ enterContent: '请输入协议内容',
+ createdAt: '创建时间',
+ updatedAt: '更新时间',
+ deleteConfirm: '确定要删除该协议吗?',
+ },
login: {
title: '管理员登录',
username: '用户名',
@@ -268,7 +270,8 @@ orderManagement: {
invalidate: '作废',
requestFailed: '请求失败',
operationSuccess: '操作成功',
- operationFailed: '操作失败'
+ operationFailed: '操作失败',
+ operation:'操作'
},
layout: {
employee: '员工管理',
@@ -296,7 +299,8 @@ orderManagement: {
logout: '退出登录',
profile: '个人资料',
settings: '设置',
- notifications: '通知'
+ notifications: '通知',
+ agreementManagement: '协议管理',
},
roleManagement: {
title: '角色管理',
@@ -1113,7 +1117,8 @@ orderManagement: {
info: '信息',
close: '关闭',
back: '返回',
- submit: '提交'
+ submit: '提交',
+ operation:'操作'
},
// 店铺管理
diff --git a/apps/FrontendDesigner/src/router/index.js b/apps/FrontendDesigner/src/router/index.js
index 3a2d4a3..194a3d6 100644
--- a/apps/FrontendDesigner/src/router/index.js
+++ b/apps/FrontendDesigner/src/router/index.js
@@ -29,6 +29,7 @@ const AdminAgent = () => import('@/views/admin/Adminagent/index.vue')
const AdminCommissionWithdrawal = () => import('@/views/admin/AdminCommissionManagement/AdminCommissionWithdrawal.vue')
const AdminShop = () => import('@/views/admin/AdminShop/shop.vue')
const AdminEmployee = () => import('@/views/admin/AdminShop/employee.vue')
+const AdminAgreement = () => import('@/views/admin/Adminagreement/index.vue')
//权限路由映射表
export const permissionRoutes = [
{
@@ -235,7 +236,17 @@ export const permissionRoutes = [
requiresAuth: true
}
},
-
+ {
+ path: 'agreement-management',
+ name: 'AdminAgreement',
+ component: AdminAgreement,
+ meta: {
+ title: 'admin.layout.agreementManagement',
+ icon: 'Document',
+ menuOrder: 6,
+ requiresAuth: true
+ }
+ },
{
path: 'permission',
diff --git a/apps/FrontendDesigner/src/views/AdminLogin/AdminLogin.vue b/apps/FrontendDesigner/src/views/AdminLogin/AdminLogin.vue
index 6d60863..e8f3056 100644
--- a/apps/FrontendDesigner/src/views/AdminLogin/AdminLogin.vue
+++ b/apps/FrontendDesigner/src/views/AdminLogin/AdminLogin.vue
@@ -142,10 +142,10 @@ const handleLogin = async () => {
loading.value = true
// 发送登录请求
const response = await requestUtils.common(adminApi.default.LOGIN, {
- username: loginForm.username,
- password: loginForm.password,
- code: loginForm.code,
- uuid: uuid.value
+ username: loginForm.username.trim(),
+ password: loginForm.password.trim(),
+ code: loginForm.code.trim(),
+ uuid: uuid.value.trim()
}
)
if(response.code !== 0){
diff --git a/apps/FrontendDesigner/src/views/admin/Adminagreement/index.js b/apps/FrontendDesigner/src/views/admin/Adminagreement/index.js
new file mode 100644
index 0000000..b34c90d
--- /dev/null
+++ b/apps/FrontendDesigner/src/views/admin/Adminagreement/index.js
@@ -0,0 +1,124 @@
+import {adminApi,requestUtils} from '@deotaland/utils';
+export class AdminAgreement {
+ constructor(){
+ }
+ // 修改协议状态
+ async updateAgreementStatus(id,data){
+ let parmas = {
+ id:data.id,
+ status:data.status,//状态: 0禁用 1启用
+ }
+ const requestUrl = {
+ method:adminApi.default.updateAgreementStatus.method,
+ url:adminApi.default.updateAgreementStatus.url.replace('{id}',parmas.id).replace('{status}',parmas.status),
+ }
+ return await requestUtils.common(requestUrl,parmas);
+ }
+ //删除协议
+ async deleteAgreement(id){
+ let parmas = {
+ id:id,
+ }
+ const requestUrl = {
+ method:adminApi.default.removeAgreement.method,
+ url:adminApi.default.removeAgreement.url.replace('{id}',parmas.id),
+ }
+ return await requestUtils.common(requestUrl,parmas);
+ }
+ //获取协议详情
+ async getAgreementDetail(id){
+ let parmas = {
+ id:id,
+ }
+ const requestUrl = {
+ method:adminApi.default.getAgreementDetail.method,
+ url:adminApi.default.getAgreementDetail.url.replace('{id}',parmas.id),
+ }
+ return await requestUtils.common(requestUrl,parmas);
+ /**
+ 返回示例:
+ {
+ "code": 0,
+ "success": true,
+ "data": {
+ "id": 1073741824,
+ "agreementType": "string",
+ "agreementTypeName": "string",
+ "content": "string",
+ "version": "string",
+ "status": 1073741824,
+ "createdAt": "2026-01-14T07:37:06.427Z",
+ "updatedAt": "2026-01-14T07:37:06.427Z",
+ "lang": "string"
+ },
+ "message": "操作成功"
+}
+ */
+ }
+ //获取协议列表
+ async getAgreementList(data){
+ let parmas = {
+ pageNum:data.pageNum,
+ pageSize:data.pageSize,
+ agreementType:data.agreementType,//协议类型: user_agreement/privacy_policy/service_terms
+ status:data.status,//状态: 0禁用 1启用
+ lang:data.lang,//语言类型: en/zh
+ }
+ const requestUrl = {
+ method:adminApi.default.getAgreementList.method,
+ url:adminApi.default.getAgreementList.url,
+ }
+ return await requestUtils.common(requestUrl,parmas);
+ /**
+ 返回示例:
+ {
+ "total": 9007199254740991,
+ "rows": [
+ {
+ "id": 1073741824,
+ "agreementType": "string",
+ "agreementTypeName": "string",
+ "content": "string",
+ "version": "string",
+ "status": 1073741824,
+ "createdAt": "2026-01-14T07:37:46.846Z",
+ "updatedAt": "2026-01-14T07:37:46.846Z",
+ "lang": "string"
+ }
+ ],
+ "code": 1073741824,
+ "msg": "string"
+}
+ */
+ }
+ //创建协议
+ async createAgreement(data){
+ let parmas = {
+ agreementType:data.agreementType,//协议类型: user_agreement/privacy_policy/service_terms
+ version:data.version,//版本号
+ content:data.content,//协议内容
+ lang:data.lang,//语言类型: en/zh
+ }
+ const requestUrl = {
+ method:adminApi.default.addAgreement.method,
+ url:adminApi.default.addAgreement.url,
+ }
+ return await requestUtils.common(requestUrl,parmas);
+ }
+ //更新协议
+ async updateAgreement(data){
+ let parmas = {
+ id:data.id,
+ agreementType:data.agreementType,//协议类型: user_agreement/privacy_policy/service_terms
+ version:data.version,//版本号
+ content:data.content,//协议内容
+ lang:data.lang,//语言类型: en/zh
+ status:data.status,//状态: 0禁用 1启用
+ }
+ const requestUrl = {
+ method:adminApi.default.editAgreement.method,
+ url:adminApi.default.editAgreement.url.replace('{id}',parmas.id),
+ }
+ return await requestUtils.common(requestUrl,parmas);
+ }
+}
\ No newline at end of file
diff --git a/apps/FrontendDesigner/src/views/admin/Adminagreement/index.vue b/apps/FrontendDesigner/src/views/admin/Adminagreement/index.vue
new file mode 100644
index 0000000..ec29977
--- /dev/null
+++ b/apps/FrontendDesigner/src/views/admin/Adminagreement/index.vue
@@ -0,0 +1,539 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('common.search') }}
+
+
+ {{ $t('common.reset') }}
+
+
+
+
+
+
+
+
+ {{ $t('admin.agreementManagement.userAgreement') }}
+ {{ $t('admin.agreementManagement.privacyPolicy') }}
+ {{ $t('admin.agreementManagement.serviceTerms') }}
+
+
+
+
+
+
+ {{ scope.row.status === 1 ? $t('admin.agreementManagement.enabled') : $t('admin.agreementManagement.disabled') }}
+
+
+
+
+
+ English
+ 中文
+
+
+
+
+
+
+
+ {{ $t('common.detail') }}
+
+
+ {{ $t('common.edit') }}
+
+
+ {{ $t('common.delete') }}
+
+
+ {{ scope.row.status === 1 ? $t('admin.agreementManagement.disable') : $t('admin.agreementManagement.enable') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ detailData.agreementTypeName || '' }}
+
+
+ {{ detailData.version || '' }}
+
+
+
+ {{ detailData.status === 1 ? $t('admin.agreementManagement.enabled') : $t('admin.agreementManagement.disabled') }}
+
+
+
+ {{ detailData.lang === 'en' ? 'English' : '中文' }}
+
+
+
+
+
+ {{ detailData.createdAt || '' }}
+
+
+ {{ detailData.updatedAt || '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/frontend/src/components/auth/PhoneLoginForm.vue b/apps/frontend/src/components/auth/PhoneLoginForm.vue
index 4619e4d..378da99 100644
--- a/apps/frontend/src/components/auth/PhoneLoginForm.vue
+++ b/apps/frontend/src/components/auth/PhoneLoginForm.vue
@@ -135,7 +135,32 @@
{{ passwordError }}
-
+
+