登录协议补充
CI/CD / build (push) Successful in 5m18s Details

This commit is contained in:
13121765685 2026-01-14 17:22:13 +08:00
parent 57edd9bbf9
commit 6fe9e04030
22 changed files with 2109 additions and 46 deletions

View File

@ -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 属性绑定语法

View File

@ -16,6 +16,8 @@
"@element-plus/icons-vue": "^2.3.2", "@element-plus/icons-vue": "^2.3.2",
"@google/genai": "^1.27.0", "@google/genai": "^1.27.0",
"@types/three": "^0.180.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-china-area-data": "^6.1.0",
"element-plus": "^2.11.7", "element-plus": "^2.11.7",
"konva": "^10.0.12", "konva": "^10.0.12",

View File

@ -0,0 +1,116 @@
<template>
<div class="rich-text-editor">
<Toolbar
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="mode"
class="toolbar"
/>
<Editor
:defaultConfig="editorConfig"
:value="modelValue"
:mode="mode"
class="editor"
@onCreated="handleCreated"
@onChange="handleChange"
/>
</div>
</template>
<script setup>
import '@wangeditor/editor/dist/css/style.css'
import { onBeforeUnmount, ref, shallowRef, watch } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { FileServer } from '@deotaland/utils'
const props = defineProps({
modelValue: {
type: String,
default: ''
},
mode: {
type: String,
default: 'default'
},
placeholder: {
type: String,
default: '请输入内容'
},
readonly: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:modelValue', 'change'])
const editorRef = shallowRef()
const fileServer = new FileServer()
const toolbarConfig = {
excludeKeys: ['group-video']
}
const editorConfig = {
placeholder: props.placeholder,
readOnly: props.readonly,
MENU_CONF: {
uploadImage: {
async customUpload(file, insertFn) {
try {
const url = await fileServer.uploadFile(file)
insertFn(url, file.name, url)
} catch (error) {
console.error('图片上传失败:', error)
}
}
}
}
}
const handleCreated = (editor) => {
editorRef.value = editor
if (props.modelValue) {
editor.setHtml(props.modelValue)
}
}
const handleChange = (editor) => {
const html = editor.getHtml()
emit('update:modelValue', html)
emit('change', html)
}
watch(() => props.modelValue, (newVal) => {
if (editorRef.value) {
const currentHtml = editorRef.value.getHtml()
if (currentHtml !== newVal) {
editorRef.value.setHtml(newVal)
}
}
}, { immediate: false })
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor == null) return
editor.destroy()
})
</script>
<style scoped>
.rich-text-editor {
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
}
.toolbar {
border-bottom: 1px solid #dcdfe6;
}
.editor {
min-height: 400px;
height: 400px;
overflow-y: auto;
}
</style>

View File

@ -21,6 +21,7 @@ export default {
back: 'Back', back: 'Back',
submit: 'Submit', submit: 'Submit',
all: 'All', all: 'All',
operation:'Operation',
}, },
// Shop Management // Shop Management
@ -115,6 +116,7 @@ export default {
pointsList: 'Points List' pointsList: 'Points List'
} }
}, },
// Employee Management // Employee Management
employee: { employee: {
idCardImageTip: 'Please upload ID card image', idCardImageTip: 'Please upload ID card image',
@ -422,7 +424,8 @@ export default {
adminAgent: 'Admin Agent', adminAgent: 'Admin Agent',
logout: 'Logout', logout: 'Logout',
profile: 'Profile', profile: 'Profile',
settings: 'Settings' settings: 'Settings',
agreementManagement: 'Agreement Management',
}, },
roleManagement: { roleManagement: {
title: 'Role Management', title: 'Role Management',
@ -1195,6 +1198,30 @@ export default {
userPhone: 'Enter user phone', userPhone: 'Enter user phone',
userNickname: 'Enter user nickname' 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: { modelUpload: {

View File

@ -1,30 +1,5 @@
// 中文语言包 // 中文语言包
export default { 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: { orderManagement: {
title: '订单', title: '订单',
description: '查看和管理您的购买和订阅信息', description: '查看和管理您的购买和订阅信息',
@ -194,6 +169,33 @@ orderManagement: {
// 管理后台 // 管理后台
admin: { admin: {
title: '管理后台', 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: { login: {
title: '管理员登录', title: '管理员登录',
username: '用户名', username: '用户名',
@ -268,7 +270,8 @@ orderManagement: {
invalidate: '作废', invalidate: '作废',
requestFailed: '请求失败', requestFailed: '请求失败',
operationSuccess: '操作成功', operationSuccess: '操作成功',
operationFailed: '操作失败' operationFailed: '操作失败',
operation:'操作'
}, },
layout: { layout: {
employee: '员工管理', employee: '员工管理',
@ -296,7 +299,8 @@ orderManagement: {
logout: '退出登录', logout: '退出登录',
profile: '个人资料', profile: '个人资料',
settings: '设置', settings: '设置',
notifications: '通知' notifications: '通知',
agreementManagement: '协议管理',
}, },
roleManagement: { roleManagement: {
title: '角色管理', title: '角色管理',
@ -1113,7 +1117,8 @@ orderManagement: {
info: '信息', info: '信息',
close: '关闭', close: '关闭',
back: '返回', back: '返回',
submit: '提交' submit: '提交',
operation:'操作'
}, },
// 店铺管理 // 店铺管理

View File

@ -29,6 +29,7 @@ const AdminAgent = () => import('@/views/admin/Adminagent/index.vue')
const AdminCommissionWithdrawal = () => import('@/views/admin/AdminCommissionManagement/AdminCommissionWithdrawal.vue') const AdminCommissionWithdrawal = () => import('@/views/admin/AdminCommissionManagement/AdminCommissionWithdrawal.vue')
const AdminShop = () => import('@/views/admin/AdminShop/shop.vue') const AdminShop = () => import('@/views/admin/AdminShop/shop.vue')
const AdminEmployee = () => import('@/views/admin/AdminShop/employee.vue') const AdminEmployee = () => import('@/views/admin/AdminShop/employee.vue')
const AdminAgreement = () => import('@/views/admin/Adminagreement/index.vue')
//权限路由映射表 //权限路由映射表
export const permissionRoutes = [ export const permissionRoutes = [
{ {
@ -235,7 +236,17 @@ export const permissionRoutes = [
requiresAuth: true requiresAuth: true
} }
}, },
{
path: 'agreement-management',
name: 'AdminAgreement',
component: AdminAgreement,
meta: {
title: 'admin.layout.agreementManagement',
icon: 'Document',
menuOrder: 6,
requiresAuth: true
}
},
{ {
path: 'permission', path: 'permission',

View File

@ -142,10 +142,10 @@ const handleLogin = async () => {
loading.value = true loading.value = true
// //
const response = await requestUtils.common(adminApi.default.LOGIN, { const response = await requestUtils.common(adminApi.default.LOGIN, {
username: loginForm.username, username: loginForm.username.trim(),
password: loginForm.password, password: loginForm.password.trim(),
code: loginForm.code, code: loginForm.code.trim(),
uuid: uuid.value uuid: uuid.value.trim()
} }
) )
if(response.code !== 0){ if(response.code !== 0){

View File

@ -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);
}
}

View File

@ -0,0 +1,539 @@
<template>
<div class="agreement-management">
<el-card shadow="hover" class="content-card">
<template #header>
<div class="card-header">
<span>{{ $t('admin.agreementManagement.title') }}</span>
<el-button type="primary" @click="handleCreate">
{{ $t('admin.agreementManagement.create') }}
</el-button>
</div>
</template>
<div class="card-body">
<!-- 查询条件 -->
<el-form :inline="true" :model="searchForm" class="search-form">
<el-form-item :label="$t('admin.agreementManagement.agreementType')">
<el-select v-model="searchForm.agreementType" :placeholder="$t('admin.agreementManagement.selectType')">
<el-option :label="$t('admin.agreementManagement.userAgreement')" value="user_agreement" />
<el-option :label="$t('admin.agreementManagement.privacyPolicy')" value="privacy_policy" />
<el-option :label="$t('admin.agreementManagement.serviceTerms')" value="service_terms" />
</el-select>
</el-form-item>
<el-form-item :label="$t('admin.agreementManagement.status')">
<el-select v-model="searchForm.status" :placeholder="$t('admin.agreementManagement.selectStatus')">
<el-option :label="$t('admin.agreementManagement.enabled')" :value="1" />
<el-option :label="$t('admin.agreementManagement.disabled')" :value="0" />
</el-select>
</el-form-item>
<el-form-item :label="$t('admin.agreementManagement.lang')">
<el-select v-model="searchForm.lang" :placeholder="$t('admin.agreementManagement.selectLang')">
<el-option label="English" value="en" />
<el-option label="中文" value="zh" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">
{{ $t('common.search') }}
</el-button>
<el-button @click="handleReset">
{{ $t('common.reset') }}
</el-button>
</el-form-item>
</el-form>
<!-- 协议列表 -->
<el-table
:data="tableData"
v-loading="loading"
:header-cell-style="{background: '#fafafa'}"
stripe
>
<el-table-column prop="agreementType" :label="$t('admin.agreementManagement.agreementType')" width="180">
<template #default="scope">
<span v-if="scope.row.agreementType === 'user_agreement'">{{ $t('admin.agreementManagement.userAgreement') }}</span>
<span v-else-if="scope.row.agreementType === 'privacy_policy'">{{ $t('admin.agreementManagement.privacyPolicy') }}</span>
<span v-else-if="scope.row.agreementType === 'service_terms'">{{ $t('admin.agreementManagement.serviceTerms') }}</span>
</template>
</el-table-column>
<el-table-column prop="version" :label="$t('admin.agreementManagement.version')" width="120" />
<el-table-column prop="status" :label="$t('admin.agreementManagement.status')" width="100">
<template #default="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'warning'">
{{ scope.row.status === 1 ? $t('admin.agreementManagement.enabled') : $t('admin.agreementManagement.disabled') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="lang" :label="$t('admin.agreementManagement.lang')" width="100">
<template #default="scope">
<span v-if="scope.row.lang === 'en'">English</span>
<span v-else-if="scope.row.lang === 'zh'">中文</span>
</template>
</el-table-column>
<el-table-column prop="createdAt" :label="$t('admin.agreementManagement.createdAt')" width="200" />
<el-table-column prop="updatedAt" :label="$t('admin.agreementManagement.updatedAt')" width="200" />
<el-table-column :label="$t('common.operation')" width="300" fixed="right">
<template #default="scope">
<el-button size="small" @click="handleDetail(scope.row)">
{{ $t('common.detail') }}
</el-button>
<el-button size="small" type="primary" @click="handleEdit(scope.row)">
{{ $t('common.edit') }}
</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.row)">
{{ $t('common.delete') }}
</el-button>
<el-button
size="small"
:type="scope.row.status === 1 ? 'warning' : 'success'"
@click="handleUpdateStatus(scope.row)"
>
{{ scope.row.status === 1 ? $t('admin.agreementManagement.disable') : $t('admin.agreementManagement.enable') }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination">
<el-pagination
v-model:current-page="pagination.pageNum"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</el-card>
<!-- 详情弹窗 -->
<el-dialog
:title="$t('common.detail')"
v-model="detailDialogVisible"
width="60%"
>
<el-descriptions :column="1" border>
<el-descriptions-item :label="$t('admin.agreementManagement.agreementType')">
{{ detailData.agreementTypeName || '' }}
</el-descriptions-item>
<el-descriptions-item :label="$t('admin.agreementManagement.version')">
{{ detailData.version || '' }}
</el-descriptions-item>
<el-descriptions-item :label="$t('admin.agreementManagement.status')">
<el-tag :type="detailData.status === 1 ? 'success' : 'warning'">
{{ detailData.status === 1 ? $t('admin.agreementManagement.enabled') : $t('admin.agreementManagement.disabled') }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item :label="$t('admin.agreementManagement.lang')">
{{ detailData.lang === 'en' ? 'English' : '中文' }}
</el-descriptions-item>
<el-descriptions-item :label="$t('admin.agreementManagement.content')">
<div v-html="detailData.content || ''" class="agreement-content"></div>
</el-descriptions-item>
<el-descriptions-item :label="$t('admin.agreementManagement.createdAt')">
{{ detailData.createdAt || '' }}
</el-descriptions-item>
<el-descriptions-item :label="$t('admin.agreementManagement.updatedAt')">
{{ detailData.updatedAt || '' }}
</el-descriptions-item>
</el-descriptions>
<template #footer>
<span class="dialog-footer">
<el-button @click="detailDialogVisible = false">{{ $t('common.close') }}</el-button>
</span>
</template>
</el-dialog>
<!-- 表单弹窗 -->
<el-dialog
:title="isEdit ? $t('common.edit') : $t('admin.agreementManagement.create')"
v-model="formDialogVisible"
width="60%"
>
<el-form :model="formData" :rules="rules" ref="formRef" label-width="120px">
<el-form-item :label="$t('admin.agreementManagement.agreementType')" prop="agreementType">
<el-select v-model="formData.agreementType" :placeholder="$t('admin.agreementManagement.selectType')">
<el-option :label="$t('admin.agreementManagement.userAgreement')" value="user_agreement" />
<el-option :label="$t('admin.agreementManagement.privacyPolicy')" value="privacy_policy" />
<el-option :label="$t('admin.agreementManagement.serviceTerms')" value="service_terms" />
</el-select>
</el-form-item>
<el-form-item :label="$t('admin.agreementManagement.version')" prop="version">
<el-input v-model="formData.version" :placeholder="$t('admin.agreementManagement.enterVersion')" />
</el-form-item>
<el-form-item :label="$t('admin.agreementManagement.lang')" prop="lang">
<el-select v-model="formData.lang" :placeholder="$t('admin.agreementManagement.selectLang')">
<el-option label="English" value="en" />
<el-option label="中文" value="zh" />
</el-select>
</el-form-item>
<el-form-item :label="$t('admin.agreementManagement.status')" prop="status">
<el-select v-model="formData.status" :placeholder="$t('admin.agreementManagement.selectStatus')">
<el-option :label="$t('admin.agreementManagement.enabled')" :value="1" />
<el-option :label="$t('admin.agreementManagement.disabled')" :value="0" />
</el-select>
</el-form-item>
<el-form-item :label="$t('admin.agreementManagement.content')" prop="content">
<RichTextEditor
v-model="formData.content"
:placeholder="$t('admin.agreementManagement.enterContent')"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="formDialogVisible = false">{{ $t('common.close') }}</el-button>
<el-button type="primary" @click="handleSubmit">{{ $t('common.submit') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue';
import { useI18n } from 'vue-i18n';
import { AdminAgreement } from './index.js';
import { ElMessage, ElMessageBox } from 'element-plus';
import RichTextEditor from '@/components/common/RichTextEditor.vue';
const { t } = useI18n();
// API
const adminAgreement = new AdminAgreement();
//
const tableData = ref([]);
const loading = ref(false);
//
const searchForm = reactive({
agreementType: '',
status: '',
lang: ''
});
//
const pagination = reactive({
pageNum: 1,
pageSize: 10,
total: 0
});
//
const detailDialogVisible = ref(false);
const detailData = ref({});
//
const formDialogVisible = ref(false);
const isEdit = ref(false);
const formRef = ref(null);
const formData = reactive({
id: '',
agreementType: '',
version: '',
content: '',
lang: '',
status: 1
});
//
const rules = reactive({
agreementType: [
{ required: true, message: '请选择协议类型', trigger: 'change' }
],
version: [
{ required: true, message: '请输入版本号', trigger: 'blur' }
],
lang: [
{ required: true, message: '请选择语言', trigger: 'change' }
],
status: [
{ required: true, message: '请选择状态', trigger: 'change' }
],
content: [
{ required: true, message: '请输入协议内容', trigger: 'change' }
]
});
//
const getAgreementList = async () => {
loading.value = true;
try {
const params = {
pageNum: pagination.pageNum,
pageSize: pagination.pageSize,
agreementType: searchForm.agreementType,
status: searchForm.status,
lang: searchForm.lang
};
const res = await adminAgreement.getAgreementList(params);
// API使code
if (res.code === 200 || res.code === 0) {
tableData.value = res.rows || res.data?.rows || [];
pagination.total = res.total || res.data?.total || 0;
} else {
ElMessage.error(res.msg || res.message || '获取协议列表失败');
}
} catch (error) {
ElMessage.error('获取协议列表失败');
} finally {
loading.value = false;
}
};
//
onMounted(() => {
getAgreementList();
});
//
const handleSearch = () => {
pagination.pageNum = 1;
getAgreementList();
};
//
const handleReset = () => {
searchForm.agreementType = '';
searchForm.status = '';
searchForm.lang = '';
pagination.pageNum = 1;
getAgreementList();
};
//
const handleSizeChange = (size) => {
pagination.pageSize = size;
getAgreementList();
};
//
const handleCurrentChange = (current) => {
pagination.pageNum = current;
getAgreementList();
};
//
const handleDetail = async (row) => {
try {
const res = await adminAgreement.getAgreementDetail(row.id);
if (res.code === 200 || res.code === 0) {
detailData.value = res.data;
detailDialogVisible.value = true;
} else {
ElMessage.error(res.msg || res.message || '获取协议详情失败');
}
} catch (error) {
ElMessage.error('获取协议详情失败');
}
};
//
const handleCreate = () => {
isEdit.value = false;
//
Object.assign(formData, {
id: '',
agreementType: '',
version: '',
content: '',
lang: '',
status: 1
});
//
if (formRef.value) {
formRef.value.resetFields();
}
formDialogVisible.value = true;
};
//
const handleEdit = (row) => {
isEdit.value = true;
//
if (formRef.value) {
formRef.value.clearValidate();
}
// tick
formDialogVisible.value = true;
nextTick(() => {
Object.assign(formData, {
id: row.id,
agreementType: row.agreementType,
version: row.version,
content: row.content || '',
lang: row.lang,
status: row.status
});
});
};
//
const handleSubmit = async () => {
if (!formRef.value) return;
try {
await formRef.value.validate();
let res;
if (isEdit.value) {
res = await adminAgreement.updateAgreement(formData);
} else {
res = await adminAgreement.createAgreement(formData);
}
if (res.code === 200 || res.code === 0) {
ElMessage.success(res.msg || res.message || '操作成功');
formDialogVisible.value = false;
getAgreementList();
} else {
ElMessage.error(res.msg || res.message || '操作失败');
}
} catch (error) {
if (error.name !== 'Error') {
return;
}
ElMessage.error('操作失败');
}
};
//
const handleDelete = async (row) => {
try {
await ElMessageBox.confirm(
t('admin.agreementManagement.deleteConfirm'),
t('common.confirm'),
{
confirmButtonText: t('common.confirm'),
cancelButtonText: t('common.cancel'),
type: 'warning'
}
);
const res = await adminAgreement.deleteAgreement(row.id);
if (res.code === 200 || res.code === 0) {
ElMessage.success(res.msg || res.message || '删除成功');
getAgreementList();
} else {
ElMessage.error(res.msg || res.message || '删除失败');
}
} catch (error) {
if (error !== 'cancel') {
ElMessage.error('删除失败');
}
}
};
//
const handleUpdateStatus = async (row) => {
try {
const newStatus = row.status === 1 ? 0 : 1;
const res = await adminAgreement.updateAgreementStatus(row.id, {
id: row.id,
status: newStatus
});
if (res.code === 200 || res.code === 0) {
ElMessage.success(res.msg || res.message || '状态更新成功');
getAgreementList();
} else {
ElMessage.error(res.msg || res.message || '状态更新失败');
}
} catch (error) {
ElMessage.error('状态更新失败');
}
};
</script>
<style scoped>
.content-card {
margin-bottom: 20px;
width: 100%;
box-sizing: border-box;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.search-form {
margin: 20px;
padding: 10px;
background-color: #fafafa;
border-radius: 4px;
}
/* 调整筛选下拉框宽度 */
.search-form :deep(.el-select) {
width: 200px;
}
.search-form :deep(.el-input) {
width: 200px;
}
.pagination {
margin: 20px;
text-align: right;
}
.agreement-content {
white-space: pre-wrap;
word-break: break-word;
}
/* 富文本编辑器样式 */
:deep(.rich-text-editor) {
width: 100%;
}
:deep(.w-e-text-container) {
min-height: 400px !important;
}
/* 调整表格宽度 */
:deep(.el-table) {
width: 100%;
min-width: 800px;
}
/* 确保表格容器和表头占满宽度 */
:deep(.el-table__header-wrapper),
:deep(.el-table__body-wrapper),
:deep(.el-table__footer-wrapper) {
width: 100% !important;
}
:deep(.el-table__header),
:deep(.el-table__body),
:deep(.el-table__footer) {
width: 100% !important;
table-layout: auto;
}
/* 确保卡片内容区域占满宽度 */
.content-card :deep(.el-card__body) {
width: 100%;
padding: 0;
}
/* 响应式设计 */
@media (max-width: 768px) {
.card-header {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.search-form {
display: flex;
flex-direction: column;
gap: 10px;
}
.el-form--inline .el-form-item {
width: 100%;
margin-right: 0;
}
}
</style>

View File

@ -135,7 +135,32 @@
<div v-if="passwordError" class="error-message">{{ passwordError }}</div> <div v-if="passwordError" class="error-message">{{ passwordError }}</div>
</div> </div>
<!-- 协议勾选登录和注册时显示重置密码时不显示 -->
<div v-if="loginMode !== 'reset'" class="agreement-checkbox">
<label class="checkbox-label">
<input
type="checkbox"
v-model="agreementChecked"
class="checkbox-input"
/>
<span class="checkbox-text">
{{ t('login.agreement_prefix') }}
<a
class="agreement-link"
@click="goToAgreement('user_agreement')"
>
{{ t('login.user_agreement') }}
</a>
{{ t('login.agreement_and') }}
<a
class="agreement-link"
@click="goToAgreement('privacy_policy')"
>
{{ t('login.privacy_policy') }}
</a>
</span>
</label>
</div>
<!-- 登录/注册按钮 --> <!-- 登录/注册按钮 -->
<button <button
@ -169,10 +194,13 @@
<script setup> <script setup>
import { ref, computed, watch } from 'vue' import { ref, computed, watch } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { WarningFilled, View, Hide } from '@element-plus/icons-vue' import { WarningFilled, View, Hide } from '@element-plus/icons-vue'
import { useVuelidate } from '@vuelidate/core' import { useVuelidate } from '@vuelidate/core'
import { required, minLength } from '@vuelidate/validators' import { required, minLength } from '@vuelidate/validators'
const { t } = useI18n() const { t } = useI18n()
const router = useRouter()
const emit = defineEmits(['login', 'codeLogin', 'register', 'resetPassword', 'resetSuccess', 'sendCode']) const emit = defineEmits(['login', 'codeLogin', 'register', 'resetPassword', 'resetSuccess', 'sendCode'])
const props = defineProps({ const props = defineProps({
loading: { loading: {
@ -209,6 +237,9 @@ const passwordError = ref('')
const countdown = ref(0) const countdown = ref(0)
const canSendCode = ref(true) const canSendCode = ref(true)
//
const agreementChecked = ref(false)
// //
const rules = { const rules = {
phone: { required }, phone: { required },
@ -233,12 +264,12 @@ const isPhoneValid = computed(() => {
const isFormValid = computed(() => { const isFormValid = computed(() => {
// //
if (loginMode.value === 'password' && loginMethod.value === 'code') { if (loginMode.value === 'password' && loginMethod.value === 'code') {
return !!form.value.phone && !!form.value.code && !phoneError.value && !codeError.value return !!form.value.phone && !!form.value.code && !phoneError.value && !codeError.value && agreementChecked.value
} }
// //
if (loginMode.value === 'password' && loginMethod.value === 'password') { if (loginMode.value === 'password' && loginMethod.value === 'password') {
return !!form.value.phone && !!form.value.password && !phoneError.value && !passwordError.value return !!form.value.phone && !!form.value.password && !phoneError.value && !passwordError.value && agreementChecked.value
} }
// //
@ -246,7 +277,7 @@ const isFormValid = computed(() => {
return false return false
} }
return !phoneError.value && !codeError.value && !passwordError.value return !phoneError.value && !codeError.value && !passwordError.value && agreementChecked.value
}) })
// //
@ -386,7 +417,15 @@ const toggleLoginMode = (mode, method = 'password') => {
phoneError.value = '' phoneError.value = ''
codeError.value = '' codeError.value = ''
passwordError.value = '' passwordError.value = ''
//
agreementChecked.value = false
} }
//
const goToAgreement = (type) => {
router.push(`/agreement/${type}`)
}
// //
defineExpose({ defineExpose({
toggleLoginMode toggleLoginMode
@ -689,6 +728,63 @@ defineExpose({
} }
} }
/* 协议勾选框 */
.agreement-checkbox {
margin-top: 8px;
}
.checkbox-label {
display: flex;
align-items: flex-start;
gap: 8px;
cursor: pointer;
user-select: none;
}
.checkbox-input {
width: 16px;
height: 16px;
margin-top: 2px;
cursor: pointer;
accent-color: #7C3AED;
border: 2px solid #D1D5DB;
border-radius: 4px;
transition: all 0.2s ease;
}
.checkbox-input:hover {
border-color: #7C3AED;
}
.checkbox-input:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.2);
}
.checkbox-text {
font-size: 13px;
color: #6B7280;
line-height: 1.5;
flex: 1;
}
.agreement-link {
color: #7C3AED;
text-decoration: none;
font-weight: 500;
transition: all 0.2s ease;
cursor: pointer;
}
.agreement-link:hover {
color: #6B46C1;
text-decoration: underline;
}
.agreement-link:active {
color: #5B21B6;
}
/* 响应式设计 */ /* 响应式设计 */
@media (max-width: 768px) { @media (max-width: 768px) {
.form-input { .form-input {
@ -748,6 +844,14 @@ defineExpose({
padding: 8px 12px; padding: 8px 12px;
font-size: 13px; font-size: 13px;
} }
.agreement-checkbox {
margin-top: 6px;
}
.checkbox-text {
font-size: 12px;
}
} }
/* 暗色主题样式 */ /* 暗色主题样式 */
@ -829,6 +933,32 @@ html.dark .send-code-button:hover:not(:disabled) {
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.4); box-shadow: 0 4px 12px rgba(139, 92, 246, 0.4);
} }
/* 暗色主题协议勾选框 */
html.dark .checkbox-input {
border-color: #4B5563;
background: rgba(31, 41, 55, 0.8);
}
html.dark .checkbox-input:hover {
border-color: #8B5CF6;
}
html.dark .checkbox-text {
color: #9CA3AF;
}
html.dark .agreement-link {
color: #A78BFA;
}
html.dark .agreement-link:hover {
color: #C4B5FD;
}
html.dark .agreement-link:active {
color: #8B5CF6;
}
html.dark .send-code-button:active:not(:disabled) { html.dark .send-code-button:active:not(:disabled) {
box-shadow: 0 2px 6px rgba(139, 92, 246, 0.3); box-shadow: 0 2px 6px rgba(139, 92, 246, 0.3);
} }

View File

@ -60,13 +60,13 @@
</el-avatar> </el-avatar>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item command="profile"> <!-- <el-dropdown-item command="profile">
<UserIcon class="dropdown-item-icon" /> <UserIcon class="dropdown-item-icon" />
{{ t('header.profile') }} {{ t('header.profile') }}
</el-dropdown-item> </el-dropdown-item> -->
<el-dropdown-item command="settings"> <!-- <el-dropdown-item command="settings">
{{ t('header.settings') }} {{ t('header.settings') }}
</el-dropdown-item> </el-dropdown-item> -->
<el-dropdown-item divided command="logout"> <el-dropdown-item divided command="logout">
{{ t('header.logout') }} {{ t('header.logout') }}
</el-dropdown-item> </el-dropdown-item>

View File

@ -742,6 +742,11 @@ export default {
phone_code_login_method: '验证码登录', phone_code_login_method: '验证码登录',
phone_password_login_method: '密码登录', phone_password_login_method: '密码登录',
phone_code_login_button: '登录', phone_code_login_button: '登录',
agreement_prefix: '我已阅读并同意',
user_agreement: '《用户协议》',
privacy_policy: '《隐私政策》',
agreement_and: '和',
agreement_required: '请先阅读并同意用户协议和隐私政策',
}, },
payment: { payment: {
methods: '支付方式', methods: '支付方式',
@ -1214,10 +1219,19 @@ export default {
selectEndTime: '选择结束时间', selectEndTime: '选择结束时间',
inputEmail: '请输入邮箱', inputEmail: '请输入邮箱',
optional: '可选', optional: '可选',
loading: '加载中...',
retry: '重试',
validation: { validation: {
referenceImageRequired: '请上传参考图像或选择草图以继续生成' referenceImageRequired: '请上传参考图像或选择草图以继续生成'
} }
}, },
agreement: {
title: '协议',
userAgreement: '用户协议',
privacyPolicy: '隐私政策',
termsOfService: '服务条款',
loadFailed: '加载协议失败'
},
userCenter: { userCenter: {
title: '用户中心', title: '用户中心',
description: '管理您的账户信息和设置', description: '管理您的账户信息和设置',
@ -2428,6 +2442,11 @@ export default {
phone_code_login_method: 'Code Login', phone_code_login_method: 'Code Login',
phone_password_login_method: 'Password Login', phone_password_login_method: 'Password Login',
phone_code_login_button: 'Sign in', phone_code_login_button: 'Sign in',
agreement_prefix: 'I have read and agree to the',
user_agreement: 'User Agreement',
privacy_policy: 'Privacy Policy',
agreement_and: 'and',
agreement_required: 'Please read and agree to the User Agreement and Privacy Policy first',
}, },
payment: { payment: {
methods: 'Payment Methods', methods: 'Payment Methods',
@ -2903,10 +2922,19 @@ export default {
selectEndTime: 'Select End Time', selectEndTime: 'Select End Time',
inputEmail: 'Please enter email', inputEmail: 'Please enter email',
optional: 'Optional', optional: 'Optional',
loading: 'Loading...',
retry: 'Retry',
validation: { validation: {
referenceImageRequired: 'Please upload a reference image or select a sketch to continue generation' referenceImageRequired: 'Please upload a reference image or select a sketch to continue generation'
} }
}, },
agreement: {
title: 'Agreement',
userAgreement: 'User Agreement',
privacyPolicy: 'Privacy Policy',
termsOfService: 'Terms of Service',
loadFailed: 'Failed to load agreement'
},
iPandCardLeft: { iPandCardLeft: {
textPrompt: 'Text Prompt', textPrompt: 'Text Prompt',
placeholder: { placeholder: {

View File

@ -45,6 +45,12 @@ NProgress.configure({
})// 开启轻量模式(顶部细线) })// 开启轻量模式(顶部细线)
// 路由配置 // 路由配置
const routes = [ const routes = [
{
path: '/agreement/:type',
name: 'agreement',
component: () => import('../views/user/agreement.vue'),
meta: { requiresAuth: false, keepAlive: false, fullScreen: true }
},
{ {
path: '/', path: '/',
name: 'home', name: 'home',

View File

@ -154,6 +154,7 @@ const goToPhoneLogin = () => {
onMounted(() => { onMounted(() => {
// detectEnvironment() // detectEnvironment()
// isWeChatBrowser()&&goToPhoneLogin() // isWeChatBrowser()&&goToPhoneLogin()
goToPhoneLogin()
}) })
</script> </script>
@ -979,15 +980,19 @@ html.dark .error-icon {
} }
.auth-links-row { .auth-links-row {
display: flex; /* display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 16px; */
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px; gap: 16px;
} }
.auth-link { .auth-link {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
gap: 6px; gap: 6px;
background: none; background: none;
border: none; border: none;

View File

@ -0,0 +1,520 @@
<template>
<div class="agreement-page">
<div class="page-header">
<button class="back-button" @click="goBack">
<el-icon class="back-icon"><ArrowLeft /></el-icon>
<span class="back-text">{{ t('common.back') }}</span>
</button>
<!-- <h1 class="page-title">{{ pageTitle }}</h1> -->
</div>
<div class="content-container">
<div v-if="loading" class="loading-container">
<div class="loading-spinner"></div>
<p class="loading-text">{{ t('common.loading') }}</p>
</div>
<div v-else-if="error" class="error-container">
<div class="error-icon"></div>
<p class="error-text">{{ error }}</p>
<button class="retry-button" @click="getAgreement">{{ t('common.retry') }}</button>
</div>
<div v-else class="agreement-content" v-html="msg">
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { clientApi, requestUtils } from '@deotaland/utils'
import { ArrowLeft } from '@element-plus/icons-vue'
const router = useRouter()
const { t } = useI18n()
const route = useRoute()
const type = route.params.type
const msg = ref('')
const loading = ref(false)
const error = ref('')
const pageTitle = computed(() => {
const titles = {
'user-agreement': t('agreement.userAgreement'),
'privacy-policy': t('agreement.privacyPolicy'),
'terms-of-service': t('agreement.termsOfService')
}
return titles[type] || t('agreement.title')
})
const goBack = () => {
router.go(-1)
}
const getAgreement = async () => {
loading.value = true
error.value = ''
try {
const requestUrl = {
method: clientApi.default.getAgreement.method,
url: clientApi.default.getAgreement.url.replace('{type}', type),
}
const res = await requestUtils.common(requestUrl)
if (res.code === 0 && res.success) {
msg.value = res.data.content
} else {
error.value = res.message || t('agreement.loadFailed')
}
} catch (err) {
error.value = t('agreement.loadFailed')
console.error('获取协议失败:', err)
} finally {
loading.value = false
}
}
onMounted(() => {
getAgreement()
})
</script>
<style scoped>
.agreement-page {
min-height: 100vh;
background: linear-gradient(135deg, #f3f4f6 0%, #e9d5ff 100%);
display: flex;
flex-direction: column;
}
.page-header {
display: flex;
align-items: center;
gap: 16px;
padding: 20px 24px;
background: #ffffff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
position: sticky;
top: 0;
z-index: 100;
}
.back-button {
display: flex;
align-items: center;
gap: 6px;
color: #6B7280;
font-size: 14px;
font-weight: 500;
padding: 8px 12px;
border-radius: 8px;
transition: all 0.3s ease;
background: rgba(139, 92, 246, 0.1);
border: 1px solid transparent;
color: #8B5CF6;
cursor: pointer;
}
.back-button:hover {
background: rgba(139, 92, 246, 0.15);
color: #7C3AED;
transform: translateX(-2px);
}
.back-button:active {
transform: translateX(0);
}
.back-icon {
font-size: 18px;
transition: transform 0.3s ease;
}
.back-button:hover .back-icon {
transform: translateX(-2px);
}
.back-text {
font-size: 14px;
font-weight: 500;
}
.page-title {
font-size: 20px;
font-weight: 700;
color: #1F2937;
margin: 0;
flex: 1;
}
.content-container {
flex: 1;
padding: 24px;
max-width: 900px;
width: 100%;
margin: 0 auto;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 400px;
gap: 16px;
}
.loading-spinner {
width: 48px;
height: 48px;
border: 4px solid rgba(139, 92, 246, 0.2);
border-top-color: #8B5CF6;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.loading-text {
color: #6B7280;
font-size: 14px;
margin: 0;
}
.error-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 400px;
gap: 16px;
padding: 40px;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.error-icon {
font-size: 48px;
}
.error-text {
color: #EF4444;
font-size: 16px;
margin: 0;
text-align: center;
}
.retry-button {
padding: 10px 24px;
background: linear-gradient(135deg, #8B5CF6, #7C3AED);
color: #ffffff;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.retry-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.4);
}
.retry-button:active {
transform: translateY(0);
}
.agreement-content {
background: #ffffff;
border-radius: 12px;
padding: 32px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
line-height: 1.8;
color: #374151;
font-size: 15px;
}
.agreement-content :deep(h1),
.agreement-content :deep(h2),
.agreement-content :deep(h3),
.agreement-content :deep(h4),
.agreement-content :deep(h5),
.agreement-content :deep(h6) {
color: #1F2937;
margin-top: 24px;
margin-bottom: 12px;
font-weight: 600;
}
.agreement-content :deep(h1) {
font-size: 24px;
border-bottom: 2px solid rgba(139, 92, 246, 0.2);
padding-bottom: 12px;
}
.agreement-content :deep(h2) {
font-size: 20px;
color: #4B5563;
}
.agreement-content :deep(h3) {
font-size: 18px;
color: #6B7280;
}
.agreement-content :deep(p) {
margin-bottom: 16px;
}
.agreement-content :deep(ul),
.agreement-content :deep(ol) {
margin: 16px 0;
padding-left: 24px;
}
.agreement-content :deep(li) {
margin-bottom: 8px;
}
.agreement-content :deep(a) {
color: #8B5CF6;
text-decoration: none;
transition: color 0.3s ease;
}
.agreement-content :deep(a:hover) {
color: #7C3AED;
text-decoration: underline;
}
.agreement-content :deep(code) {
background: rgba(139, 92, 246, 0.1);
color: #7C3AED;
padding: 2px 6px;
border-radius: 4px;
font-size: 14px;
}
.agreement-content :deep(pre) {
background: #1F2937;
color: #F3F4F6;
padding: 16px;
border-radius: 8px;
overflow-x: auto;
margin: 16px 0;
}
.agreement-content :deep(blockquote) {
border-left: 4px solid #8B5CF6;
padding-left: 16px;
margin: 16px 0;
color: #6B7280;
font-style: italic;
}
.agreement-content :deep(table) {
width: 100%;
border-collapse: collapse;
margin: 16px 0;
}
.agreement-content :deep(th),
.agreement-content :deep(td) {
border: 1px solid #E5E7EB;
padding: 12px;
text-align: left;
}
.agreement-content :deep(th) {
background: rgba(139, 92, 246, 0.1);
color: #4B5563;
font-weight: 600;
}
.agreement-content :deep(img) {
max-width: 100%;
height: auto;
border-radius: 8px;
margin: 16px 0;
}
@media (max-width: 1024px) {
.content-container {
padding: 20px;
}
.agreement-content {
padding: 24px;
}
}
@media (max-width: 768px) {
.page-header {
padding: 16px 20px;
}
.page-title {
font-size: 18px;
}
.back-button {
padding: 6px 10px;
}
.back-text {
font-size: 13px;
}
.content-container {
padding: 16px;
}
.agreement-content {
padding: 20px;
font-size: 14px;
}
.agreement-content :deep(h1) {
font-size: 20px;
}
.agreement-content :deep(h2) {
font-size: 18px;
}
.agreement-content :deep(h3) {
font-size: 16px;
}
}
@media (max-width: 480px) {
.page-header {
padding: 12px 16px;
gap: 12px;
}
.page-title {
font-size: 16px;
}
.back-button {
padding: 6px 8px;
}
.back-text {
display: none;
}
.back-icon {
font-size: 20px;
}
.content-container {
padding: 12px;
}
.agreement-content {
padding: 16px;
font-size: 13px;
}
.agreement-content :deep(h1) {
font-size: 18px;
}
.agreement-content :deep(h2) {
font-size: 16px;
}
.agreement-content :deep(h3) {
font-size: 14px;
}
.agreement-content :deep(th),
.agreement-content :deep(td) {
padding: 8px;
font-size: 12px;
}
}
html.dark .agreement-page {
background: linear-gradient(135deg, #111827 0%, #1F2937 100%);
}
html.dark .page-header {
background: #1F2937;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
html.dark .page-title {
color: #F3F4F6;
}
html.dark .agreement-content {
background: #1F2937;
color: #D1D5DB;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
html.dark .agreement-content :deep(h1),
html.dark .agreement-content :deep(h2),
html.dark .agreement-content :deep(h3) {
color: #F3F4F6;
}
html.dark .agreement-content :deep(h2) {
color: #E5E7EB;
}
html.dark .agreement-content :deep(h3) {
color: #D1D5DB;
}
html.dark .agreement-content :deep(a) {
color: #A78BFA;
}
html.dark .agreement-content :deep(a:hover) {
color: #C4B5FD;
}
html.dark .agreement-content :deep(code) {
background: rgba(167, 139, 250, 0.2);
color: #C4B5FD;
}
html.dark .agreement-content :deep(blockquote) {
border-left-color: #A78BFA;
color: #9CA3AF;
}
html.dark .agreement-content :deep(th) {
background: rgba(167, 139, 250, 0.15);
color: #E5E7EB;
}
html.dark .agreement-content :deep(th),
html.dark .agreement-content :deep(td) {
border-color: #374151;
}
html.dark .error-container {
background: #1F2937;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
html.dark .error-text {
color: #F87171;
}
html.dark .loading-text {
color: #9CA3AF;
}
</style>

View File

@ -66,8 +66,8 @@ export default defineConfig({
// 配置代理解决CORS问题 // 配置代理解决CORS问题
proxy: { proxy: {
'/api': { '/api': {
target: 'https://api.deotaland.ai', // target: 'https://api.deotaland.ai',
// target: 'http://api.deotaland.local', target: 'http://api.deotaland.local',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') rewrite: (path) => path.replace(/^\/api/, '')
} }

View File

@ -0,0 +1,9 @@
const agreement = {
updateAgreementStatus:{url:'/api-base/admin/agreement/status/{id}/{status}',method:'POST'},// 修改协议状态
removeAgreement:{url:'/api-base/admin/agreement/remove/{id}',method:'POST'},// 删除协议
editAgreement:{url:'/api-base/admin/agreement/edit',method:'POST'},// 修改协议
addAgreement:{url:'/api-base/admin/agreement/add',method:'POST'},// 新增协议
getAgreementDetail:{url:'/api-base/admin/agreement/{id}',method:'GET'},// 查询协议详情
getAgreementList:{url:'/api-base/admin/agreement/list',method:'GET'},// 查询协议列表
}
export default agreement;

View File

@ -12,6 +12,7 @@ import seriespriceConfig from './seriespriceConfig.js';
import voucher from './voucher.js'; import voucher from './voucher.js';
import agent from './agent.js'; import agent from './agent.js';
import shop from './shop.js'; import shop from './shop.js';
import agreement from './agreement.js';
export default { export default {
...login, ...login,
...order, ...order,
@ -27,4 +28,5 @@ export default {
...voucher, ...voucher,
...agent, ...agent,
...shop, ...shop,
...agreement,
}; };

View File

@ -0,0 +1,4 @@
const agreement = {
getAgreement:{url:'/api-base/agreement/{type}',method:'GET'},// 根据协议类型获取协议内容 //协议类型: user_agreement/privacy_policy
}
export default agreement;

View File

@ -10,6 +10,7 @@ import agent from './agent.js';
import rechargeconfig from './rechargeconfig.js'; import rechargeconfig from './rechargeconfig.js';
import voucher from './voucher.js'; import voucher from './voucher.js';
import shop from './shop.js'; import shop from './shop.js';
import agreement from './agreement.js';
export default { export default {
...meshy, ...meshy,
...login, ...login,
@ -23,4 +24,5 @@ export default {
...rechargeconfig, ...rechargeconfig,
...voucher, ...voucher,
...shop, ...shop,
...agreement,
}; };

View File

@ -46,6 +46,12 @@ service.interceptors.request.use(
if (token) { if (token) {
// 将token添加到请求头 // 将token添加到请求头
config.headers['Authorization'] = `Bearer ${token}`; config.headers['Authorization'] = `Bearer ${token}`;
const lang = localStorage.getItem('lang');
if (lang =='zh') {
config.headers['accept-language'] = 'zh-CN';
} else if (lang == 'en') {
config.headers['accept-language'] = 'en-US';
}
// config.headers['token'] = `${token}`; // config.headers['token'] = `${token}`;
// config.headers['Authorization'] = `123`; // config.headers['Authorization'] = `123`;
// config.headers['token'] = `123`; // config.headers['token'] = `123`;

View File

@ -56,6 +56,12 @@ importers:
'@types/three': '@types/three':
specifier: ^0.180.0 specifier: ^0.180.0
version: 0.180.0 version: 0.180.0
'@wangeditor/editor':
specifier: ^5.1.23
version: 5.1.23
'@wangeditor/editor-for-vue':
specifier: ^5.1.12
version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.24)
element-china-area-data: element-china-area-data:
specifier: ^6.1.0 specifier: ^6.1.0
version: 6.1.0 version: 6.1.0
@ -1267,6 +1273,10 @@ packages:
tailwindcss: 4.1.17 tailwindcss: 4.1.17
dev: true dev: true
/@transloadit/prettier-bytes@0.0.7:
resolution: {integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==}
dev: false
/@tweenjs/tween.js@23.1.3: /@tweenjs/tween.js@23.1.3:
resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==}
dev: false dev: false
@ -1314,6 +1324,10 @@ packages:
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
dev: true dev: true
/@types/event-emitter@0.3.5:
resolution: {integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==}
dev: false
/@types/json-schema@7.0.15: /@types/json-schema@7.0.15:
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
dev: true dev: true
@ -1370,6 +1384,47 @@ packages:
'@types/node': 25.0.6 '@types/node': 25.0.6
dev: false dev: false
/@uppy/companion-client@2.2.2:
resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==}
dependencies:
'@uppy/utils': 4.1.3
namespace-emitter: 2.0.1
dev: false
/@uppy/core@2.3.4:
resolution: {integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==}
dependencies:
'@transloadit/prettier-bytes': 0.0.7
'@uppy/store-default': 2.1.1
'@uppy/utils': 4.1.3
lodash.throttle: 4.1.1
mime-match: 1.0.2
namespace-emitter: 2.0.1
nanoid: 3.3.11
preact: 10.28.2
dev: false
/@uppy/store-default@2.1.1:
resolution: {integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==}
dev: false
/@uppy/utils@4.1.3:
resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==}
dependencies:
lodash.throttle: 4.1.1
dev: false
/@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4):
resolution: {integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==}
peerDependencies:
'@uppy/core': ^2.3.3
dependencies:
'@uppy/companion-client': 2.2.2
'@uppy/core': 2.3.4
'@uppy/utils': 4.1.3
nanoid: 3.3.11
dev: false
/@vitejs/plugin-vue@6.0.1(vite@7.2.2)(vue@3.5.24): /@vitejs/plugin-vue@6.0.1(vite@7.2.2)(vue@3.5.24):
resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==} resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -1543,6 +1598,192 @@ packages:
- '@vue/composition-api' - '@vue/composition-api'
- vue - vue
/@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3):
resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==}
peerDependencies:
'@wangeditor/core': 1.x
dom7: ^3.0.0
lodash.throttle: ^4.1.1
nanoid: ^3.2.0
slate: ^0.72.0
snabbdom: ^3.1.0
dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0
is-url: 1.2.4
lodash.throttle: 4.1.1
nanoid: 3.3.11
slate: 0.72.8
snabbdom: 3.6.3
dev: false
/@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3):
resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==}
peerDependencies:
'@wangeditor/core': 1.x
dom7: ^3.0.0
slate: ^0.72.0
snabbdom: ^3.1.0
dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0
prismjs: 1.30.0
slate: 0.72.8
snabbdom: 3.6.3
dev: false
/@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3):
resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==}
peerDependencies:
'@uppy/core': ^2.1.1
'@uppy/xhr-upload': ^2.0.3
dom7: ^3.0.0
is-hotkey: ^0.2.0
lodash.camelcase: ^4.3.0
lodash.clonedeep: ^4.5.0
lodash.debounce: ^4.0.8
lodash.foreach: ^4.5.0
lodash.isequal: ^4.5.0
lodash.throttle: ^4.1.1
lodash.toarray: ^4.4.0
nanoid: ^3.2.0
slate: ^0.72.0
snabbdom: ^3.1.0
dependencies:
'@types/event-emitter': 0.3.5
'@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
dom7: 3.0.0
event-emitter: 0.3.5
html-void-elements: 2.0.1
i18next: 20.6.1
is-hotkey: 0.2.0
lodash.camelcase: 4.3.0
lodash.clonedeep: 4.5.0
lodash.debounce: 4.0.8
lodash.foreach: 4.5.0
lodash.isequal: 4.5.0
lodash.throttle: 4.1.1
lodash.toarray: 4.4.0
nanoid: 3.3.11
scroll-into-view-if-needed: 2.2.31
slate: 0.72.8
slate-history: 0.66.0(slate@0.72.8)
snabbdom: 3.6.3
dev: false
/@wangeditor/editor-for-vue@5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.24):
resolution: {integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==}
peerDependencies:
'@wangeditor/editor': '>=5.1.0'
vue: ^3.0.5
dependencies:
'@wangeditor/editor': 5.1.23
vue: 3.5.24
dev: false
/@wangeditor/editor@5.1.23:
resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==}
dependencies:
'@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/basic-modules@1.1.7)(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/video-module': 1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/core@1.1.19)(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0
is-hotkey: 0.2.0
lodash.camelcase: 4.3.0
lodash.clonedeep: 4.5.0
lodash.debounce: 4.0.8
lodash.foreach: 4.5.0
lodash.isequal: 4.5.0
lodash.throttle: 4.1.1
lodash.toarray: 4.4.0
nanoid: 3.3.11
slate: 0.72.8
snabbdom: 3.6.3
dev: false
/@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3):
resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==}
peerDependencies:
'@wangeditor/core': 1.x
dom7: ^3.0.0
slate: ^0.72.0
snabbdom: ^3.1.0
dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0
slate: 0.72.8
snabbdom: 3.6.3
dev: false
/@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3):
resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==}
peerDependencies:
'@wangeditor/core': 1.x
dom7: ^3.0.0
lodash.isequal: ^4.5.0
lodash.throttle: ^4.1.1
nanoid: ^3.2.0
slate: ^0.72.0
snabbdom: ^3.1.0
dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0
lodash.isequal: 4.5.0
lodash.throttle: 4.1.1
nanoid: 3.3.11
slate: 0.72.8
snabbdom: 3.6.3
dev: false
/@wangeditor/upload-image-module@1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/basic-modules@1.1.7)(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3):
resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==}
peerDependencies:
'@uppy/core': ^2.0.3
'@uppy/xhr-upload': ^2.0.3
'@wangeditor/basic-modules': 1.x
'@wangeditor/core': 1.x
dom7: ^3.0.0
lodash.foreach: ^4.5.0
slate: ^0.72.0
snabbdom: ^3.1.0
dependencies:
'@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0
lodash.foreach: 4.5.0
slate: 0.72.8
snabbdom: 3.6.3
dev: false
/@wangeditor/video-module@1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/core@1.1.19)(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3):
resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==}
peerDependencies:
'@uppy/core': ^2.1.4
'@uppy/xhr-upload': ^2.0.7
'@wangeditor/core': 1.x
dom7: ^3.0.0
nanoid: ^3.2.0
slate: ^0.72.0
snabbdom: ^3.1.0
dependencies:
'@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0
nanoid: 3.3.11
slate: 0.72.8
snabbdom: 3.6.3
dev: false
/@webgpu/types@0.1.66: /@webgpu/types@0.1.66:
resolution: {integrity: sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA==} resolution: {integrity: sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA==}
dev: false dev: false
@ -1793,6 +2034,10 @@ packages:
resolution: {integrity: sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==} resolution: {integrity: sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==}
dev: false dev: false
/compute-scroll-into-view@1.0.20:
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
dev: false
/concat-map@0.0.1: /concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: true dev: true
@ -1867,6 +2112,14 @@ packages:
/csstype@3.2.3: /csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
/d@1.0.2:
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
engines: {node: '>=0.12'}
dependencies:
es5-ext: 0.10.64
type: 2.7.3
dev: false
/data-uri-to-buffer@4.0.1: /data-uri-to-buffer@4.0.1:
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
engines: {node: '>= 12'} engines: {node: '>= 12'}
@ -1929,6 +2182,12 @@ packages:
entities: 2.2.0 entities: 2.2.0
dev: false dev: false
/dom7@3.0.0:
resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==}
dependencies:
ssr-window: 3.0.0
dev: false
/domelementtype@2.3.0: /domelementtype@2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
dev: false dev: false
@ -2071,6 +2330,33 @@ packages:
hasown: 2.0.2 hasown: 2.0.2
dev: false dev: false
/es5-ext@0.10.64:
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
engines: {node: '>=0.10'}
requiresBuild: true
dependencies:
es6-iterator: 2.0.3
es6-symbol: 3.1.4
esniff: 2.0.1
next-tick: 1.1.0
dev: false
/es6-iterator@2.0.3:
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
dependencies:
d: 1.0.2
es5-ext: 0.10.64
es6-symbol: 3.1.4
dev: false
/es6-symbol@3.1.4:
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
engines: {node: '>=0.12'}
dependencies:
d: 1.0.2
ext: 1.7.0
dev: false
/esbuild@0.25.12: /esbuild@0.25.12:
resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -2260,6 +2546,16 @@ packages:
- supports-color - supports-color
dev: true dev: true
/esniff@2.0.1:
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
engines: {node: '>=0.10'}
dependencies:
d: 1.0.2
es5-ext: 0.10.64
event-emitter: 0.3.5
type: 2.7.3
dev: false
/espree@10.4.0: /espree@10.4.0:
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -2311,6 +2607,13 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/event-emitter@0.3.5:
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
dependencies:
d: 1.0.2
es5-ext: 0.10.64
dev: false
/event-target-shim@5.0.1: /event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -2325,6 +2628,12 @@ packages:
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
dev: true dev: true
/ext@1.7.0:
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
dependencies:
type: 2.7.3
dev: false
/extend@3.0.2: /extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@ -2673,6 +2982,10 @@ packages:
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
dev: false dev: false
/html-void-elements@2.0.1:
resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
dev: false
/htmlparser2@6.1.0: /htmlparser2@6.1.0:
resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==}
dependencies: dependencies:
@ -2691,6 +3004,12 @@ packages:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
/i18next@20.6.1:
resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==}
dependencies:
'@babel/runtime': 7.28.4
dev: false
/ieee754@1.2.1: /ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: false dev: false
@ -2704,6 +3023,10 @@ packages:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
dev: false dev: false
/immer@9.0.21:
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
dev: false
/import-fresh@3.3.1: /import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -2754,11 +3077,24 @@ packages:
is-extglob: 2.1.1 is-extglob: 2.1.1
dev: true dev: true
/is-hotkey@0.2.0:
resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==}
dev: false
/is-path-inside@3.0.3: /is-path-inside@3.0.3:
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/is-plain-object@5.0.0:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
dev: false
/is-url@1.2.4:
resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==}
dev: false
/is-what@5.5.0: /is-what@5.5.0:
resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -3021,10 +3357,39 @@ packages:
lodash: 4.17.21 lodash: 4.17.21
lodash-es: 4.17.21 lodash-es: 4.17.21
/lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
dev: false
/lodash.clonedeep@4.5.0:
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
dev: false
/lodash.debounce@4.0.8:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
dev: false
/lodash.foreach@4.5.0:
resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==}
dev: false
/lodash.isequal@4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
dev: false
/lodash.merge@4.6.2: /lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
dev: true dev: true
/lodash.throttle@4.1.1:
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
dev: false
/lodash.toarray@4.4.0:
resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==}
dev: false
/lodash@4.17.21: /lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
@ -3053,6 +3418,12 @@ packages:
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
dev: false dev: false
/mime-match@1.0.2:
resolution: {integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==}
dependencies:
wildcard: 1.1.2
dev: false
/mime-types@2.1.35: /mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@ -3169,6 +3540,10 @@ packages:
/ms@2.1.3: /ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
/namespace-emitter@2.0.1:
resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==}
dev: false
/nanoid@3.3.11: /nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@ -3178,6 +3553,10 @@ packages:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true dev: true
/next-tick@1.1.0:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
dev: false
/node-domexception@1.0.0: /node-domexception@1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'} engines: {node: '>=10.5.0'}
@ -3402,6 +3781,10 @@ packages:
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.1
/preact@10.28.2:
resolution: {integrity: sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==}
dev: false
/prelude-ls@1.2.1: /prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -3419,6 +3802,11 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/prismjs@1.30.0:
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
engines: {node: '>=6'}
dev: false
/process-nextick-args@2.0.1: /process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: false dev: false
@ -3574,6 +3962,12 @@ packages:
/safe-buffer@5.2.1: /safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
/scroll-into-view-if-needed@2.2.31:
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
dependencies:
compute-scroll-into-view: 1.0.20
dev: false
/scule@1.3.0: /scule@1.3.0:
resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
dev: true dev: true
@ -3611,11 +4005,33 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'} engines: {node: '>=14'}
/slate-history@0.66.0(slate@0.72.8):
resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==}
peerDependencies:
slate: '>=0.65.3'
dependencies:
is-plain-object: 5.0.0
slate: 0.72.8
dev: false
/slate@0.72.8:
resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==}
dependencies:
immer: 9.0.21
is-plain-object: 5.0.0
tiny-warning: 1.0.3
dev: false
/smart-buffer@4.2.0: /smart-buffer@4.2.0:
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
dev: false dev: false
/snabbdom@3.6.3:
resolution: {integrity: sha512-W2lHLLw2qR2Vv0DcMmcxXqcfdBaIcoN+y/86SmHv8fn4DazEQSH6KN3TjZcWvwujW56OHiiirsbHWZb4vx/0fg==}
engines: {node: '>=12.17.0'}
dev: false
/socks@2.8.7: /socks@2.8.7:
resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==}
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
@ -3658,6 +4074,10 @@ packages:
engines: {node: '>= 10.x'} engines: {node: '>= 10.x'}
dev: false dev: false
/ssr-window@3.0.0:
resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==}
dev: false
/string-width@4.2.3: /string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -3788,6 +4208,10 @@ packages:
resolution: {integrity: sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==} resolution: {integrity: sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==}
dev: false dev: false
/tiny-warning@1.0.3:
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
dev: false
/tinyexec@1.0.2: /tinyexec@1.0.2:
resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -3896,6 +4320,10 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/type@2.7.3:
resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
dev: false
/typedarray@0.0.6: /typedarray@0.0.6:
resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
dev: false dev: false
@ -4289,6 +4717,10 @@ packages:
dependencies: dependencies:
isexe: 2.0.0 isexe: 2.0.0
/wildcard@1.1.2:
resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==}
dev: false
/word-wrap@1.2.5: /word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}