并入后台管理端(vue)和小程序端的代码(template-10550)

This commit is contained in:
2025-08-08 23:04:17 +08:00
parent a0f4fcc03f
commit b0f9eaefa1
1452 changed files with 241138 additions and 0 deletions

59
template-10550/CONFIG.md Normal file
View File

@@ -0,0 +1,59 @@
# 配置说明文档
## 环境配置
### 1. 复制环境变量文件
```bash
cp .env.example .env
```
### 2. 修改配置文件
#### config/app.ts
```typescript
// 租户ID - 请根据实际情况修改
export const TenantId = 'YOUR_TENANT_ID';
// 接口地址 - 请根据实际情况修改
export const BaseUrl = 'https://your-api-domain.com/api';
```
#### src/utils/server.ts
```typescript
// 模版套餐ID - 请根据实际情况修改
export const TEMPLATE_ID = 'YOUR_TEMPLATE_ID';
// 服务接口 - 请根据实际情况修改
export const SERVER_API_URL = 'https://your-server-domain.com/api';
```
#### project.config.json
```json
{
"appid": "your_wechat_appid"
}
```
### 3. 小程序配置
#### 微信小程序
1. 在微信公众平台申请小程序
2. 获取AppID并填入 `project.config.json`
3. 配置服务器域名白名单
#### 支付宝小程序
1. 在支付宝开放平台申请小程序
2. 获取AppID并配置相应文件
#### 字节跳动小程序
1. 在字节跳动开发者平台申请小程序
2. 获取AppID并填入 `project.tt.json`
### 4. API配置
确保后端API服务正常运行并配置正确的域名和端口。
### 5. 安全注意事项
- 不要将真实的AppID、API密钥等敏感信息提交到公开仓库
- 使用环境变量管理敏感配置
- 定期更新密码和密钥
- 在生产环境中启用HTTPS

201
template-10550/LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

592
template-10550/README.md Normal file
View File

@@ -0,0 +1,592 @@
<div align="center">
<h1>🚀 WebSoft 小程序</h1>
<p><strong>基于 Taro + React + TypeScript 的跨平台小程序应用</strong></p>
<p>
<img src="https://img.shields.io/badge/Taro-4.0.8-blue" alt="Taro">
<img src="https://img.shields.io/badge/React-18.3.1-61DAFB" alt="React">
<img src="https://img.shields.io/badge/TypeScript-5.7.2-3178C6" alt="TypeScript">
<img src="https://img.shields.io/badge/NutUI-3.0.16-orange" alt="NutUI">
<img src="https://img.shields.io/badge/TailwindCSS-3.4.17-38B2AC" alt="TailwindCSS">
<img src="https://img.shields.io/badge/License-MIT-blue" alt="License">
</p>
</div>
## 📖 项目简介
WebSoft 小程序是一个基于 **Taro + React + TypeScript** 构建的现代化跨平台小程序应用,支持多端发布:
- **核心框架**Taro 4.0.8 + React 18.3.1 + TypeScript 5.7.2
- **UI组件库**NutUI React Taro 2.7.4 + NutUI Icons
- **样式方案**Sass + TailwindCSS 3.4.17
- **状态管理**React Hooks + Context API
- **工具库**Day.js、Crypto-js、React Router DOM
## 🎯 支持平台
本项目基于 Taro 框架,支持一套代码多端运行:
- **微信小程序** (weapp)
- **支付宝小程序** (alipay)
- **百度智能小程序** (swan)
- **字节跳动小程序** (tt)
- **QQ小程序** (qq)
- **京东小程序** (jd)
- **H5网页** (h5)
- **React Native** (rn)
- **快应用** (quickapp)
## 项目演示
| 后台管理系统 | https://mp.websoft.top |
|--------|-------------------------------------------------------------------------------------------------------------------------------------|
| 演示账号 | 请联系开发者获取演示账号
| 正式账号 | [立即注册](https://mp.websoft.top/register/?inviteCode=github) |
| 关注公众号 | ![输入图片说明](https://oss.wsdns.cn/20240327/f1175cc5aae741d3af05484747270bd5.jpeg?x-oss-process=image/resize,m_fixed,w_150/quality,Q_90) |
## 🛠️ 技术栈
### 核心框架
| 技术 | 版本 | 说明 |
|------|------|------|
| Taro | 4.0.8 | 跨平台开发框架 |
| React | 18.3.1 | 前端UI框架 |
| TypeScript | 5.7.2 | 类型安全的JavaScript |
| Webpack | 5.78.0 | 模块打包工具 |
| Babel | 7.26.0 | JavaScript编译器 |
| PostCSS | 8.4.49 | CSS后处理器 |
| ESLint | 8.57.1 | 代码质量检查 |
### UI组件库
| 技术 | 版本 | 说明 |
|------|------|------|
| NutUI React Taro | 2.7.4 | 移动端组件库 |
| NutUI Icons | 2.0.1 | 图标库 |
| NutUI Biz | 1.0.0-beta.2 | 业务组件库 |
### 样式方案
| 技术 | 版本 | 说明 |
|------|------|------|
| Sass | - | CSS预处理器 |
| TailwindCSS | 3.4.17 | 原子化CSS框架 |
| Autoprefixer | 10.4.20 | CSS自动前缀 |
### 功能组件
- **React Router DOM** - 路由管理
- **Day.js** - 日期时间处理
- **Crypto-js** - 加密解密工具
- **js-base64** - Base64编码解码
- **React Markdown** - Markdown渲染
- **ECharts Taro3 React** - 图表组件
## 📋 环境要求
### 基础环境
- 📦 **Node.js 16+**
- 📱 **微信开发者工具** (开发微信小程序)
- 🔧 **支付宝开发者工具** (开发支付宝小程序)
- 🌐 **现代浏览器** (开发H5应用)
### 包管理器
- **npm** / **yarn** / **pnpm** (推荐使用pnpm)
### 开发工具
- **推荐**VS Code / WebStorm
- **插件**ES7+ React/Redux/React-Native snippets、TypeScript Importer
## 🚀 快速开始
### 1. 克隆项目
```bash
git clone https://github.com/websoft-top/mp-taro.git
cd mp-taro
```
### 2. 安装依赖
```bash
# 使用 pnpm (推荐)
pnpm install
# 或使用 npm
npm install
# 或使用 yarn
yarn install
```
### 3. 配置开发环境
#### 环境变量配置
项目支持多环境配置,通过 `config/env.ts` 文件管理不同环境的配置:
```typescript
// config/env.ts
export const ENV_CONFIG = {
// 开发环境
development: {
API_BASE_URL: 'http://localhost:3000/api',
APP_NAME: 'Taro App Dev',
DEBUG: 'true',
},
// 生产环境
production: {
API_BASE_URL: 'https://api.example.com',
APP_NAME: 'Taro App',
DEBUG: 'false',
},
// 测试环境
test: {
API_BASE_URL: 'https://test-api.example.com',
APP_NAME: 'Taro App Test',
DEBUG: 'true',
}
}
```
#### 应用配置
编辑 `config/app.ts` 文件配置租户ID等信息
```typescript
export const TenantId = 'your_tenant_id'
export const BaseUrl = API_BASE_URL // 自动从环境配置读取
```
### 4. 启动开发服务器
#### 微信小程序开发
```bash
# 开发环境(默认)
npm run dev:weapp
# 生产环境
NODE_ENV=production npm run dev:weapp
# 测试环境
NODE_ENV=test npm run dev:weapp
```
然后使用微信开发者工具打开 `dist` 目录
#### H5开发
```bash
# 启动H5开发模式
npm run dev:h5
```
访问 `http://localhost:10086` 查看H5版本
#### 其他平台
```bash
# 支付宝小程序
npm run dev:alipay
# 百度智能小程序
npm run dev:swan
# 字节跳动小程序
npm run dev:tt
# QQ小程序
npm run dev:qq
# 京东小程序
npm run dev:jd
```
## ⚙️ 配置说明
### 项目配置
主要配置文件位于 `config/` 目录:
- `config/index.ts` - Taro主配置文件
- `config/dev.ts` - 开发环境配置
- `config/prod.ts` - 生产环境配置
- `config/env.ts` - 环境变量配置(新增)
- `config/app.ts` - 应用配置API地址、租户ID等
### 环境变量配置
项目支持多环境配置,在 `config/env.ts` 中管理:
```typescript
// 环境变量配置
export const ENV_CONFIG = {
development: {
API_BASE_URL: 'http://localhost:3000/api',
APP_NAME: 'Taro App Dev',
DEBUG: 'true',
},
production: {
API_BASE_URL: 'https://api.example.com',
APP_NAME: 'Taro App',
DEBUG: 'false',
},
test: {
API_BASE_URL: 'https://test-api.example.com',
APP_NAME: 'Taro App Test',
DEBUG: 'true',
}
}
// 获取当前环境配置
export function getEnvConfig() {
const env = process.env.NODE_ENV || 'development'
if (env === 'production') {
return ENV_CONFIG.production
} else if (env === 'test') {
return ENV_CONFIG.test
} else {
return ENV_CONFIG.development
}
}
// 导出环境变量
export const { API_BASE_URL, APP_NAME, DEBUG } = getEnvConfig()
```
### 应用配置
`config/app.ts` 中配置:
```typescript
import { API_BASE_URL } from './env'
// 租户ID
export const TenantId = 'your_tenant_id'
// API基础地址自动从环境配置读取
export const BaseUrl = API_BASE_URL
// 其他配置...
```
### 环境切换
通过设置 `NODE_ENV` 环境变量来切换不同环境:
```bash
# 开发环境(默认)
npm run dev:weapp
# 生产环境
NODE_ENV=production npm run dev:weapp
# 测试环境
NODE_ENV=test npm run dev:weapp
```
## 🌍 环境变量详细说明
### 环境变量文件结构
```
config/
├── env.ts # 环境变量配置文件
├── app.ts # 应用配置(使用环境变量)
└── index.ts # Taro配置注入环境变量
```
### 支持的环境变量
| 变量名 | 说明 | 开发环境默认值 | 生产环境建议值 |
|--------|------|---------------|---------------|
| `API_BASE_URL` | API基础地址 | `http://localhost:3000/api` | `https://api.yourdomain.com/api` |
| `APP_NAME` | 应用名称 | `Taro App Dev` | `Your App Name` |
| `DEBUG` | 调试模式 | `true` | `false` |
### 环境变量使用方法
#### 1. 修改环境配置
编辑 `config/env.ts` 文件:
```typescript
export const ENV_CONFIG = {
development: {
API_BASE_URL: 'http://localhost:3000/api', // 修改为你的开发环境API地址
APP_NAME: 'My App Dev',
DEBUG: 'true',
},
production: {
API_BASE_URL: 'https://api.yourdomain.com/api', // 修改为你的生产环境API地址
APP_NAME: 'My App',
DEBUG: 'false',
}
}
```
#### 2. 在代码中使用环境变量
```typescript
// 在 config/app.ts 中
import { API_BASE_URL, APP_NAME, DEBUG } from './env'
export const BaseUrl = API_BASE_URL
export const AppName = APP_NAME
export const IsDebug = DEBUG === 'true'
// 在其他文件中使用
import { BaseUrl } from '@/config/app'
console.log('API地址:', BaseUrl)
```
#### 3. 运行时环境切换
```bash
# 开发环境(默认)
npm run dev:weapp
# 生产环境
NODE_ENV=production npm run dev:weapp
# 测试环境
NODE_ENV=test npm run dev:weapp
# 构建生产版本
NODE_ENV=production npm run build:weapp
```
### 环境变量最佳实践
1. **敏感信息处理**:不要在代码中硬编码敏感信息,使用环境变量管理
2. **环境隔离**确保不同环境使用不同的API地址和配置
3. **默认值设置**:为所有环境变量提供合理的默认值
4. **类型安全**使用TypeScript确保环境变量的类型安全
### 路径别名配置
项目已配置路径别名,可以使用以下方式导入:
```typescript
import Component from '@/components/Component'
import { request } from '@/utils/request'
import { useCart } from '@/hooks/useCart'
import config from '@/config/app'
```
### 样式配置
- **Sass**: 支持嵌套、变量、混入等特性
- **TailwindCSS**: 原子化CSS配置文件为 `tailwind.config.js`
- **PostCSS**: 自动处理CSS兼容性配置文件为 `postcss.config.js`
## 🎯 核心功能
### 🔐 用户认证与授权
- **微信登录**基于微信OpenID的用户认证
- **短信登录**:支持手机号短信验证登录
- **用户注册**:完整的用户注册流程
- **密码找回**:支持手机号找回密码
### 📝 内容管理系统(CMS)
- **文章浏览**:支持文章列表和详情查看
- **分类管理**:内容分类浏览
- **富文本渲染**支持Markdown内容渲染
- **媒体展示**:图片、视频等媒体文件展示
### 🛒 电商系统
- **商品展示**:商品列表、详情、分类浏览
- **购物车**:商品加入购物车、数量管理
- **订单管理**:订单创建、查看、状态跟踪
- **地址管理**:收货地址的增删改查
- **支付集成**:支持微信支付等支付方式
### 👤 用户中心
- **个人资料**:用户信息查看和编辑
- **实名认证**:用户身份验证功能
- **帮助中心**:常见问题和帮助文档
- **关于我们**:应用介绍和联系方式
- **设置中心**:个人偏好设置
### 📊 数据可视化
- **图表展示**基于ECharts的数据可视化
- **统计分析**:业务数据统计展示
- **实时更新**:动态数据更新
## 🏗️ 项目结构
```
src/
├── app.config.ts # 应用配置文件
├── app.scss # 全局样式
├── app.ts # 应用入口文件
├── api/ # API接口定义
│ ├── cms/ # 内容管理相关API
│ ├── shop/ # 商城相关API
│ ├── system/ # 系统相关API
│ ├── passport/ # 用户认证相关API
│ └── index.ts # API统一导出
├── assets/ # 静态资源
│ └── tabbar/ # 底部导航图标
├── components/ # 公共组件
│ ├── Header.tsx # 页面头部组件
│ ├── TabBar.tsx # 底部导航组件
│ ├── GoodsList.tsx # 商品列表组件
│ └── ...
├── hooks/ # 自定义Hooks
│ └── useCart.ts # 购物车Hook
├── pages/ # 页面文件
│ ├── index/ # 首页
│ ├── cart/ # 购物车页面
│ ├── order/ # 订单页面
│ └── user/ # 用户中心页面
├── passport/ # 用户认证页面
│ ├── login.tsx # 登录页面
│ ├── register.tsx # 注册页面
│ └── ...
├── cms/ # 内容管理页面
│ ├── category/ # 分类页面
│ └── detail/ # 详情页面
├── shop/ # 商城页面
│ ├── category/ # 商品分类
│ ├── goodsDetail/ # 商品详情
│ ├── orderConfirm/ # 订单确认
│ └── orderDetail/ # 订单详情
├── user/ # 用户相关页面
│ ├── profile/ # 个人资料
│ ├── address/ # 地址管理
│ ├── setting/ # 设置
│ └── ...
└── utils/ # 工具函数
├── request.ts # 网络请求封装
├── common.ts # 通用工具函数
├── time.ts # 时间处理工具
└── server.ts # 服务端相关工具
config/ # 配置文件目录
├── index.ts # Taro主配置
├── dev.ts # 开发环境配置
├── prod.ts # 生产环境配置
├── env.ts # 环境变量配置
└── app.ts # 应用配置
types/ # 类型定义
└── global.d.ts # 全局类型定义
```
## 🔧 开发规范
### 代码结构
- **Pages**页面组件负责页面逻辑和UI展示
- **Components**公共组件可复用的UI组件
- **Hooks**自定义Hooks封装业务逻辑
- **Utils**:工具函数,通用的功能函数
- **API**接口定义与后端API的交互
### 命名规范
- **组件名**使用大驼峰命名法PascalCase
- **文件名**使用小驼峰命名法camelCase或短横线命名法kebab-case
- **变量名**使用小驼峰命名法camelCase
- **常量**:使用全大写,下划线分隔
- **CSS类名**使用短横线命名法kebab-case
### TypeScript规范
- 优先使用接口interface定义类型
- 为函数参数和返回值添加类型注解
- 使用泛型提高代码复用性
- 避免使用 `any` 类型
## 📚 构建与部署
### 构建命令
```bash
# 构建微信小程序
npm run build:weapp
# 构建H5应用
npm run build:h5
# 构建支付宝小程序
npm run build:alipay
# 构建其他平台
npm run build:swan # 百度智能小程序
npm run build:tt # 字节跳动小程序
npm run build:qq # QQ小程序
npm run build:jd # 京东小程序
```
### 主要API模块
项目API按功能模块组织
- **用户认证**: `src/api/passport/` - 登录、注册、权限验证
- **用户管理**: `src/api/system/user/` - 用户信息管理
- **内容管理**: `src/api/cms/` - 文章、媒体文件管理
- **商城管理**: `src/api/shop/` - 商品、订单管理
- **系统管理**: `src/api/system/` - 系统配置、参数管理
## 🚀 部署指南
### 微信小程序部署
1. 构建小程序代码:
```bash
npm run build:weapp
```
2. 使用微信开发者工具打开 `dist` 目录
3. 点击"上传"按钮,上传代码到微信后台
4. 在微信公众平台提交审核
### H5应用部署
1. 构建H5应用
```bash
npm run build:h5
```
2. 将 `dist` 目录下的文件上传到Web服务器
3. 配置Nginx或Apache服务器
4. 确保HTTPS访问微信要求
### 其他平台部署
各平台部署流程类似,构建对应平台代码后,使用相应的开发者工具上传即可。
### 生产环境配置
在生产环境中,需要修改相关配置:
1. **环境变量配置**:修改 `config/env.ts` 中的生产环境配置
```typescript
production: {
API_BASE_URL: 'https://your-production-api.com/api',
APP_NAME: 'Your App Name',
DEBUG: 'false',
}
```
2. **构建配置**:修改 `config/prod.ts` 中的构建配置
- 启用代码压缩和混淆
- 配置CDN加速
- 优化资源加载
3. **部署命令**
```bash
NODE_ENV=production npm run build:weapp
```
## 🔧 常见问题
### 开发环境问题
1. **Node.js版本问题**确保使用Node.js 16+版本
2. **依赖安装失败**:尝试清除缓存后重新安装
```bash
npm cache clean --force
npm install
```
3. **编译错误**检查TypeScript配置和代码语法
### 小程序开发问题
1. **微信开发者工具无法预览**检查appid配置和网络连接
2. **API请求失败**:确认后端服务正常运行,检查域名白名单
3. **样式显示异常**检查rpx单位使用和NutUI组件样式
### 性能优化建议
1. **代码分割**使用Taro的分包功能减少主包大小
2. **图片优化**使用WebP格式启用图片懒加载
3. **请求优化**合并API请求使用缓存机制
## 🤝 贡献指南
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 打开 Pull Request
## 📄 许可证
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情
## 📞 联系我们
- 官网https://websoft.top
- 邮箱170083662@qq.com
- QQ群479713884
---
⭐ 如果这个项目对您有帮助,请给我们一个星标!

View File

@@ -0,0 +1,24 @@
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
presets: [
['taro',
{
framework: 'react',
ts: 'true',
compiler: 'webpack5',
}]
],
plugins: [
[
"import",
{
"libraryName": "@nutui/nutui-react-taro",
"libraryDirectory": "dist/esm",
"style": 'css',
"camel2DashComponentName": false
},
'nutui-react-taro'
]
]
}

View File

@@ -0,0 +1,12 @@
import { API_BASE_URL } from './env'
// 租户ID - 请根据实际情况修改
export const TenantId = '10550';
// 接口地址 - 请根据实际情况修改
export const BaseUrl = API_BASE_URL;
// 当前版本
export const Version = 'v3.0.8';
// 版权信息
export const Copyright = 'WebSoft Inc.';
// java -jar CertificateDownloader.jar -k 0kF5OlPr482EZwtn9zGufUcqa7ovgxRL -m 1723321338 -f ./apiclient_key.pem -s 2B933F7C35014A1C363642623E4A62364B34C4EB -o ./

View File

@@ -0,0 +1,13 @@
import type { UserConfigExport } from "@tarojs/cli";
export default {
logger: {
quiet: false,
stats: true
},
mini: {
miniCssExtractPluginOption: {
ignoreOrder: true
}
},
h5: {}
} satisfies UserConfigExport<'webpack5'>

View File

@@ -0,0 +1,42 @@
// 环境变量配置
export const ENV_CONFIG = {
// 开发环境
development: {
API_BASE_URL: 'https://cms-api.websoft.top/api',
APP_NAME: '时里院子市集',
DEBUG: 'true',
},
// 生产环境
production: {
API_BASE_URL: 'https://cms-api.websoft.top/api',
APP_NAME: '时里院子市集',
DEBUG: 'false',
},
// 测试环境
test: {
API_BASE_URL: 'https://test-api.example.com/api',
APP_NAME: 'Taro App Test',
DEBUG: 'true',
}
}
// 获取当前环境配置
export function getEnvConfig() {
const env = process.env.NODE_ENV || 'development'
if (env === 'production') {
return ENV_CONFIG.production
} else { // @ts-ignore
if (env === 'test') {
return ENV_CONFIG.test
} else {
return ENV_CONFIG.development
}
}
}
// 导出环境变量
export const {
API_BASE_URL,
APP_NAME,
DEBUG
} = getEnvConfig()

View File

@@ -0,0 +1,118 @@
import { defineConfig, type UserConfigExport } from '@tarojs/cli'
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'
import devConfig from './dev'
import prodConfig from './prod'
import { getEnvConfig } from './env'
// import vitePluginImp from 'vite-plugin-imp'
// https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数
export default defineConfig<'webpack5'>(async (merge, {}) => {
const baseConfig: UserConfigExport<'webpack5'> = {
projectName: 'websoft-react',
date: '2024-12-30',
plugins: ['@tarojs/plugin-html'],
designWidth (input:any) {
// 配置 NutUI 375 尺寸
if (input?.file?.replace(/\\+/g, '/').indexOf('@nutui') > -1) {
return 375
}
// 全局使用 Taro 默认的 750 尺寸
return 750
},
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2,
375: 2 / 1
},
sourceRoot: 'src',
outputRoot: 'dist',
defineConstants: {
API_BASE_URL: JSON.stringify(getEnvConfig().API_BASE_URL),
APP_NAME: JSON.stringify(getEnvConfig().APP_NAME),
DEBUG: JSON.stringify(getEnvConfig().DEBUG)
},
copy: {
patterns: [
],
options: {
}
},
framework: 'react',
compiler: {
type: 'webpack5',
prebundle: {
exclude: ['@nutui/nutui-react-taro', '@nutui/icons-react-taro'],
enable: false
}
},
cache: {
enable: false // Webpack 持久化缓存配置建议开启。默认配置请参考https://docs.taro.zone/docs/config-detail#cache
},
mini: {
postcss: {
pxtransform: {
enable: true,
config: {
selectorBlackList: ['nut-']
}
},
cssModules: {
enable: false, // 默认为 false如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
},
webpackChain(chain) {
chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)
}
},
h5: {
publicPath: '/',
staticDirectory: 'static',
output: {
filename: 'js/[name].[hash:8].js',
chunkFilename: 'js/[name].[chunkhash:8].js'
},
miniCssExtractPluginOption: {
ignoreOrder: true,
filename: 'css/[name].[hash].css',
chunkFilename: 'css/[name].[chunkhash].css'
},
postcss: {
autoprefixer: {
enable: true,
config: {}
},
cssModules: {
enable: false, // 默认为 false如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
},
webpackChain(chain) {
chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)
}
},
rn: {
appName: 'taroDemo',
postcss: {
cssModules: {
enable: false, // 默认为 false如需使用 css modules 功能,则设为 true
}
}
}
}
if (process.env.NODE_ENV === 'development') {
// 本地开发构建配置(不混淆压缩)
return merge({}, baseConfig, devConfig)
}
// 生产构建配置(默认开启压缩混淆等)
return merge({}, baseConfig, prodConfig)
})

View File

@@ -0,0 +1,36 @@
import type { UserConfigExport } from "@tarojs/cli";
export default {
mini: {
miniCssExtractPluginOption: {
ignoreOrder: true
}
},
h5: {
/**
* WebpackChain 插件配置
* @docs https://github.com/neutrinojs/webpack-chain
*/
// webpackChain (chain) {
// /**
// * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。
// * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer
// */
// chain.plugin('analyzer')
// .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
// /**
// * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。
// * @docs https://github.com/chrisvfritz/prerender-spa-plugin
// */
// const path = require('path')
// const Prerender = require('prerender-spa-plugin')
// const staticDir = path.join(__dirname, '..', 'dist')
// chain
// .plugin('prerender')
// .use(new Prerender({
// staticDir,
// routes: [ '/pages/index/index' ],
// postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') })
// }))
// }
}
} satisfies UserConfigExport<'webpack5'>

View File

@@ -0,0 +1,245 @@
# 前端订单提交实现文档
## 概述
本文档描述了前端订单提交的完整实现,包括单商品下单、购物车批量下单等场景。
## 核心改进
### 1. 统一的API接口
**新的订单创建接口:**
```typescript
// 订单商品项
interface OrderGoodsItem {
goodsId: number;
quantity: number;
skuId?: number;
specInfo?: string;
}
// 创建订单请求
interface OrderCreateRequest {
goodsItems: OrderGoodsItem[];
addressId?: number;
payType: number;
couponId?: number;
comments?: string;
deliveryType?: number;
selfTakeMerchantId?: number;
title?: string;
}
// 微信支付返回数据
interface WxPayResult {
prepayId: string;
orderNo: string;
timeStamp: string;
nonceStr: string;
package: string;
signType: string;
paySign: string;
}
```
### 2. 标题长度限制
**工具函数:**
```typescript
// 截取文本,限制长度
export function truncateText(text: string, maxLength: number = 30): string {
if (!text) return '';
if (text.length <= maxLength) return text;
return text.substring(0, maxLength);
}
// 生成订单标题
export function generateOrderTitle(goodsNames: string[], maxLength: number = 30): string {
if (!goodsNames || goodsNames.length === 0) return '商品订单';
let title = goodsNames.length === 1
? goodsNames[0]
: `${goodsNames[0]}${goodsNames.length}件商品`;
return truncateText(title, maxLength);
}
```
## 实现细节
### 1. 单商品下单
**文件:** `src/shop/orderConfirm/index.tsx`
**核心逻辑:**
```typescript
const onWxPay = async (goods: ShopGoods) => {
// 1. 校验收货地址
if (!address) {
Taro.showToast({ title: '请选择收货地址', icon: 'error' });
return;
}
Taro.showLoading({title: '支付中...'});
try {
// 2. 构建订单数据
const orderData: OrderCreateRequest = {
goodsItems: [{ goodsId: goods.goodsId!, quantity: 1 }],
addressId: address.id,
payType: 1,
comments: goods.name,
deliveryType: 0
};
// 3. 创建订单
const result = await createOrder(orderData);
// 4. 微信支付
if (result && result.prepayId) {
await Taro.requestPayment({
timeStamp: result.timeStamp,
nonceStr: result.nonceStr,
package: result.package,
signType: result.signType,
paySign: result.paySign,
});
// 5. 支付成功处理
Taro.showToast({ title: '支付成功', icon: 'success' });
setTimeout(() => {
Taro.switchTab({url: '/pages/order/order'});
}, 2000);
}
} catch (error: any) {
Taro.showToast({ title: error.message || '下单失败', icon: 'error' });
} finally {
Taro.hideLoading();
}
};
```
### 2. 购物车批量下单
**文件:** `src/shop/orderConfirmCart/index.tsx`
**核心逻辑:**
```typescript
const onCartPay = async () => {
// 1. 校验
if (!address || !cartItems || cartItems.length === 0) {
// 错误处理
return;
}
try {
// 2. 构建批量商品数据
const orderData: OrderCreateRequest = {
goodsItems: cartItems.map(item => ({
goodsId: item.goodsId!,
quantity: item.quantity || 1
})),
addressId: address.id,
payType: 1,
comments: '购物车下单',
deliveryType: 0
};
// 3. 创建订单并支付
const result = await createOrder(orderData);
// ... 支付逻辑
} catch (error) {
// 错误处理
}
};
```
## 数据流程
### 1. 前端提交流程
```
用户点击支付
校验地址和商品
构建OrderCreateRequest
调用createOrder API
后端返回WxPayResult
调用微信支付
支付成功跳转
```
### 2. 后端处理流程
```
接收OrderCreateRequest
参数校验
构建订单主表
保存订单商品明细
库存扣减
生成订单标题(≤30字)
创建微信支付
返回支付参数
```
## 关键特性
### 1. 数据安全
- 前端只传递商品ID和数量
- 价格、库存等敏感信息由后端实时获取
- 防止前端数据篡改
### 2. 业务完整性
- 统一的订单创建流程
- 完整的错误处理机制
- 支持多种下单场景
### 3. 用户体验
- 清晰的加载状态
- 友好的错误提示
- 自动跳转到订单页面
## 扩展功能
### 1. 支持的下单类型
- 单商品立即购买
- 购物车批量下单
- 自提订单
- 使用优惠券下单
### 2. 支持的配送方式
- 快递配送 (deliveryType: 0)
- 到店自提 (deliveryType: 1)
### 3. 支持的支付方式
- 微信支付 (payType: 1)
- 余额支付 (payType: 0)
- 其他支付方式...
## 注意事项
1. **标题长度限制**订单标题最多30个汉字超过自动截取
2. **库存校验**:后端会实时校验商品库存
3. **地址校验**:确保收货地址属于当前用户
4. **错误处理**:完善的异常捕获和用户提示
5. **支付安全**:支付参数由后端生成,前端不可篡改
## 测试建议
1. 测试单商品下单流程
2. 测试购物车批量下单
3. 测试各种异常情况(库存不足、地址无效等)
4. 测试支付成功和失败的处理
5. 测试订单标题长度限制功能

View File

@@ -0,0 +1,103 @@
# 订单列表功能完善说明
## 完善的功能
### 1. 订单商品正确显示
- **问题**: 原来只显示订单基本信息,没有显示具体的商品信息
- **解决方案**:
- 扩展了订单接口,添加了 `OrderWithGoods` 类型
- 在加载订单列表时,同时获取每个订单的商品信息
- 使用 `listShopOrderGoods` API 获取订单商品详情
- 显示商品图片、名称、规格、数量和价格
### 2. 订单状态正确显示
- **问题**: 原来固定显示"待付款"状态
- **解决方案**:
- 添加了 `getOrderStatusText` 函数,根据订单的 `payStatus``deliveryStatus``orderStatus` 动态显示状态
- 支持的状态包括:待付款、待发货、待收货、已收货、已完成、已取消、退款申请中、退款成功等
### 3. 确认收货功能
- **新增功能**:
- 当订单状态为"待收货"时,显示"确认收货"按钮
- 点击确认收货后,更新订单状态为"已收货"和"已完成"
- 操作成功后显示提示信息并刷新列表
### 4. 取消订单功能
- **新增功能**:
- 当订单状态为"待付款"时,显示"取消订单"按钮
- 点击取消订单后,更新订单状态为"已取消"
- 操作成功后显示提示信息并刷新列表
### 5. 操作按钮优化
- **改进**: 根据订单状态动态显示不同的操作按钮
- 待付款:显示"取消订单"和"立即支付"按钮
- 待收货:显示"确认收货"按钮
- 已完成:显示"申请退款"按钮(预留功能)
### 6. 订单详情页面修复
- **问题**: 订单详情页面使用了错误的API
- **解决方案**:
- 修改为使用正确的 `listShopOrderGoods` API
- 直接显示商品信息,无需额外查询商品详情
- 优化了商品信息的显示格式
## 技术改进
### 1. 类型安全
- 添加了 `OrderWithGoods` 接口扩展
- 完善了 `OrderListProps` 接口定义
- 使用了正确的 TypeScript 类型
### 2. 错误处理
- 添加了完善的错误处理机制
- 操作失败时显示友好的错误提示
- 防止因单个订单商品获取失败而影响整个列表
### 3. 用户体验
- 添加了操作成功的提示信息
- 操作完成后自动刷新列表
- 阻止事件冒泡,避免误触
### 4. 数据一致性
- 操作完成后通知父组件刷新数据
- 确保订单状态的实时更新
## 使用说明
### 订单状态说明
- **待付款**: `payStatus = 0`
- **待发货**: `payStatus = 1 && deliveryStatus = 10`
- **待收货**: `deliveryStatus = 20`
- **已收货**: `deliveryStatus = 30`
- **已完成**: `orderStatus = 1`
- **已取消**: `orderStatus = 2`
### API 依赖
- `pageShopOrder`: 分页查询订单
- `listShopOrderGoods`: 查询订单商品
- `updateShopOrder`: 更新订单状态
### 组件结构
```
src/pages/order/
├── order.tsx # 订单主页面
├── components/
│ └── OrderList.tsx # 订单列表组件
└── test-order.tsx # 测试页面(可选)
```
## 测试建议
1. 创建不同状态的测试订单
2. 验证订单商品信息显示是否正确
3. 测试确认收货功能
4. 测试取消订单功能
5. 验证订单状态切换是否正常
## 后续优化建议
1. 添加订单搜索功能
2. 实现立即支付功能
3. 添加申请退款功能
4. 优化商品图片加载和缓存
5. 添加订单操作的二次确认

View File

@@ -0,0 +1,264 @@
# 支付逻辑重构指南
## 概述
本文档描述了支付逻辑的重构过程,将原本分散的支付代码统一整合,提高了代码的可维护性和复用性。
## 重构前后对比
### 重构前的问题
1. **代码重复**:每个支付方式都有重复的订单构建逻辑
2. **维护困难**:支付逻辑分散在多个方法中
3. **扩展性差**:添加新的支付方式需要修改多处代码
### 重构后的优势
1. **统一入口**:所有支付都通过 `onPay` 方法处理
2. **代码复用**:订单构建逻辑统一封装
3. **易于扩展**:新增支付方式只需在工具类中添加
4. **错误处理统一**:所有支付的错误处理逻辑一致
## 核心改进
### 1. 统一的支付工具类
**文件:** `src/utils/payment.ts`
```typescript
// 支付类型枚举
export enum PaymentType {
BALANCE = 0, // 余额支付
WECHAT = 1, // 微信支付
ALIPAY = 3, // 支付宝支付
}
// 统一支付处理类
export class PaymentHandler {
static async pay(
orderData: OrderCreateRequest,
paymentType: PaymentType,
callback?: PaymentCallback
): Promise<void> {
// 统一的支付处理逻辑
}
}
```
### 2. 订单数据构建函数
```typescript
// 单商品订单
export function buildSingleGoodsOrder(
goodsId: number,
quantity: number = 1,
addressId?: number,
options?: {
comments?: string;
deliveryType?: number;
couponId?: number;
}
): OrderCreateRequest
// 购物车订单
export function buildCartOrder(
cartItems: Array<{ goodsId: number; quantity: number }>,
addressId?: number,
options?: { ... }
): OrderCreateRequest
```
### 3. 简化的支付入口
**重构前:**
```typescript
const onWxPay = async (goods: ShopGoods) => {
// 校验逻辑
// 构建订单数据
// 调用创建订单API
// 处理微信支付
// 错误处理
}
const onBalancePay = async (goods: ShopGoods) => {
// 重复的校验逻辑
// 重复的订单构建逻辑
// 处理余额支付
// 重复的错误处理
}
const onPay = async (goods: ShopGoods) => {
if (payment?.type == 0) {
await onBalancePay(goods)
}
if (payment?.type == 1) {
await onWxPay(goods)
}
}
```
**重构后:**
```typescript
const onPay = async (goods: ShopGoods) => {
// 基础校验
if (!address || !payment) {
// 错误提示
return;
}
// 构建订单数据
const orderData = buildSingleGoodsOrder(
goods.goodsId!,
1,
address.id,
{ comments: goods.name }
);
// 选择支付类型
const paymentType = payment.type === 0 ? PaymentType.BALANCE : PaymentType.WECHAT;
// 执行支付
await PaymentHandler.pay(orderData, paymentType);
};
```
## 使用示例
### 1. 单商品下单
```typescript
// 在 orderConfirm/index.tsx 中
const onPay = async (goods: ShopGoods) => {
if (!address || !payment) return;
const orderData = buildSingleGoodsOrder(
goods.goodsId!,
1,
address.id,
{
comments: goods.name,
deliveryType: 0
}
);
const paymentType = payment.type === 0 ? PaymentType.BALANCE : PaymentType.WECHAT;
await PaymentHandler.pay(orderData, paymentType);
};
```
### 2. 购物车批量下单
```typescript
// 在 orderConfirmCart/index.tsx 中
const onPay = async () => {
if (!address || !cartItems?.length) return;
const orderData = buildCartOrder(
cartItems.map(item => ({
goodsId: item.goodsId!,
quantity: item.quantity || 1
})),
address.id,
{
comments: '购物车下单',
deliveryType: 0
}
);
const paymentType = payment?.type === 0 ? PaymentType.BALANCE : PaymentType.WECHAT;
await PaymentHandler.pay(orderData, paymentType);
};
```
### 3. 使用优惠券下单
```typescript
const onPayWithCoupon = async (goods: ShopGoods, couponId: number) => {
const orderData = buildSingleGoodsOrder(
goods.goodsId!,
1,
address.id,
{
comments: `使用优惠券购买${goods.name}`,
couponId: couponId
}
);
await PaymentHandler.pay(orderData, PaymentType.WECHAT);
};
```
### 4. 自提订单
```typescript
const onSelfPickupOrder = async (goods: ShopGoods, merchantId: number) => {
const orderData = buildSingleGoodsOrder(
goods.goodsId!,
1,
address.id,
{
comments: `自提订单 - ${goods.name}`,
deliveryType: 1,
selfTakeMerchantId: merchantId
}
);
await PaymentHandler.pay(orderData, PaymentType.WECHAT);
};
```
## 扩展新的支付方式
### 1. 添加支付类型
```typescript
// 在 PaymentType 枚举中添加
export enum PaymentType {
BALANCE = 0,
WECHAT = 1,
ALIPAY = 3,
UNIONPAY = 4, // 新增银联支付
}
```
### 2. 实现支付处理方法
```typescript
// 在 PaymentHandler 类中添加
private static async handleUnionPay(result: any): Promise<void> {
// 银联支付逻辑
}
```
### 3. 在支付分发中添加
```typescript
// 在 PaymentHandler.pay 方法中添加
switch (paymentType) {
case PaymentType.WECHAT:
await this.handleWechatPay(result);
break;
case PaymentType.BALANCE:
await this.handleBalancePay(result);
break;
case PaymentType.UNIONPAY: // 新增
await this.handleUnionPay(result);
break;
// ...
}
```
## 优势总结
1. **代码简洁**:支付入口方法从 50+ 行减少到 20+ 行
2. **逻辑清晰**:订单构建、支付处理、错误处理分离
3. **易于测试**:每个功能模块独立,便于单元测试
4. **维护性强**:修改支付逻辑只需在工具类中修改
5. **扩展性好**:新增支付方式无需修改业务代码
## 注意事项
1. **向后兼容**:确保重构后的接口与原有调用方式兼容
2. **错误处理**:统一的错误处理机制,确保用户体验一致
3. **类型安全**:使用 TypeScript 枚举确保支付类型的类型安全
4. **测试覆盖**:对重构后的代码进行充分的测试

View File

@@ -0,0 +1,181 @@
# 后端多规格功能适配指南
## 概述
前端已完成商品多规格功能集成,需要后端相应适配以支持完整的多规格商品流程。
## 需要适配的API接口
### 1. 商品规格查询接口
**接口**: `GET /shop/shop-goods-spec`
**当前问题**: 参数模型中缺少 `goodsId` 字段
**需要修改**:
```java
// ShopGoodsSpecParam 类需要添加 goodsId 字段
public class ShopGoodsSpecParam extends PageParam {
private Long goodsId; // 添加此字段
private Long id;
private String keywords;
// ... getter/setter
}
```
### 2. 商品SKU查询接口
**接口**: `GET /shop/shop-goods-sku`
**当前问题**: 参数模型中缺少 `goodsId` 字段
**需要修改**:
```java
// ShopGoodsSkuParam 类需要添加 goodsId 字段
public class ShopGoodsSkuParam extends PageParam {
private Long goodsId; // 添加此字段
private Long id;
private String keywords;
// ... getter/setter
}
```
### 3. 购物车接口适配
**当前购物车数据结构**:
```typescript
interface CartItem {
goodsId: number;
name: string;
price: string;
image: string;
quantity: number;
addTime: number;
skuId?: number; // 新增SKU ID
specInfo?: string; // 新增规格信息
}
```
**后端需要适配**:
- 购物车存储时支持 `skuId``specInfo` 字段
- 购物车查询时返回完整的SKU信息
- 价格计算时优先使用SKU价格
### 4. 订单创建接口适配
**前端订单数据结构**:
```typescript
interface OrderGoodsItem {
goodsId: number;
quantity: number;
skuId?: number; // SKU ID
specInfo?: string; // 规格信息字符串
}
```
**后端需要处理**:
- 订单商品项支持SKU信息
- 库存扣减时根据SKU进行
- 价格计算时使用SKU价格
- 订单详情显示规格信息
## 数据库表结构检查
### 1. 购物车表 (如果有)
确保包含以下字段:
```sql
ALTER TABLE shop_cart ADD COLUMN sku_id BIGINT COMMENT 'SKU ID';
ALTER TABLE shop_cart ADD COLUMN spec_info VARCHAR(500) COMMENT '规格信息';
```
### 2. 订单商品表
确保包含以下字段:
```sql
-- shop_order_goods 表应该已有这些字段
-- sku_id BIGINT COMMENT 'SKU ID'
-- spec VARCHAR(255) COMMENT '商品规格'
```
## 业务逻辑适配
### 1. 库存管理
- 单规格商品:使用 `shop_goods.stock`
- 多规格商品:使用 `shop_goods_sku.stock`
- 下单时根据是否有SKU选择对应的库存扣减逻辑
### 2. 价格计算
- 单规格商品:使用 `shop_goods.price`
- 多规格商品:使用 `shop_goods_sku.price`
- 订单金额计算时优先使用SKU价格
### 3. 规格数据组织
后端查询规格时需要按商品ID过滤:
```java
// 示例查询逻辑
public List<ShopGoodsSpec> listByGoodsId(Long goodsId) {
return shopGoodsSpecMapper.selectList(
new QueryWrapper<ShopGoodsSpec>()
.eq("goods_id", goodsId)
.orderByAsc("spec_name", "spec_value")
);
}
```
## 前端调用示例
### 1. 加载商品规格
```typescript
// 前端会这样调用
listShopGoodsSpec({ goodsId: 123 })
listShopGoodsSku({ goodsId: 123 })
```
### 2. 创建订单
```typescript
// 单规格商品
{
goodsItems: [{
goodsId: 123,
quantity: 2
}]
}
// 多规格商品
{
goodsItems: [{
goodsId: 123,
quantity: 2,
skuId: 456,
specInfo: "颜色:红色|尺寸:L"
}]
}
```
## 测试建议
1. **创建测试数据**:
- 创建一个多规格商品
- 添加规格组(颜色、尺寸等)
- 生成对应的SKU数据
2. **测试场景**:
- 商品详情页规格加载
- 规格选择和SKU匹配
- 加入购物车(多规格)
- 立即购买(多规格)
- 订单创建和支付
3. **边界情况**:
- SKU库存为0的处理
- 规格数据不完整的处理
- 单规格和多规格商品混合购买
## 注意事项
1. **向后兼容**: 确保单规格商品的现有功能不受影响
2. **数据一致性**: SKU价格和库存与主商品数据的同步
3. **性能优化**: 规格和SKU数据的查询优化
4. **错误处理**: 规格选择错误、库存不足等异常情况的处理
## 完成检查清单
- [ ] ShopGoodsSpecParam 添加 goodsId 字段
- [ ] ShopGoodsSkuParam 添加 goodsId 字段
- [ ] 规格查询接口支持按商品ID过滤
- [ ] SKU查询接口支持按商品ID过滤
- [ ] 购物车接口支持SKU信息
- [ ] 订单创建接口支持SKU信息
- [ ] 库存扣减逻辑适配多规格
- [ ] 价格计算逻辑适配多规格
- [ ] 测试多规格商品完整流程

View File

@@ -0,0 +1,248 @@
/**
* 订单服务实现类示例
* 展示如何保存订单商品信息的业务逻辑
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class ShopOrderServiceImpl implements ShopOrderService {
@Autowired
private ShopOrderMapper shopOrderMapper;
@Autowired
private OrderGoodsMapper orderGoodsMapper;
@Autowired
private ShopGoodsService shopGoodsService;
@Autowired
private ShopUserAddressService addressService;
@Autowired
private WxPayService wxPayService;
/**
* 创建订单
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, String> createOrder(OrderCreateRequest request, User loginUser) {
// 1. 参数校验
validateOrderRequest(request, loginUser);
// 2. 构建订单对象
ShopOrder shopOrder = buildShopOrder(request, loginUser);
// 3. 应用业务规则
applyBusinessRules(shopOrder, loginUser);
// 4. 保存订单主表
boolean saved = shopOrderMapper.insert(shopOrder) > 0;
if (!saved) {
throw new BusinessException("订单保存失败");
}
// 5. 保存订单商品明细 - 核心业务逻辑
saveOrderGoods(shopOrder, request.getGoodsItems());
// 6. 创建微信支付订单
try {
return wxPayService.createWxOrder(shopOrder);
} catch (Exception e) {
log.error("创建微信支付订单失败,订单号:{}", shopOrder.getOrderNo(), e);
throw new BusinessException("创建支付订单失败:" + e.getMessage());
}
}
/**
* 保存订单商品明细 - 核心实现
*/
private void saveOrderGoods(ShopOrder shopOrder, List<OrderGoodsItem> goodsItems) {
List<OrderGoods> orderGoodsList = new ArrayList<>();
BigDecimal totalPrice = BigDecimal.ZERO;
int totalQuantity = 0;
List<String> goodsNames = new ArrayList<>();
for (OrderGoodsItem item : goodsItems) {
// 1. 获取商品最新信息进行校验
ShopGoods goods = shopGoodsService.getById(item.getGoodsId());
if (goods == null) {
throw new BusinessException("商品不存在:" + item.getGoodsId());
}
// 2. 商品状态校验
if (goods.getIsShow() != 1) {
throw new BusinessException("商品已下架:" + goods.getName());
}
// 3. 库存校验
if (goods.getStock() < item.getQuantity()) {
throw new BusinessException("商品库存不足:" + goods.getName());
}
// 4. 价格计算(以数据库中的价格为准)
BigDecimal itemPrice = new BigDecimal(goods.getPrice());
BigDecimal itemTotalPrice = itemPrice.multiply(new BigDecimal(item.getQuantity()));
// 5. 构建订单商品记录
OrderGoods orderGoods = new OrderGoods();
orderGoods.setOrderId(shopOrder.getOrderId());
orderGoods.setGoodsId(item.getGoodsId());
orderGoods.setTotalNum(item.getQuantity());
orderGoods.setPayPrice(itemTotalPrice.toString());
orderGoods.setType(0); // 0商城
orderGoods.setPayStatus("0"); // 0未付款
orderGoods.setOrderStatus(0); // 0未完成
orderGoods.setUserId(shopOrder.getUserId());
orderGoods.setTenantId(shopOrder.getTenantId());
orderGoods.setCreateTime(LocalDateTime.now());
// 6. SKU信息处理如果有规格
if (item.getSkuId() != null) {
// 处理SKU相关逻辑
// orderGoods.setSkuId(item.getSkuId());
// orderGoods.setSpecInfo(item.getSpecInfo());
}
orderGoodsList.add(orderGoods);
// 7. 累计计算
totalPrice = totalPrice.add(itemTotalPrice);
totalQuantity += item.getQuantity();
goodsNames.add(goods.getName());
// 8. 扣减库存(根据业务需求,可能在支付成功后扣减)
if (goods.getDeductStockType() == 10) { // 10下单减库存
goods.setStock(goods.getStock() - item.getQuantity());
shopGoodsService.updateById(goods);
}
}
// 9. 批量保存订单商品
if (!orderGoodsList.isEmpty()) {
orderGoodsMapper.insertBatch(orderGoodsList);
}
// 10. 更新订单总价和数量
shopOrder.setTotalPrice(totalPrice.toString());
shopOrder.setPayPrice(totalPrice.toString()); // 暂时不考虑优惠
shopOrder.setTotalNum(totalQuantity);
// 11. 生成订单标题限制30个汉字
String title = generateOrderTitle(goodsNames);
shopOrder.setTitle(title);
// 12. 更新订单主表
shopOrderMapper.updateById(shopOrder);
}
/**
* 生成订单标题限制长度不超过30个汉字
*/
private String generateOrderTitle(List<String> goodsNames) {
if (goodsNames.isEmpty()) {
return "商品订单";
}
String title;
if (goodsNames.size() == 1) {
title = goodsNames.get(0);
} else {
title = goodsNames.get(0) + "" + goodsNames.size() + "件商品";
}
// 限制标题长度最多30个汉字
if (title.length() > 30) {
title = title.substring(0, 30);
}
return title;
}
/**
* 参数校验
*/
private void validateOrderRequest(OrderCreateRequest request, User loginUser) {
if (request.getGoodsItems() == null || request.getGoodsItems().isEmpty()) {
throw new BusinessException("商品信息不能为空");
}
if (request.getAddressId() == null) {
throw new BusinessException("收货地址不能为空");
}
// 校验收货地址是否属于当前用户
ShopUserAddress address = addressService.getById(request.getAddressId());
if (address == null || !address.getUserId().equals(loginUser.getUserId())) {
throw new BusinessException("收货地址不存在或不属于当前用户");
}
// 校验商品数量
for (OrderGoodsItem item : request.getGoodsItems()) {
if (item.getGoodsId() == null || item.getQuantity() <= 0) {
throw new BusinessException("商品信息不正确");
}
}
}
/**
* 构建订单对象
*/
private ShopOrder buildShopOrder(OrderCreateRequest request, User loginUser) {
ShopOrder shopOrder = new ShopOrder();
// 基础信息
shopOrder.setOrderNo(generateOrderNo());
shopOrder.setType(0); // 0商城订单
shopOrder.setChannel(0); // 0小程序
shopOrder.setUserId(loginUser.getUserId());
shopOrder.setTenantId(loginUser.getTenantId());
// 用户信息
shopOrder.setRealName(loginUser.getRealName());
shopOrder.setPhone(loginUser.getPhone());
// 地址信息
ShopUserAddress address = addressService.getById(request.getAddressId());
shopOrder.setAddressId(request.getAddressId());
shopOrder.setAddress(address.getProvince() + address.getCity() +
address.getRegion() + address.getAddress());
// 支付信息
shopOrder.setPayType(request.getPayType());
shopOrder.setPayStatus(0); // 0未付款
shopOrder.setOrderStatus(0); // 0未使用
// 配送信息
shopOrder.setDeliveryType(request.getDeliveryType());
if (request.getSelfTakeMerchantId() != null) {
shopOrder.setSelfTakeMerchantId(request.getSelfTakeMerchantId());
}
// 其他信息
shopOrder.setComments(request.getComments());
shopOrder.setCreateTime(LocalDateTime.now());
return shopOrder;
}
/**
* 应用业务规则
*/
private void applyBusinessRules(ShopOrder shopOrder, User loginUser) {
// 设置默认标题(如果没有设置)
if (shopOrder.getTitle() == null) {
shopOrder.setTitle("商品订单");
}
// 其他业务规则...
}
/**
* 生成订单号
*/
private String generateOrderNo() {
return "SO" + System.currentTimeMillis() +
String.format("%04d", new Random().nextInt(10000));
}
}

View File

@@ -0,0 +1,154 @@
# 前端多规格功能测试指南
## 功能概述
已完成商品详情页多规格功能集成,包括:
- 规格数据加载
- 规格选择器组件
- 购物车支持SKU信息
- 立即购买支持SKU信息
## 测试步骤
### 1. 准备测试数据
在后端创建一个多规格商品,包含:
- 基础商品信息
- 规格组:颜色(红色、蓝色)、尺寸(S、M、L)
- 对应的SKU数据
### 2. 商品详情页测试
1. 访问商品详情页:`/shop/goodsDetail/index?id={商品ID}`
2. 检查是否正确加载:
- 商品基本信息
- 商品图片轮播
- 价格显示
### 3. 规格选择测试
1. 点击"加入购物车"按钮
2. 应该弹出规格选择器
3. 检查规格选择器内容:
- 商品图片和基本信息
- 规格组显示(颜色、尺寸)
- 规格值选项
- 数量选择器
### 4. 规格交互测试
1. 选择不同规格组合
2. 检查:
- SKU价格更新
- 库存数量更新
- 不可选规格置灰
- 数量限制(不超过库存)
### 5. 加入购物车测试
1. 选择完整规格
2. 设置购买数量
3. 点击确定
4. 检查:
- 成功提示
- 购物车数量更新
- 购物车页面显示规格信息
### 6. 立即购买测试
1. 点击"立即购买"按钮
2. 选择规格和数量
3. 点击确定
4. 检查是否正确跳转到订单确认页
## 预期行为
### 单规格商品
- 直接加入购物车/立即购买
- 不显示规格选择器
### 多规格商品
- 必须选择规格才能操作
- 显示规格选择器
- 根据选择更新价格和库存
## 数据流验证
### 1. API调用检查
打开浏览器开发者工具检查以下API调用
```
GET /shop/shop-goods/{id} // 商品详情
GET /shop/shop-goods-spec?goodsId={id} // 商品规格
GET /shop/shop-goods-sku?goodsId={id} // 商品SKU
```
### 2. 购物车数据检查
检查本地存储中的购物车数据:
```javascript
// 在浏览器控制台执行
JSON.parse(localStorage.getItem('cart_items') || '[]')
```
应该包含SKU信息
```json
[{
"goodsId": 123,
"name": "测试商品",
"price": "99.00",
"image": "...",
"quantity": 2,
"skuId": 456,
"specInfo": "颜色:红色|尺寸:L",
"addTime": 1640995200000
}]
```
## 常见问题排查
### 1. 规格选择器不显示
- 检查 `specs` 数组是否有数据
- 检查 `showSpecSelector` 状态
- 检查API返回数据格式
### 2. SKU匹配失败
- 检查规格值字符串格式
- 检查SKU数据中的 `sku` 字段格式
- 确认规格名称排序一致性
### 3. 价格不更新
- 检查SKU数据中的 `price` 字段
- 检查 `selectedSku` 状态更新
- 确认价格显示逻辑
### 4. 库存显示错误
- 检查SKU数据中的 `stock` 字段
- 检查库存为0时的处理逻辑
- 确认数量选择器的最大值限制
## 调试技巧
### 1. 控制台日志
在关键位置添加日志:
```javascript
console.log('Specs loaded:', specs);
console.log('SKUs loaded:', skus);
console.log('Selected SKU:', selectedSku);
```
### 2. React DevTools
使用React DevTools检查组件状态
- GoodsDetail组件的state
- SpecSelector组件的props和state
### 3. 网络面板
检查API请求和响应
- 请求参数是否正确
- 响应数据格式是否符合预期
- 是否有错误状态码
## 性能优化建议
1. **数据预加载**: 考虑在商品详情加载时同时加载规格数据
2. **缓存策略**: 对规格数据进行适当缓存
3. **懒加载**: 规格选择器可以考虑懒加载
4. **防抖处理**: 规格选择时的价格更新可以添加防抖
## 后续优化方向
1. **规格图片**: 支持规格值对应的商品图片
2. **规格预设**: 支持默认选中某个规格组合
3. **批量操作**: 支持批量添加不同规格的商品
4. **规格搜索**: 在规格较多时支持搜索功能

View File

@@ -0,0 +1,317 @@
/**
* 前端订单提交完整示例
* 展示如何使用新的订单API进行下单
*/
import React, { useState, useEffect } from 'react';
import Taro from '@tarojs/taro';
import { Button } from '@nutui/nutui-react-taro';
import { createOrder } from '@/api/shop/shopOrder';
import { OrderCreateRequest, OrderGoodsItem } from '@/api/shop/shopOrder/model';
import { ShopGoods } from '@/api/shop/shopGoods/model';
import { ShopUserAddress } from '@/api/shop/shopUserAddress/model';
import { generateOrderTitle } from '@/utils/common';
interface OrderExampleProps {
goods: ShopGoods;
address: ShopUserAddress;
quantity?: number;
}
const OrderExample: React.FC<OrderExampleProps> = ({
goods,
address,
quantity = 1
}) => {
const [loading, setLoading] = useState(false);
/**
* 单商品下单示例
*/
const handleSingleGoodsOrder = async () => {
if (!address) {
Taro.showToast({
title: '请选择收货地址',
icon: 'error'
});
return;
}
setLoading(true);
try {
// 1. 构建订单请求数据
const orderData: OrderCreateRequest = {
goodsItems: [
{
goodsId: goods.goodsId!,
quantity: quantity
}
],
addressId: address.id,
payType: 1, // 微信支付
comments: `购买${goods.name}`,
deliveryType: 0, // 快递配送
// 可选:自定义订单标题
title: generateOrderTitle([goods.name!])
};
// 2. 调用创建订单API
const result = await createOrder(orderData);
if (result && result.prepayId) {
// 3. 调用微信支付
await Taro.requestPayment({
timeStamp: result.timeStamp,
nonceStr: result.nonceStr,
package: result.package,
signType: result.signType,
paySign: result.paySign,
});
// 4. 支付成功处理
Taro.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(() => {
Taro.switchTab({url: '/pages/order/order'});
}, 2000);
}
} catch (error: any) {
console.error('下单失败:', error);
Taro.showToast({
title: error.message || '下单失败',
icon: 'error'
});
} finally {
setLoading(false);
}
};
/**
* 购物车批量下单示例
*/
const handleCartOrder = async (cartItems: Array<{goodsId: number, quantity: number, goodsName: string}>) => {
if (!address) {
Taro.showToast({
title: '请选择收货地址',
icon: 'error'
});
return;
}
if (!cartItems || cartItems.length === 0) {
Taro.showToast({
title: '购物车为空',
icon: 'error'
});
return;
}
setLoading(true);
try {
// 1. 构建订单商品列表
const goodsItems: OrderGoodsItem[] = cartItems.map(item => ({
goodsId: item.goodsId,
quantity: item.quantity
}));
// 2. 生成订单标题
const goodsNames = cartItems.map(item => item.goodsName);
const orderTitle = generateOrderTitle(goodsNames);
// 3. 构建订单请求数据
const orderData: OrderCreateRequest = {
goodsItems,
addressId: address.id,
payType: 1, // 微信支付
comments: '购物车下单',
deliveryType: 0, // 快递配送
title: orderTitle
};
// 4. 调用创建订单API
const result = await createOrder(orderData);
if (result && result.prepayId) {
// 5. 调用微信支付
await Taro.requestPayment({
timeStamp: result.timeStamp,
nonceStr: result.nonceStr,
package: result.package,
signType: result.signType,
paySign: result.paySign,
});
// 6. 支付成功处理
Taro.showToast({
title: '支付成功',
icon: 'success'
});
// 7. 清空购物车(可选)
// clearCart();
setTimeout(() => {
Taro.switchTab({url: '/pages/order/order'});
}, 2000);
}
} catch (error: any) {
console.error('下单失败:', error);
Taro.showToast({
title: error.message || '下单失败',
icon: 'error'
});
} finally {
setLoading(false);
}
};
/**
* 自提订单示例
*/
const handleSelfPickupOrder = async (merchantId: number) => {
setLoading(true);
try {
const orderData: OrderCreateRequest = {
goodsItems: [
{
goodsId: goods.goodsId!,
quantity: quantity
}
],
addressId: address.id,
payType: 1,
deliveryType: 1, // 自提
selfTakeMerchantId: merchantId,
comments: `自提订单 - ${goods.name}`,
title: generateOrderTitle([goods.name!])
};
const result = await createOrder(orderData);
if (result && result.prepayId) {
await Taro.requestPayment({
timeStamp: result.timeStamp,
nonceStr: result.nonceStr,
package: result.package,
signType: result.signType,
paySign: result.paySign,
});
Taro.showToast({
title: '下单成功,请到店自提',
icon: 'success'
});
setTimeout(() => {
Taro.switchTab({url: '/pages/order/order'});
}, 2000);
}
} catch (error: any) {
console.error('下单失败:', error);
Taro.showToast({
title: error.message || '下单失败',
icon: 'error'
});
} finally {
setLoading(false);
}
};
/**
* 使用优惠券下单示例
*/
const handleOrderWithCoupon = async (couponId: number) => {
setLoading(true);
try {
const orderData: OrderCreateRequest = {
goodsItems: [
{
goodsId: goods.goodsId!,
quantity: quantity
}
],
addressId: address.id,
payType: 1,
couponId: couponId, // 使用优惠券
deliveryType: 0,
comments: `使用优惠券购买${goods.name}`,
title: generateOrderTitle([goods.name!])
};
const result = await createOrder(orderData);
if (result && result.prepayId) {
await Taro.requestPayment({
timeStamp: result.timeStamp,
nonceStr: result.nonceStr,
package: result.package,
signType: result.signType,
paySign: result.paySign,
});
Taro.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(() => {
Taro.switchTab({url: '/pages/order/order'});
}, 2000);
}
} catch (error: any) {
console.error('下单失败:', error);
Taro.showToast({
title: error.message || '下单失败',
icon: 'error'
});
} finally {
setLoading(false);
}
};
return (
<div>
<Button
type="primary"
loading={loading}
onClick={handleSingleGoodsOrder}
>
</Button>
<Button
type="success"
loading={loading}
onClick={() => handleCartOrder([
{goodsId: goods.goodsId!, quantity: 1, goodsName: goods.name!}
])}
>
</Button>
<Button
type="warning"
loading={loading}
onClick={() => handleSelfPickupOrder(1)}
>
</Button>
<Button
type="info"
loading={loading}
onClick={() => handleOrderWithCoupon(123)}
>
使
</Button>
</div>
);
};
export default OrderExample;

View File

@@ -0,0 +1,189 @@
# 商品多规格功能集成总结
## 完成的工作
### 1. 前端功能集成 ✅
#### 商品详情页改造
- **文件**: `src/shop/goodsDetail/index.tsx`
- **新增功能**:
- 加载商品规格数据 (`listShopGoodsSpec`)
- 加载商品SKU数据 (`listShopGoodsSku`)
- 集成规格选择器组件
- 支持多规格加入购物车
- 支持多规格立即购买
#### 购物车系统升级
- **文件**: `src/hooks/useCart.ts`
- **改进内容**:
- `CartItem` 接口新增 `skuId``specInfo` 字段
- `addToCart` 函数支持SKU信息
- 购物车商品唯一性判断支持SKU区分
#### 规格选择器组件优化
- **文件**: `src/components/SpecSelector/index.tsx`
- **改进内容**:
- 支持 `action` 参数区分加入购物车和立即购买
- 优化回调函数参数传递
- 改进组件接口设计
### 2. 数据流设计 ✅
#### API调用流程
```
商品详情页加载
├── getShopGoods(goodsId) - 获取商品基本信息
├── listShopGoodsSpec(goodsId) - 获取商品规格
└── listShopGoodsSku(goodsId) - 获取商品SKU
```
#### 用户操作流程
```
用户点击加入购物车/立即购买
├── 检查是否有规格 (specs.length > 0)
├── 有规格: 显示规格选择器
│ ├── 用户选择规格组合
│ ├── 系统匹配对应SKU
│ ├── 更新价格和库存显示
│ └── 确认后执行对应操作
└── 无规格: 直接执行操作
```
#### 数据结构设计
```typescript
// 购物车商品项
interface CartItem {
goodsId: number;
name: string;
price: string;
image: string;
quantity: number;
addTime: number;
skuId?: number; // 新增: SKU ID
specInfo?: string; // 新增: 规格信息
}
// 订单商品项
interface OrderGoodsItem {
goodsId: number;
quantity: number;
skuId?: number; // 新增: SKU ID
specInfo?: string; // 新增: 规格信息
}
```
## 技术实现要点
### 1. 规格数据组织
- 规格按 `specName` 分组
- 规格值按 `specValue` 组织
- SKU通过规格值字符串匹配 (`sku` 字段)
### 2. SKU匹配算法
```typescript
// 构建规格值字符串,按规格名称排序确保一致性
const sortedSpecNames = specGroups.map(g => g.specName).sort();
const specValues = sortedSpecNames.map(name => selectedSpecs[name]).join('|');
const sku = skus.find(s => s.sku === specValues);
```
### 3. 购物车唯一性判断
```typescript
// 根据goodsId和skuId判断是否为同一商品
const existingItemIndex = newItems.findIndex(item =>
item.goodsId === goods.goodsId &&
(goods.skuId ? item.skuId === goods.skuId : !item.skuId)
);
```
## 需要后端配合的工作
### 1. API参数模型修改 🔄
- `ShopGoodsSpecParam` 需要添加 `goodsId` 字段
- `ShopGoodsSkuParam` 需要添加 `goodsId` 字段
### 2. 查询逻辑适配 🔄
- 规格查询接口支持按商品ID过滤
- SKU查询接口支持按商品ID过滤
### 3. 业务逻辑升级 🔄
- 购物车接口支持SKU信息存储
- 订单创建接口支持SKU信息处理
- 库存扣减逻辑适配多规格
- 价格计算逻辑适配多规格
## 测试验证
### 前端测试 ✅
- [x] 商品详情页规格数据加载
- [x] 规格选择器显示和交互
- [x] SKU匹配和价格更新
- [x] 购物车多规格商品支持
- [x] 立即购买多规格商品支持
### 后端测试 🔄
- [ ] API参数传递验证
- [ ] 规格数据查询验证
- [ ] SKU数据查询验证
- [ ] 购物车SKU信息存储
- [ ] 订单SKU信息处理
## 文档输出
1. **后端适配指南**: `docs/backend-multi-spec-integration.md`
- API接口修改要求
- 数据库表结构检查
- 业务逻辑适配建议
- 测试场景和检查清单
2. **前端测试指南**: `docs/frontend-multi-spec-test.md`
- 功能测试步骤
- 数据流验证方法
- 常见问题排查
- 调试技巧和优化建议
## 兼容性保证
### 向后兼容
- 单规格商品功能完全保持不变
- 现有购物车数据结构兼容
- 现有订单流程不受影响
### 渐进增强
- 多规格功能作为增强特性
- 规格数据不存在时自动降级为单规格模式
- 错误处理确保用户体验不受影响
## 下一步工作
### 短期 (1-2周)
1. 后端API适配完成
2. 端到端测试验证
3. 生产环境部署测试
### 中期 (1个月)
1. 性能优化和监控
2. 用户反馈收集和改进
3. 边界情况处理完善
### 长期 (3个月)
1. 规格图片支持
2. 批量操作功能
3. 高级规格管理功能
## 风险评估
### 低风险 ✅
- 前端功能实现完整
- 数据结构设计合理
- 向后兼容性良好
### 中风险 ⚠️
- 后端API适配工作量
- 数据迁移和兼容性
- 性能影响评估
### 缓解措施
- 详细的后端适配文档
- 完整的测试用例覆盖
- 分阶段部署和验证

View File

@@ -0,0 +1,190 @@
# 订单状态修复总结
## 问题分析
### 1. 数据类型不一致
- **问题**: `payStatus` 字段在模型中定义为 `boolean` 类型,但代码中按数字处理
- **影响**: 导致支付状态判断错误,"待付款"状态显示不正确
### 2. 状态判断逻辑错误
- **问题**: 状态判断优先级不正确,没有按照业务逻辑顺序检查
- **影响**: 订单状态显示混乱,用户看到错误的订单状态
### 3. 操作按钮显示错误
- **问题**: 按钮显示条件与实际订单状态不匹配
- **影响**: 用户在错误的状态下看到不应该出现的操作按钮
### 4. Tab筛选逻辑不完整
- **问题**: 缺少"待收货"状态的筛选,状态分类不够细致
- **影响**: 用户无法准确筛选不同状态的订单
## 修复内容
### 1. 订单状态判断逻辑优化 ✅
**文件**: `src/pages/order/components/OrderList.tsx`
**修复前**:
```typescript
const getOrderStatusText = (order: ShopOrder) => {
if (!order.payStatus) return '待付款';
if (order.payStatus && order.deliveryStatus === 10) return '待发货';
// ... 其他逻辑
};
```
**修复后**:
```typescript
const getOrderStatusText = (order: ShopOrder) => {
// 优先检查订单状态
if (order.orderStatus === 2) return '已取消';
if (order.orderStatus === 4) return '退款申请中';
// ... 其他退款相关状态
// 检查支付状态 (payStatus为boolean类型)
if (!order.payStatus || order.payStatus === false) return '待付款';
// 已付款后检查发货状态
if (order.deliveryStatus === 10) return '待发货';
if (order.deliveryStatus === 20) return '待收货';
if (order.deliveryStatus === 30) return '已收货';
// 最后检查订单完成状态
if (order.orderStatus === 1) return '已完成';
return '未知状态';
};
```
### 2. Tab筛选功能完善 ✅
**新增"待收货"状态**:
```typescript
const tabs = [
{ index: 0, key: '全部', title: '全部' },
{ index: 1, key: '待付款', title: '待付款' },
{ index: 2, key: '待发货', title: '待发货' },
{ index: 3, key: '待收货', title: '待收货' }, // 新增
{ index: 4, key: '已收货', title: '已收货' },
{ index: 5, key: '已完成', title: '已完成' }
];
```
### 3. 操作按钮逻辑修复 ✅
**修复前**:
```typescript
{item.payStatus && (
<Space>
<Button onClick={() => cancelOrder(item)}>取消订单</Button>
<Button type="primary">立即支付</Button>
</Space>
)}
```
**修复后**:
```typescript
{/* 待付款状态:显示取消订单和立即支付 */}
{(!item.payStatus || item.payStatus === false) && item.orderStatus !== 2 && (
<Space>
<Button onClick={() => cancelOrder(item)}>取消订单</Button>
<Button type="primary">立即支付</Button>
</Space>
)}
```
### 4. 订单详情页状态显示修复 ✅
**文件**: `src/shop/orderDetail/index.tsx`
- 统一状态判断逻辑
- 修复函数调用参数
- 确保与订单列表页面的状态显示一致
## 订单状态流程图
```
订单创建
待付款 (payStatus: false)
↓ (用户支付)
待发货 (payStatus: true, deliveryStatus: 10)
↓ (商家发货)
待收货 (payStatus: true, deliveryStatus: 20)
↓ (用户确认收货)
已收货 (payStatus: true, deliveryStatus: 30)
↓ (系统自动或手动完成)
已完成 (orderStatus: 1)
// 异常流程
任意状态 → 已取消 (orderStatus: 2)
已完成 → 退款申请中 (orderStatus: 4)
退款申请中 → 退款成功 (orderStatus: 6)
```
## 字段含义说明
### payStatus (支付状态)
- **类型**: `boolean`
- **值**: `false/0` = 未付款, `true/1` = 已付款
### deliveryStatus (发货状态)
- **类型**: `number`
- **值**:
- `10` = 未发货/待发货
- `20` = 已发货/待收货
- `30` = 已收货
### orderStatus (订单状态)
- **类型**: `number`
- **值**:
- `0` = 未使用
- `1` = 已完成
- `2` = 已取消
- `3` = 取消中
- `4` = 退款申请中
- `5` = 退款被拒绝
- `6` = 退款成功
- `7` = 客户端申请退款
## 测试验证
### 1. 状态显示测试
- [ ] 创建不同状态的测试订单
- [ ] 验证订单列表页面状态显示正确
- [ ] 验证订单详情页面状态显示正确
- [ ] 验证状态文本与实际订单状态匹配
### 2. Tab筛选测试
- [ ] 测试"全部"tab显示所有订单
- [ ] 测试"待付款"tab只显示未支付订单
- [ ] 测试"待发货"tab只显示已支付待发货订单
- [ ] 测试"待收货"tab只显示已发货待收货订单
- [ ] 测试"已收货"tab只显示已收货订单
- [ ] 测试"已完成"tab只显示已完成订单
### 3. 操作按钮测试
- [ ] 待付款状态显示"取消订单"和"立即支付"按钮
- [ ] 待收货状态显示"确认收货"按钮
- [ ] 已完成状态显示"申请退款"按钮
- [ ] 其他状态不显示不相关按钮
### 4. 状态流转测试
- [ ] 测试支付后状态从"待付款"变为"待发货"
- [ ] 测试发货后状态从"待发货"变为"待收货"
- [ ] 测试确认收货后状态从"待收货"变为"已收货"
- [ ] 测试取消订单功能
## 注意事项
1. **数据类型一致性**: 确保前后端对 `payStatus` 字段类型的处理一致
2. **状态优先级**: 按照业务逻辑正确设置状态判断优先级
3. **用户体验**: 确保状态显示清晰,操作按钮符合用户预期
4. **异常处理**: 对于未知状态要有合适的默认显示
## 后续优化建议
1. **状态枚举**: 考虑使用枚举类型定义订单状态,提高代码可读性
2. **状态机**: 实现订单状态机,确保状态流转的合法性
3. **国际化**: 支持订单状态文本的多语言显示
4. **实时更新**: 考虑实现订单状态的实时推送更新

1
template-10550/index.js Normal file
View File

@@ -0,0 +1 @@
import '@tarojs/rn-supporter/entry-file.js'

View File

@@ -0,0 +1,14 @@
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')
const { getMetroConfig } = require('@tarojs/rn-supporter')
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const config = {}
module.exports = (async function () {
return mergeConfig(getDefaultConfig(__dirname), await getMetroConfig(), config)
})()

107
template-10550/package.json Normal file
View File

@@ -0,0 +1,107 @@
{
"name": "template-10550",
"version": "1.0.0",
"private": true,
"description": "WebSoft Inc.",
"templateInfo": {
"name": "react-NutUI",
"typescript": true,
"css": "Sass",
"framework": "React"
},
"scripts": {
"build:weapp": "taro build --type weapp",
"build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt",
"build:h5": "taro build --type h5",
"build:rn": "taro build --type rn",
"build:qq": "taro build --type qq",
"build:jd": "taro build --type jd",
"build:quickapp": "taro build --type quickapp",
"dev:weapp": "npm run build:weapp -- --watch",
"dev:swan": "npm run build:swan -- --watch",
"dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch",
"dev:h5": "npm run build:h5 -- --watch",
"dev:rn": "npm run build:rn -- --watch",
"dev:qq": "npm run build:qq -- --watch",
"dev:jd": "npm run build:jd -- --watch",
"dev:quickapp": "npm run build:quickapp -- --watch",
"build:tailwind": "postcss --config tailwind.config.js -o ./dist/index.css ./src/app.css"
},
"browserslist": [
"last 3 versions",
"Android >= 4.1",
"ios >= 8"
],
"author": "",
"dependencies": {
"@babel/runtime": "^7.26.0",
"@nutui/icons-react-taro": "^2.0.1",
"@nutui/nutui-biz": "1.0.0-beta.2",
"@nutui/nutui-react": "^3.0.16",
"@nutui/nutui-react-taro": "^2.7.4",
"@react-native/metro-config": "^0.73.2",
"@tarojs/components": "4.0.8",
"@tarojs/components-rn": "^4.1.4",
"@tarojs/helper": "4.0.8",
"@tarojs/plugin-framework-react": "4.0.8",
"@tarojs/plugin-html": "4.0.8",
"@tarojs/plugin-platform-alipay": "4.0.8",
"@tarojs/plugin-platform-h5": "4.0.8",
"@tarojs/plugin-platform-jd": "4.0.8",
"@tarojs/plugin-platform-qq": "4.0.8",
"@tarojs/plugin-platform-swan": "4.0.8",
"@tarojs/plugin-platform-tt": "4.0.8",
"@tarojs/plugin-platform-weapp": "4.0.8",
"@tarojs/react": "4.0.8",
"@tarojs/rn-runner": "^4.1.4",
"@tarojs/rn-supporter": "^4.1.4",
"@tarojs/runtime": "4.0.8",
"@tarojs/runtime-rn": "^4.1.4",
"@tarojs/shared": "4.0.8",
"@tarojs/taro": "4.0.8",
"@tarojs/taro-rn": "^4.1.4",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
"echarts-taro3-react": "^1.0.13",
"expo": "~50.0.2",
"js-base64": "^3.7.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-markdown": "^10.1.0",
"react-native": "^0.73.1",
"react-router-dom": "^7.1.1"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@babel/plugin-proposal-class-properties": "7.14.5",
"@babel/preset-react": "^7.26.3",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
"@tarojs/cli": "4.0.8",
"@tarojs/taro-loader": "4.0.8",
"@tarojs/webpack5-runner": "4.0.8",
"@types/node": "^18.19.68",
"@types/react": "^18.3.18",
"@types/webpack-env": "^1.18.5",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"autoprefixer": "^10.4.20",
"babel-plugin-import": "^1.13.8",
"babel-preset-taro": "4.0.8",
"eslint": "^8.57.1",
"eslint-config-taro": "4.0.8",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.49",
"react-refresh": "^0.11.0",
"stylelint": "^14.16.1",
"tailwindcss": "^3.4.17",
"ts-node": "^10.9.2",
"tsconfig-paths-webpack-plugin": "^4.2.0",
"typescript": "^5.7.2",
"webpack": "5.78.0"
}
}

22732
template-10550/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -0,0 +1,25 @@
{
"miniprogramRoot": "dist/",
"projectname": "template-10550",
"description": "时里院子市集",
"appid": "wx5170f9f17a813877",
"setting": {
"urlCheck": true,
"es6": false,
"enhance": false,
"compileHotReLoad": false,
"postcss": false,
"preloadBackgroundData": false,
"minified": false,
"newFeature": true,
"autoAudits": false,
"coverView": true,
"showShadowRootInWxmlPanel": false,
"scopeDataCheck": false,
"useCompilerModule": false
},
"compileType": "miniprogram",
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {}
}

View File

@@ -0,0 +1,13 @@
{
"miniprogramRoot": "./",
"projectname": "mp-react",
"description": "时里院子市集",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}

View File

@@ -0,0 +1,129 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { BszxBm, BszxBmParam } from './model';
/**
* 分页查询百色中学-报名记录
*/
export async function pageBszxBm(params: BszxBmParam) {
const res = await request.get<ApiResult<PageResult<BszxBm>>>(
'/bszx/bszx-bm/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询百色中学-报名记录列表
*/
export async function listBszxBm(params?: BszxBmParam) {
const res = await request.get<ApiResult<BszxBm[]>>(
'/bszx/bszx-bm',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加百色中学-报名记录
*/
export async function addBszxBm(data: BszxBm) {
const res = await request.post<ApiResult<BszxBm>>(
'/bszx/bszx-bm',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改百色中学-报名记录
*/
export async function updateBszxBm(data: BszxBm) {
const res = await request.put<ApiResult<unknown>>(
'/bszx/bszx-bm',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除百色中学-报名记录
*/
export async function removeBszxBm(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-bm/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除百色中学-报名记录
*/
export async function removeBatchBszxBm(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-bm/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询百色中学-报名记录
*/
export async function getBszxBm(id: number) {
const res = await request.get<ApiResult<BszxBm>>(
'/bszx/bszx-bm/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询应用-百色中学-报名记录列表
*/
export async function myPageBszxBm(params?: BszxBmParam) {
const res = await request.get<ApiResult<PageResult<BszxBm>>>(
'/bszx/bszx-bm/myPage',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
export async function getPoster() {
const res = await request.get<ApiResult<BszxBm>>(
'/bszx/bszx-bm/generatePoster'
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,70 @@
import type { PageParam } from '@/api/index';
/**
* 百色中学-报名记录
*/
export interface BszxBm {
// 自增ID
id?: number;
// 文章ID
articleId?: string;
// 类型
type?: number;
// 姓名
name?: string;
// 性别 1男 2女
sex?: string;
// 手机号码
phone?: string;
// 班级
className?: string;
// 年级
gradeName?: string;
// 居住地址
address?: string;
// 工作单位
workUnit?: string;
// 职务
position?: string;
// 是否能到场
present?: string;
// 年龄
age?: number;
// 人数
number?: number;
// 额外信息
extra?: string;
// 生成的邀请函存放路径
certificate?: string;
// 预定日期
dateTime?: string;
// 表单数据
formData?: string;
// 表单ID
formId?: number;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 百色中学-报名记录搜索条件
*/
export interface BszxBmParam extends PageParam {
id?: number;
userId?: number;
orderNo?: string;
limit?: number;
keywords?: string;
}

View File

@@ -0,0 +1,120 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { BszxClass, BszxClassParam } from './model';
/**
* 分页查询百色中学-班级
*/
export async function pageBszxClass(params: BszxClassParam) {
const res = await request.get<ApiResult<PageResult<BszxClass>>>(
'/bszx/bszx-class/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询百色中学-班级列表
*/
export async function listBszxClass(params?: BszxClassParam) {
const res = await request.get<ApiResult<BszxClass[]>>(
'/bszx/bszx-class',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加百色中学-班级
*/
export async function addBszxClass(data: BszxClass) {
const res = await request.post<ApiResult<unknown>>(
'/bszx/bszx-class',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改百色中学-班级
*/
export async function updateBszxClass(data: BszxClass) {
const res = await request.put<ApiResult<unknown>>(
'/bszx/bszx-class',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除百色中学-班级
*/
export async function removeBszxClass(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-class/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除百色中学-班级
*/
export async function removeBatchBszxClass(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-class/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询百色中学-班级
*/
export async function getBszxClass(id: number) {
const res = await request.get<ApiResult<BszxClass>>(
'/bszx/bszx-class/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询应用-百色中学-班级列表
*/
export async function getBszxClassForTree() {
const res = await request.get<ApiResult<BszxClass[]>>(
'/bszx/bszx-class/tree'
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,37 @@
import type { PageParam } from '@/api/index';
/**
* 百色中学-班级
*/
export interface BszxClass {
// ID
id?: number;
// 时代ID
eraId?: number;
// 年级ID
gradeId?: number;
// 班级
name?: string;
// 班级
text?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 子级
children?: BszxClass[];
}
/**
* 百色中学-班级搜索条件
*/
export interface BszxClassParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,105 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { BszxEra, BszxEraParam } from './model';
/**
* 分页查询百色中学-年代
*/
export async function pageBszxEra(params: BszxEraParam) {
const res = await request.get<ApiResult<PageResult<BszxEra>>>(
'/bszx/bszx-era/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询百色中学-年代列表
*/
export async function listBszxEra(params?: BszxEraParam) {
const res = await request.get<ApiResult<BszxEra[]>>(
'/bszx/bszx-era',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加百色中学-年代
*/
export async function addBszxEra(data: BszxEra) {
const res = await request.post<ApiResult<unknown>>(
'/bszx/bszx-era',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改百色中学-年代
*/
export async function updateBszxEra(data: BszxEra) {
const res = await request.put<ApiResult<unknown>>(
'/bszx/bszx-era',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除百色中学-年代
*/
export async function removeBszxEra(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-era/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除百色中学-年代
*/
export async function removeBatchBszxEra(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-era/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询百色中学-年代
*/
export async function getBszxEra(id: number) {
const res = await request.get<ApiResult<BszxEra>>(
'/bszx/bszx-era/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,21 @@
import type { PageParam } from '@/api/index';
/**
* 百色中学-年代
*/
export interface BszxEra {
// ID
id?: number;
// 年代
name?: string;
// 租户id
tenantId?: number;
}
/**
* 百色中学-年代搜索条件
*/
export interface BszxEraParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,105 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { BszxGrade, BszxGradeParam } from './model';
/**
* 分页查询百色中学-年级
*/
export async function pageBszxGrade(params: BszxGradeParam) {
const res = await request.get<ApiResult<PageResult<BszxGrade>>>(
'/bszx/bszx-grade/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询百色中学-年级列表
*/
export async function listBszxGrade(params?: BszxGradeParam) {
const res = await request.get<ApiResult<BszxGrade[]>>(
'/bszx/bszx-grade',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加百色中学-年级
*/
export async function addBszxGrade(data: BszxGrade) {
const res = await request.post<ApiResult<unknown>>(
'/bszx/bszx-grade',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改百色中学-年级
*/
export async function updateBszxGrade(data: BszxGrade) {
const res = await request.put<ApiResult<unknown>>(
'/bszx/bszx-grade',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除百色中学-年级
*/
export async function removeBszxGrade(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-grade/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除百色中学-年级
*/
export async function removeBatchBszxGrade(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-grade/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询百色中学-年级
*/
export async function getBszxGrade(id: number) {
const res = await request.get<ApiResult<BszxGrade>>(
'/bszx/bszx-grade/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,31 @@
import type { PageParam } from '@/api/index';
/**
* 百色中学-年级
*/
export interface BszxGrade {
// ID
id?: number;
// 年级
name?: string;
// 年代
eraId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 百色中学-年级搜索条件
*/
export interface BszxGradeParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,138 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type {BszxPay, BszxPayParam} from "@/api/bszx/bszxPay/model";
import type {BszxBm,BszxBmParam} from "@/api/bszx/bszxBm/model";
/**
* 分页查询百色中学-捐款记录
*/
export async function pageBszxPay(params: BszxPayParam) {
const res = await request.get<ApiResult<PageResult<BszxPay>>>(
'/bszx/bszx-pay/page',
params
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询百色中学-捐款记录列表
*/
export async function listBszxPay(params?: BszxPayParam) {
const res = await request.get<ApiResult<BszxPay[]>>(
'/bszx/bszx-pay',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加百色中学-捐款记录
*/
export async function addBszxPay(data: BszxPay) {
const res = await request.post<ApiResult<BszxPay>>(
'/bszx/bszx-pay',
data
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改百色中学-捐款记录
*/
export async function updateBszxPay(data: BszxPay) {
const res = await request.put<ApiResult<unknown>>(
'/bszx/bszx-pay',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除百色中学-捐款记录
*/
export async function removeBszxPay(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-pay/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除百色中学-捐款记录
*/
export async function removeBatchBszxPay(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/bszx/bszx-pay/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询百色中学-捐款记录
*/
export async function getBszxPay(id: number) {
const res = await request.get<ApiResult<BszxPay>>(
'/bszx/bszx-pay/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询应用-百色中学-报名记录列表
*/
export async function myPageBszxPay(params?: BszxBmParam) {
const res = await request.get<ApiResult<PageResult<BszxBm>>>(
'/bszx/bszx-pay/myPage',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
export async function getPayCert(id: number) {
const res = await request.get<ApiResult<BszxBm>>(
'/bszx/bszx-pay/generatePayCert/' + id, {}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
export async function getCount() {
const res = await request.get<ApiResult<any>>(
'/bszx/bszx-pay/getCount'
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,80 @@
import type { PageParam } from '@/api/index';
import {CmsArticle} from "@/api/cms/cmsArticle/model";
/**
* 百色中学-捐款记录
*/
export interface BszxPay {
// ID
id?: number;
// 年龄
age?: number;
// 姓名
name?: string;
// 性别 1男 2女
sex?: string;
// 手机号码
phone?: string;
// 班级
className?: string;
// 年级
gradeName?: string;
// 居住地址
address?: string;
// 工作单位
workUnit?: string;
// 职务
position?: string;
// 数量
number?: number;
// 价格
price?: string;
// 额外信息
extra?: string;
// 预定日期
dateTime?: string;
// 捐赠证书
certificate?: string;
// 表单数据
formData?: string;
// 表单ID
formId?: number;
// 表单名称
formName?: string;
// 订单号
orderNo?: string;
// 用户ID
userId?: number;
// 头像
avatar?: string;
// 昵称
nickname?: string;
// 真实姓名
realName?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
present?: any;
// 关联的文章
article?: CmsArticle;
}
/**
* 百色中学-捐款记录搜索条件
*/
export interface BszxPayParam extends PageParam {
id?: number;
userId?: number;
formId?: number;
orderNo?: string;
keywords?: string;
}

View File

@@ -0,0 +1,102 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsAd, CmsAdParam } from './model';
/**
* 分页查询广告位
*/
export async function pageCmsAd(params: CmsAdParam) {
const res = await request.get<ApiResult<PageResult<CmsAd>>>(
'/cms/cms-ad/page',
params
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询广告位列表
*/
export async function listCmsAd(params?: CmsAdParam) {
const res = await request.get<ApiResult<CmsAd[]>>(
'/cms/cms-ad',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加广告位
*/
export async function addCmsAd(data: CmsAd) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-ad',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改广告位
*/
export async function updateCmsAd(data: CmsAd) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-ad',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除广告位
*/
export async function removeCmsAd(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-ad/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除广告位
*/
export async function removeBatchCmsAd(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-ad/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询广告位
*/
export async function getCmsAd(id: number) {
const res = await request.get<ApiResult<CmsAd>>(
'/cms/cms-ad/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,59 @@
import type { PageParam } from '@/api/index';
/**
* 广告位
*/
export interface CmsAd {
// ID
adId?: number;
// 页面ID
designId?: number;
// 广告类型
adType?: string;
// 广告类型
type?: string;
// 广告位名称
name?: string;
// 宽
width?: string;
// 高
height?: string;
// 广告图片
images?: string;
// 图片列表
imageList?: any[];
// 路由/链接地址
path?: string;
// 用户ID
userId?: number;
// 页面ID
pageId?: number;
// 页面名称
pageName?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
merchantId?: number;
// 图片数组
imgArr?: any[];
}
/**
* 广告位搜索条件
*/
export interface CmsAdParam extends PageParam {
adId?: number;
adType?: string;
pageId?: number;
pageName?: string;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsAdRecord, CmsAdRecordParam } from './model';
/**
* 分页查询广告图片
*/
export async function pageCmsAdRecord(params: CmsAdRecordParam) {
const res = await request.get<ApiResult<PageResult<CmsAdRecord>>>(
'/cms/cms-ad-record/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询广告图片列表
*/
export async function listCmsAdRecord(params?: CmsAdRecordParam) {
const res = await request.get<ApiResult<CmsAdRecord[]>>(
'/cms/cms-ad-record',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加广告图片
*/
export async function addCmsAdRecord(data: CmsAdRecord) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-ad-record',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改广告图片
*/
export async function updateCmsAdRecord(data: CmsAdRecord) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-ad-record',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除广告图片
*/
export async function removeCmsAdRecord(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-ad-record/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除广告图片
*/
export async function removeBatchCmsAdRecord(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-ad-record/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询广告图片
*/
export async function getCmsAdRecord(id: number) {
const res = await request.get<ApiResult<CmsAdRecord>>(
'/cms/cms-ad-record/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,35 @@
import type { PageParam } from '@/api';
/**
* 广告图片
*/
export interface CmsAdRecord {
// ID
adRecordId?: number;
// 广告标题
title?: string;
// 图片地址
path?: string;
// 链接地址
url?: string;
// 广告位ID
adId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 广告图片搜索条件
*/
export interface CmsAdRecordParam extends PageParam {
adRecordId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,206 @@
import request from '@/utils/request';
import type {ApiResult, PageResult} from '@/api/index';
import type {CmsArticle, CmsArticleParam} from './model';
/**
* 分页查询文章
*/
export async function pageCmsArticle(params: CmsArticleParam) {
const res = await request.get<ApiResult<PageResult<CmsArticle>>>(
'/cms/cms-article/page',
params
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询文章列表
*/
export async function listCmsArticle(params?: CmsArticleParam) {
const res = await request.get<ApiResult<CmsArticle[]>>(
'/cms/cms-article',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加文章
*/
export async function addCmsArticle(data: CmsArticle) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-article',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改文章
*/
export async function updateCmsArticle(data: CmsArticle) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-article',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除文章
*/
export async function removeCmsArticle(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除文章
*/
export async function removeBatchCmsArticle(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询文章
*/
export async function getCmsArticle(id: number) {
const res = await request.get<ApiResult<CmsArticle>>(
'/cms/cms-article/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
export async function getCount(params?: CmsArticleParam) {
const res = await request.get<ApiResult<unknown>>('/cms/cms-article/data', {
params
});
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 上一篇
* @param params
*/
export async function getPrevious(params?: CmsArticleParam) {
const res = await request.get<ApiResult<CmsArticle>>(
'/cms/cms-article/getPrevious/' + params?.articleId,
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 下一篇
* @param params
*/
export async function getNext(params?: CmsArticleParam) {
const res = await request.get<ApiResult<CmsArticle>>(
'/cms/cms-article/getNext/' + params?.articleId,
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 验证文章密码
* @param params
*/
export async function checkArticlePassword(params?: CmsArticleParam) {
const res = await request.get<ApiResult<unknown>>(
'/cms/cms-article/checkArticlePassword',
{
params
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
export async function findTags(params?: CmsArticleParam) {
const res = await request.get<ApiResult<CmsArticle[]>>(
'/cms/cms-article/findTags',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
export async function pageTags(params?: CmsArticleParam) {
const res = await request.get<ApiResult<CmsArticle[]>>(
'/cms/cms-article/pageTags',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 按IDS查询文章
* @param params
*/
export async function getByIds(params?: CmsArticleParam) {
const res = await request.get<ApiResult<CmsArticle[]>>(
'/cms/cms-article/getByIds',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,132 @@
import type { PageParam } from '@/api/index';
/**
* 文章
*/
export interface CmsArticle {
// 文章ID
articleId?: number;
// 文章标题
title?: string;
// 文章类型 0常规 1视频
type?: number;
// 文章模型
model?: string;
// 文章详情页模板
detail?: string;
// banner图片
banner?: string;
// 列表显示方式(10小图展示 20大图展示)
showType?: number;
// 话题
topic?: string;
// 标签
tags?: any;
// 栏目ID
categoryId?: number;
// 栏目名称
categoryName?: string;
// 封面图
image?: string;
// 价格
price?: number;
startTime?: any;
endTime?: any;
// 缩列图
thumbnail?: string;
// 来源
source?: string;
// 产品概述
overview?: string;
// 虚拟阅读量(仅用作展示)
virtualViews?: number;
// 实际阅读量
actualViews?: number;
// 购买人数
bmUsers?: number;
// 浏览权限(0公开 1会员 2密码)
permission?: number;
// 访问密码
password?: string;
// 确认密码
password2?: string;
// 发布来源客户端 (APP、H5、小程序等)
platform?: string;
// 文章附件
files?: string;
// 视频地址
video?: string;
// 接受的文件类型
accept?: string;
// 经度
longitude?: string;
// 纬度
latitude?: string;
// 所在省份
province?: string;
// 所在城市
city?: string;
// 所在辖区
region?: string;
// 街道地址
address?: string;
// 点赞数
likes?: number;
// pdf地址
pdfUrl?: string;
// 评论数
commentNumbers?: number;
// 提醒谁看
toUsers?: string;
// 文章内容
content?: string;
// 是否推荐
recommend?: number;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0已发布, 1待审核 2已驳回 3违规内容
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
// 父级id
parentId?: number;
nickname?: string;
username?: string;
author?: string;
shopId?: number;
tenantName?: string;
logo?: string;
fileList?: any;
// 编辑器类型
editor?: number;
}
/**
* 文章搜索条件
*/
export interface CmsArticleParam extends PageParam {
articleId?: number;
articleIds?: string;
categoryId?: number;
parentId?: number;
status?: number;
// 是否推荐
recommend?: number;
keywords?: string;
// 验证密码
password?: string;
password2?: string;
tags?: string;
detail?: string;
sceneType?: string;
}

View File

@@ -0,0 +1,108 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsArticleCategory, CmsArticleCategoryParam } from './model';
/**
* 分页查询文章分类表
*/
export async function pageCmsArticleCategory(params: CmsArticleCategoryParam) {
const res = await request.get<ApiResult<PageResult<CmsArticleCategory>>>(
'/cms/cms-article-category/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询文章分类表列表
*/
export async function listCmsArticleCategory(params?: CmsArticleCategoryParam) {
const res = await request.get<ApiResult<CmsArticleCategory[]>>(
'/cms/cms-article-category',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加文章分类表
*/
export async function addCmsArticleCategory(data: CmsArticleCategory) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-article-category',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改文章分类表
*/
export async function updateCmsArticleCategory(data: CmsArticleCategory) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-article-category',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除文章分类表
*/
export async function removeCmsArticleCategory(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-category/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除文章分类表
*/
export async function removeBatchCmsArticleCategory(
data: (number | undefined)[]
) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-category/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询文章分类表
*/
export async function getCmsArticleCategory(id: number) {
const res = await request.get<ApiResult<CmsArticleCategory>>(
'/cms/cms-article-category/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,59 @@
import type { PageParam } from '@/api/index';
/**
* 文章分类表
*/
export interface CmsArticleCategory {
// 文章分类ID
categoryId?: number;
// 分类标识
categoryCode?: string;
// 分类名称
title?: string;
// 类型 0列表 1单页 2外链
type?: number;
// 分类图片
image?: string;
// 上级分类ID
parentId?: number;
// 路由/链接地址
path?: string;
// 组件路径
component?: string;
// 绑定的页面
pageId?: number;
// 用户ID
userId?: number;
// 文章数量
count?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)
hide?: number;
// 是否推荐
recommend?: number;
// 是否显示在首页
showIndex?: number;
// 状态, 0正常, 1禁用
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
value?: number;
label?: string;
}
/**
* 文章分类表搜索条件
*/
export interface CmsArticleCategoryParam extends PageParam {
categoryId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsArticleComment, CmsArticleCommentParam } from './model';
/**
* 分页查询文章评论表
*/
export async function pageCmsArticleComment(params: CmsArticleCommentParam) {
const res = await request.get<ApiResult<PageResult<CmsArticleComment>>>(
'/cms/cms-article-comment/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询文章评论表列表
*/
export async function listCmsArticleComment(params?: CmsArticleCommentParam) {
const res = await request.get<ApiResult<CmsArticleComment[]>>(
'/cms/cms-article-comment',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加文章评论表
*/
export async function addCmsArticleComment(data: CmsArticleComment) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-article-comment',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改文章评论表
*/
export async function updateCmsArticleComment(data: CmsArticleComment) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-article-comment',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除文章评论表
*/
export async function removeCmsArticleComment(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-comment/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除文章评论表
*/
export async function removeBatchCmsArticleComment(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-comment/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询文章评论表
*/
export async function getCmsArticleComment(id: number) {
const res = await request.get<ApiResult<CmsArticleComment>>(
'/cms/cms-article-comment/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,47 @@
import type { PageParam } from '@/api';
/**
* 文章评论表
*/
export interface CmsArticleComment {
// 评价ID
commentId?: number;
// 文章ID
articleId?: number;
// 评分 (10好评 20中评 30差评)
score?: number;
// 评价内容
content?: string;
// 是否为图片评价
isPicture?: number;
// 评论者ID
userId?: number;
// 被评价者ID
toUserId?: number;
// 回复的评论ID
replyCommentId?: number;
// 回复者ID
replyUserId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0未读, 1已读
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* 文章评论表搜索条件
*/
export interface CmsArticleCommentParam extends PageParam {
commentId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsArticleContent, CmsArticleContentParam } from './model';
/**
* 分页查询文章记录表
*/
export async function pageCmsArticleContent(params: CmsArticleContentParam) {
const res = await request.get<ApiResult<PageResult<CmsArticleContent>>>(
'/cms/cms-article-content/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询文章记录表列表
*/
export async function listCmsArticleContent(params?: CmsArticleContentParam) {
const res = await request.get<ApiResult<CmsArticleContent[]>>(
'/cms/cms-article-content',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加文章记录表
*/
export async function addCmsArticleContent(data: CmsArticleContent) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-article-content',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改文章记录表
*/
export async function updateCmsArticleContent(data: CmsArticleContent) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-article-content',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除文章记录表
*/
export async function removeCmsArticleContent(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-content/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除文章记录表
*/
export async function removeBatchCmsArticleContent(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-content/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询文章记录表
*/
export async function getCmsArticleContent(id: number) {
const res = await request.get<ApiResult<CmsArticleContent>>(
'/cms/cms-article-content/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,25 @@
import type { PageParam } from '@/api';
/**
* 文章记录表
*/
export interface CmsArticleContent {
//
id?: number;
// 文章ID
articleId?: number;
// 文章内容
content?: string;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 文章记录表搜索条件
*/
export interface CmsArticleContentParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsArticleCount, CmsArticleCountParam } from './model';
/**
* 分页查询点赞文章
*/
export async function pageCmsArticleCount(params: CmsArticleCountParam) {
const res = await request.get<ApiResult<PageResult<CmsArticleCount>>>(
'/cms/cms-article-count/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询点赞文章列表
*/
export async function listCmsArticleCount(params?: CmsArticleCountParam) {
const res = await request.get<ApiResult<CmsArticleCount[]>>(
'/cms/cms-article-count',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加点赞文章
*/
export async function addCmsArticleCount(data: CmsArticleCount) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-article-count',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改点赞文章
*/
export async function updateCmsArticleCount(data: CmsArticleCount) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-article-count',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除点赞文章
*/
export async function removeCmsArticleCount(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-count/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除点赞文章
*/
export async function removeBatchCmsArticleCount(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-count/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询点赞文章
*/
export async function getCmsArticleCount(id: number) {
const res = await request.get<ApiResult<CmsArticleCount>>(
'/cms/cms-article-count/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,25 @@
import type { PageParam } from '@/api';
/**
* 点赞文章
*/
export interface CmsArticleCount {
// 主键ID
id?: number;
// 文章ID
articleId?: number;
// 用户ID
userId?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 点赞文章搜索条件
*/
export interface CmsArticleCountParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsArticleLike, CmsArticleLikeParam } from './model';
/**
* 分页查询点赞文章
*/
export async function pageCmsArticleLike(params: CmsArticleLikeParam) {
const res = await request.get<ApiResult<PageResult<CmsArticleLike>>>(
'/cms/cms-article-like/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询点赞文章列表
*/
export async function listCmsArticleLike(params?: CmsArticleLikeParam) {
const res = await request.get<ApiResult<CmsArticleLike[]>>(
'/cms/cms-article-like',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加点赞文章
*/
export async function addCmsArticleLike(data: CmsArticleLike) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-article-like',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改点赞文章
*/
export async function updateCmsArticleLike(data: CmsArticleLike) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-article-like',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除点赞文章
*/
export async function removeCmsArticleLike(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-like/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除点赞文章
*/
export async function removeBatchCmsArticleLike(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-article-like/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询点赞文章
*/
export async function getCmsArticleLike(id: number) {
const res = await request.get<ApiResult<CmsArticleLike>>(
'/cms/cms-article-like/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,25 @@
import type { PageParam } from '@/api';
/**
* 点赞文章
*/
export interface CmsArticleLike {
// 主键ID
id?: number;
// 文章ID
articleId?: number;
// 用户ID
userId?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 点赞文章搜索条件
*/
export interface CmsArticleLikeParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsComponents, CmsComponentsParam } from './model';
/**
* 分页查询组件
*/
export async function pageCmsComponents(params: CmsComponentsParam) {
const res = await request.get<ApiResult<PageResult<CmsComponents>>>(
'/cms/cms-components/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询组件列表
*/
export async function listCmsComponents(params?: CmsComponentsParam) {
const res = await request.get<ApiResult<CmsComponents[]>>(
'/cms/cms-components',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加组件
*/
export async function addCmsComponents(data: CmsComponents) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-components',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改组件
*/
export async function updateCmsComponents(data: CmsComponents) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-components',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除组件
*/
export async function removeCmsComponents(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-components/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除组件
*/
export async function removeBatchCmsComponents(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-components/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询组件
*/
export async function getCmsComponents(id: number) {
const res = await request.get<ApiResult<CmsComponents>>(
'/cms/cms-components/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,43 @@
import type { PageParam } from '@/api';
/**
* 组件
*/
export interface CmsComponents {
// ID
id?: number;
// 组件标题
title?: string;
// 关联导航ID
navigationId?: number;
// 组件类型
type?: string;
// 页面关键词
keywords?: string;
// 页面描述
description?: string;
// 组件路径
path?: string;
// 组件图标
icon?: string;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 组件搜索条件
*/
export interface CmsComponentsParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,102 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsDesign, CmsDesignParam } from './model';
/**
* 分页查询页面管理记录表
*/
export async function pageCmsDesign(params: CmsDesignParam) {
const res = await request.get<ApiResult<PageResult<CmsDesign>>>(
'/cms/cms-design/page',
params
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询页面管理记录表列表
*/
export async function listCmsDesign(params?: CmsDesignParam) {
const res = await request.get<ApiResult<CmsDesign[]>>(
'/cms/cms-design',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加页面管理记录表
*/
export async function addCmsDesign(data: CmsDesign) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-design',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改页面管理记录表
*/
export async function updateCmsDesign(data: CmsDesign) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-design',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除页面管理记录表
*/
export async function removeCmsDesign(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-design/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除页面管理记录表
*/
export async function removeBatchCmsDesign(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-design/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询页面管理记录表
*/
export async function getCmsDesign(id: number) {
const res = await request.get<ApiResult<CmsDesign>>(
'/cms/cms-design/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,60 @@
import type { PageParam } from '@/api/index';
/**
* 页面管理记录表
*/
export interface CmsDesign {
pageId?: number;
name?: string;
keywords?: string;
description?: string;
path?: string;
component?: string;
photo?: string;
content?: string;
// 类型
type?: string;
categoryId?: number;
// 宽
width?: string;
// 高
height?: string;
// 页面样式
style?: string;
// 附件
images?: string;
// 用户ID
userId?: number;
// 设为首页
home?: number;
// 排序
sortNumber?: number;
// 备注
comments?: string;
// 状态
status?: number;
// 创建时间
createTime?: string;
// 更新时间
updateTime?: string;
// 页面布局
layout?: string;
backgroundColor?: string;
// 关联网站导航ID
navigationId?: number;
showLayout?: boolean;
btn?: any[];
showBanner?: boolean;
buyUrl?: string;
demoUrl?: string;
account?: string;
docUrl?: string;
}
/**
* 页面管理记录表搜索条件
*/
export interface CmsDesignParam extends PageParam {
pageId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsDesignRecord, CmsDesignRecordParam } from './model';
/**
* 分页查询页面组件表
*/
export async function pageCmsDesignRecord(params: CmsDesignRecordParam) {
const res = await request.get<ApiResult<PageResult<CmsDesignRecord>>>(
'/cms/cms-design-record/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询页面组件表列表
*/
export async function listCmsDesignRecord(params?: CmsDesignRecordParam) {
const res = await request.get<ApiResult<CmsDesignRecord[]>>(
'/cms/cms-design-record',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加页面组件表
*/
export async function addCmsDesignRecord(data: CmsDesignRecord) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-design-record',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改页面组件表
*/
export async function updateCmsDesignRecord(data: CmsDesignRecord) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-design-record',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除页面组件表
*/
export async function removeCmsDesignRecord(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-design-record/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除页面组件表
*/
export async function removeBatchCmsDesignRecord(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-design-record/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询页面组件表
*/
export async function getCmsDesignRecord(id: number) {
const res = await request.get<ApiResult<CmsDesignRecord>>(
'/cms/cms-design-record/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,51 @@
import type { PageParam } from '@/api';
/**
* 页面组件表
*/
export interface CmsDesignRecord {
// ID
id?: number;
// 关联导航ID
navigationId?: number;
parentId?: number;
pageId?: number;
// 组件
title?: string;
// 组件标识
dictCode?: string;
// 组件样式
styles?: string;
// 卡片阴影显示时机
shadow?: string;
// 页面关键词
keywords?: string;
// 页面描述
description?: string;
// 页面路由地址
path?: string;
// 缩列图
photo?: string;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 所属期次
periodId?: number;
}
/**
* 页面组件表搜索条件
*/
export interface CmsDesignRecordParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsDocs, CmsDocsParam } from './model';
/**
* 分页查询文档管理记录表
*/
export async function pageCmsDocs(params: CmsDocsParam) {
const res = await request.get<ApiResult<PageResult<CmsDocs>>>(
'/cms/cms-docs/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询文档管理记录表列表
*/
export async function listCmsDocs(params?: CmsDocsParam) {
const res = await request.get<ApiResult<CmsDocs[]>>(
'/cms/cms-docs',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加文档管理记录表
*/
export async function addCmsDocs(data: CmsDocs) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-docs',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改文档管理记录表
*/
export async function updateCmsDocs(data: CmsDocs) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-docs',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除文档管理记录表
*/
export async function removeCmsDocs(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-docs/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除文档管理记录表
*/
export async function removeBatchCmsDocs(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-docs/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询文档管理记录表
*/
export async function getCmsDocs(id: number) {
const res = await request.get<ApiResult<CmsDocs>>(
'/cms/cms-docs/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,45 @@
import type { PageParam } from '@/api';
/**
* 文档管理记录表
*/
export interface CmsDocs {
// 文档ID
docsId?: number;
// 文档标题
title?: string;
// 上级目录
parentId?: number;
// 书籍ID
bookId?: number;
// 可见性(public,private,protected)
visibility?: string;
// 虚拟阅读量(仅用作展示)
virtualViews?: number;
// 实际阅读量
actualViews?: number;
// 用户ID
userId?: number;
// 备注
comments?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* 文档管理记录表搜索条件
*/
export interface CmsDocsParam extends PageParam {
docsId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsDocsBook, CmsDocsBookParam } from './model';
/**
* 分页查询书籍记录表
*/
export async function pageCmsDocsBook(params: CmsDocsBookParam) {
const res = await request.get<ApiResult<PageResult<CmsDocsBook>>>(
'/cms/cms-docs-book/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询书籍记录表列表
*/
export async function listCmsDocsBook(params?: CmsDocsBookParam) {
const res = await request.get<ApiResult<CmsDocsBook[]>>(
'/cms/cms-docs-book',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加书籍记录表
*/
export async function addCmsDocsBook(data: CmsDocsBook) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-docs-book',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改书籍记录表
*/
export async function updateCmsDocsBook(data: CmsDocsBook) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-docs-book',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除书籍记录表
*/
export async function removeCmsDocsBook(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-docs-book/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除书籍记录表
*/
export async function removeBatchCmsDocsBook(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-docs-book/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询书籍记录表
*/
export async function getCmsDocsBook(id: number) {
const res = await request.get<ApiResult<CmsDocsBook>>(
'/cms/cms-docs-book/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,37 @@
import type { PageParam } from '@/api';
/**
* 书籍记录表
*/
export interface CmsDocsBook {
// ID
bookId?: number;
// 书籍名称
name?: string;
// 书籍标识
code?: string;
// 封面图
photo?: string;
// 备注
comments?: string;
// 文档内容
content?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 书籍记录表搜索条件
*/
export interface CmsDocsBookParam extends PageParam {
bookId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsDocsContent, CmsDocsContentParam } from './model';
/**
* 分页查询文档内容记录表
*/
export async function pageCmsDocsContent(params: CmsDocsContentParam) {
const res = await request.get<ApiResult<PageResult<CmsDocsContent>>>(
'/cms/cms-docs-content/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询文档内容记录表列表
*/
export async function listCmsDocsContent(params?: CmsDocsContentParam) {
const res = await request.get<ApiResult<CmsDocsContent[]>>(
'/cms/cms-docs-content',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加文档内容记录表
*/
export async function addCmsDocsContent(data: CmsDocsContent) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-docs-content',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改文档内容记录表
*/
export async function updateCmsDocsContent(data: CmsDocsContent) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-docs-content',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除文档内容记录表
*/
export async function removeCmsDocsContent(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-docs-content/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除文档内容记录表
*/
export async function removeBatchCmsDocsContent(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-docs-content/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询文档内容记录表
*/
export async function getCmsDocsContent(id: number) {
const res = await request.get<ApiResult<CmsDocsContent>>(
'/cms/cms-docs-content/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,25 @@
import type { PageParam } from '@/api';
/**
* 文档内容记录表
*/
export interface CmsDocsContent {
// ID
id?: number;
// 文档ID
docsId?: number;
// 文档内容
content?: string;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 文档内容记录表搜索条件
*/
export interface CmsDocsContentParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,151 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsDomain, CmsDomainParam } from './model';
import {SERVER_API_URL} from "@/utils/server";
/**
* 分页查询网站域名记录表
*/
export async function pageCmsDomain(params: CmsDomainParam) {
const res = await request.get<ApiResult<PageResult<CmsDomain>>>(
SERVER_API_URL + '/cms/cms-domain/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询网站域名记录表列表
*/
export async function listCmsDomain(params?: CmsDomainParam) {
const res = await request.get<ApiResult<CmsDomain[]>>(
SERVER_API_URL + '/cms/cms-domain',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加网站域名记录表
*/
export async function addCmsDomain(data: CmsDomain) {
const res = await request.post<ApiResult<unknown>>(
SERVER_API_URL + '/cms/cms-domain',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改网站域名记录表
*/
export async function updateCmsDomain(data: CmsDomain) {
const res = await request.post<ApiResult<unknown>>(
SERVER_API_URL + '/cms/cms-domain/domain',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除网站域名记录表
*/
export async function removeCmsDomain(id?: number) {
const res = await request.del<ApiResult<unknown>>(
SERVER_API_URL + '/cms/cms-domain/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除网站域名记录表
*/
export async function removeBatchCmsDomain(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
SERVER_API_URL + '/cms/cms-domain/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询网站域名记录表
*/
export async function getCmsDomain(id: number) {
const res = await request.get<ApiResult<CmsDomain>>(
SERVER_API_URL + '/cms/cms-domain/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 检查IP是否存在
*/
export async function checkExistence(
field: string,
value: string,
id?: number
) {
const res = await request.get<ApiResult<unknown>>(
SERVER_API_URL + '/cms/domain/existence',
{
params: { field, value, id }
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
export async function resolvable(id: number) {
const res = await request.get<ApiResult<CmsDomain>>(
SERVER_API_URL + '/cms/domain/resolvable/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
export async function getTenantIdByDomain(params: CmsDomainParam) {
const res = await request.get<ApiResult<PageResult<CmsDomain>>>(
SERVER_API_URL + '/cms/cms-domain/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,44 @@
import type { PageParam } from '@/api';
/**
* 网站域名记录表
*/
export interface CmsDomain {
// ID
id?: number;
// 类型 0赠送域名 1绑定域名
type?: number;
// 域名
domain?: string;
// 主机记录
hostName?: string;
// 记录值
hostValue?: string;
// 状态
status?: number;
// 排序号
sortNumber?: number;
// 网站ID
websiteId?: number;
// 租户ID
appId?: number;
// 用户ID
userId?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* 网站域名记录表搜索条件
*/
export interface CmsDomainParam extends PageParam {
id?: number;
domain?: string;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsForm, CmsFormParam } from './model';
/**
* 分页查询表单设计表
*/
export async function pageCmsForm(params: CmsFormParam) {
const res = await request.get<ApiResult<PageResult<CmsForm>>>(
'/cms/cms-form/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询表单设计表列表
*/
export async function listCmsForm(params?: CmsFormParam) {
const res = await request.get<ApiResult<CmsForm[]>>(
'/cms/cms-form',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加表单设计表
*/
export async function addCmsForm(data: CmsForm) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-form',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改表单设计表
*/
export async function updateCmsForm(data: CmsForm) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-form',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除表单设计表
*/
export async function removeCmsForm(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-form/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除表单设计表
*/
export async function removeBatchCmsForm(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-form/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询表单设计表
*/
export async function getCmsForm(id: number) {
const res = await request.get<ApiResult<CmsForm>>(
'/cms/cms-form/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,53 @@
import type { PageParam } from '@/api';
/**
* 表单设计表
*/
export interface CmsForm {
// ID
formId?: number;
// 表单标题
name?: string;
// 顶部图片
photo?: string;
// 背景图片
background?: string;
// 视频文件
video?: string;
// 提交次数
submitNumber?: number;
// 页面布局
layout?: string;
// 是否隐藏顶部图片
hidePhoto?: number;
// 是否隐藏背景图片
hideBackground?: number;
// 是否隐藏视频
hideVideo?: number;
// 背景图片透明度
opacity?: string;
// 用户ID
userId?: number;
// 商户ID
merchantId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 表单设计表搜索条件
*/
export interface CmsFormParam extends PageParam {
formId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsFormRecord, CmsFormRecordParam } from './model';
/**
* 分页查询表单数据记录表
*/
export async function pageCmsFormRecord(params: CmsFormRecordParam) {
const res = await request.get<ApiResult<PageResult<CmsFormRecord>>>(
'/cms/cms-form-record/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询表单数据记录表列表
*/
export async function listCmsFormRecord(params?: CmsFormRecordParam) {
const res = await request.get<ApiResult<CmsFormRecord[]>>(
'/cms/cms-form-record',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加表单数据记录表
*/
export async function addCmsFormRecord(data: CmsFormRecord) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-form-record',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改表单数据记录表
*/
export async function updateCmsFormRecord(data: CmsFormRecord) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-form-record',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除表单数据记录表
*/
export async function removeCmsFormRecord(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-form-record/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除表单数据记录表
*/
export async function removeBatchCmsFormRecord(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-form-record/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询表单数据记录表
*/
export async function getCmsFormRecord(id: number) {
const res = await request.get<ApiResult<CmsFormRecord>>(
'/cms/cms-form-record/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,41 @@
import type { PageParam } from '@/api/index';
/**
* 表单数据记录表
*/
export interface CmsFormRecord {
// ID
formRecordId?: number;
// 手机号
phone?: string;
// 表单数据
formData?: string;
// 表单ID
formId?: number;
// 用户ID
userId?: number;
// 商户ID
merchantId?: number;
// 姓名
name?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 表单数据记录表搜索条件
*/
export interface CmsFormRecordParam extends PageParam {
formRecordId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,105 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsLang, CmsLangParam } from './model';
/**
* 分页查询国际化
*/
export async function pageCmsLang(params: CmsLangParam) {
const res = await request.get<ApiResult<PageResult<CmsLang>>>(
'/cms/cms-lang/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询国际化列表
*/
export async function listCmsLang(params?: CmsLangParam) {
const res = await request.get<ApiResult<CmsLang[]>>(
'/cms/cms-lang',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加国际化
*/
export async function addCmsLang(data: CmsLang) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-lang',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改国际化
*/
export async function updateCmsLang(data: CmsLang) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-lang',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除国际化
*/
export async function removeCmsLang(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-lang/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除国际化
*/
export async function removeBatchCmsLang(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-lang/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询国际化
*/
export async function getCmsLang(id: number) {
const res = await request.get<ApiResult<CmsLang>>(
'/cms/cms-lang/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,39 @@
import type { PageParam } from '@/api';
/**
* 国际化
*/
export interface CmsLang {
// ID
id?: number;
// 名称
name?: string;
// 菜单组件地址, 目录可为空
code?: string;
// 启用语言
lang?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 0禁用 1启用
enable?: boolean;
// 状态, 0禁用 1启用
status?: boolean;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* 国际化搜索条件
*/
export interface CmsLangParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,105 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsLangLog, CmsLangLogParam } from './model';
/**
* 分页查询国际化记录启用
*/
export async function pageCmsLangLog(params: CmsLangLogParam) {
const res = await request.get<ApiResult<PageResult<CmsLangLog>>>(
'/cms/cms-lang-log/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询国际化记录启用列表
*/
export async function listCmsLangLog(params?: CmsLangLogParam) {
const res = await request.get<ApiResult<CmsLangLog[]>>(
'/cms/cms-lang-log',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加国际化记录启用
*/
export async function addCmsLangLog(data: CmsLangLog) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-lang-log',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改国际化记录启用
*/
export async function updateCmsLangLog(data: CmsLangLog) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-lang-log',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除国际化记录启用
*/
export async function removeCmsLangLog(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-lang-log/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除国际化记录启用
*/
export async function removeBatchCmsLangLog(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-lang-log/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询国际化记录启用
*/
export async function getCmsLangLog(id: number) {
const res = await request.get<ApiResult<CmsLangLog>>(
'/cms/cms-lang-log/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,27 @@
import type { PageParam } from '@/api';
/**
* 国际化记录启用
*/
export interface CmsLangLog {
// ID
id?: number;
// 关联ID
langId?: number;
// 编码
code?: string;
// 名称
lang?: string;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 国际化记录启用搜索条件
*/
export interface CmsLangLogParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsLink, CmsLinkParam } from './model';
/**
* 分页查询常用链接
*/
export async function pageCmsLink(params: CmsLinkParam) {
const res = await request.get<ApiResult<PageResult<CmsLink>>>(
'/cms/cms-link/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询常用链接列表
*/
export async function listCmsLink(params?: CmsLinkParam) {
const res = await request.get<ApiResult<CmsLink[]>>(
'/cms/cms-link',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加常用链接
*/
export async function addCmsLink(data: CmsLink) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-link',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改常用链接
*/
export async function updateCmsLink(data: CmsLink) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-link',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除常用链接
*/
export async function removeCmsLink(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-link/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除常用链接
*/
export async function removeBatchCmsLink(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-link/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询常用链接
*/
export async function getCmsLink(id: number) {
const res = await request.get<ApiResult<CmsLink>>(
'/cms/cms-link/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,43 @@
import type { PageParam } from '@/api';
/**
* 常用链接
*/
export interface CmsLink {
// 自增ID
id?: number;
// 链接名称
name?: string;
// 图标
icon?: string;
// 链接地址
url?: string;
// 链接分类
linkType?: string;
// 应用ID
appId?: number;
// 用户ID
userId?: number;
// 是否推荐
recommend?: number;
// 备注
comments?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 状态, 0正常, 1待确认
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 常用链接搜索条件
*/
export interface CmsLinkParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsModel, CmsModelParam } from './model';
/**
* 分页查询模型
*/
export async function pageCmsModel(params: CmsModelParam) {
const res = await request.get<ApiResult<PageResult<CmsModel>>>(
'/cms/cms-model/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询模型列表
*/
export async function listCmsModel(params?: CmsModelParam) {
const res = await request.get<ApiResult<CmsModel[]>>(
'/cms/cms-model',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加模型
*/
export async function addCmsModel(data: CmsModel) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-model',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改模型
*/
export async function updateCmsModel(data: CmsModel) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-model',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除模型
*/
export async function removeCmsModel(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-model/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除模型
*/
export async function removeBatchCmsModel(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-model/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询模型
*/
export async function getCmsModel(id: number) {
const res = await request.get<ApiResult<CmsModel>>(
'/cms/cms-model/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,57 @@
import type { PageParam } from '@/api/index';
/**
* 模型
*/
export interface CmsModel {
// ID
modelId?: number;
// 模型名称
name?: string;
// 唯一标识
model?: string;
// 菜单路由地址
path?: string;
// 菜单组件地址, 目录可为空
component?: string;
// 模型banner图片
banner?: string;
// 缩列图
thumb?: string;
// 封面图宽
imageWidth?: string;
// 封面图高
imageHeight?: string;
// 样式
style?: string;
// Banner上的标题
title?: string;
// Banner上的描述
desc?: string;
// 列表显示方式(10小图展示 20大图展示)
showType?: number;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0已发布, 1待审核 2已驳回 3违规内容
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* 模型搜索条件
*/
export interface CmsModelParam extends PageParam {
modelId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsMp, CmsMpParam } from './model';
/**
* 分页查询小程序信息
*/
export async function pageCmsMp(params: CmsMpParam) {
const res = await request.get<ApiResult<PageResult<CmsMp>>>(
'/cms/cms-mp/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询小程序信息列表
*/
export async function listCmsMp(params?: CmsMpParam) {
const res = await request.get<ApiResult<CmsMp[]>>(
'/cms/cms-mp',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加小程序信息
*/
export async function addCmsMp(data: CmsMp) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-mp',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改小程序信息
*/
export async function updateCmsMp(data: CmsMp) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-mp',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除小程序信息
*/
export async function removeCmsMp(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除小程序信息
*/
export async function removeBatchCmsMp(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询小程序信息
*/
export async function getCmsMp(id: number) {
const res = await request.get<ApiResult<CmsMp>>(
'/cms/cms-mp/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,61 @@
import type { PageParam } from '@/api';
/**
* 小程序信息
*/
export interface CmsMp {
// ID
mpId?: number;
// 是否主账号
type?: number;
// 小程序ID
appId?: string;
// 小程序密钥
appSecret?: string;
// 小程序名称
mpName?: string;
// 小程序简称
shortName?: string;
// 头像
avatar?: string;
// 小程序码
mpQrcode?: string;
// 微信认证
authentication?: number;
// 主体信息
companyName?: string;
// 小程序备案
icpNo?: string;
// 登录邮箱
email?: string;
// 登录密码
password?: string;
// 原始ID
ghId?: string;
// 入口页面
mainPath?: string;
// 过期时间
expirationTime?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 介绍
comments?: string;
// 用户ID
userId?: number;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 小程序信息搜索条件
*/
export interface CmsMpParam extends PageParam {
mpId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsMpAd, CmsMpAdParam } from './model';
/**
* 分页查询小程序广告位
*/
export async function pageCmsMpAd(params: CmsMpAdParam) {
const res = await request.get<ApiResult<PageResult<CmsMpAd>>>(
'/cms/cms-mp-ad/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询小程序广告位列表
*/
export async function listCmsMpAd(params?: CmsMpAdParam) {
const res = await request.get<ApiResult<CmsMpAd[]>>(
'/cms/cms-mp-ad',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加小程序广告位
*/
export async function addCmsMpAd(data: CmsMpAd) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-mp-ad',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改小程序广告位
*/
export async function updateCmsMpAd(data: CmsMpAd) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-mp-ad',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除小程序广告位
*/
export async function removeCmsMpAd(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-ad/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除小程序广告位
*/
export async function removeBatchCmsMpAd(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-ad/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询小程序广告位
*/
export async function getCmsMpAd(id: number) {
const res = await request.get<ApiResult<CmsMpAd>>(
'/cms/cms-mp-ad/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,47 @@
import type { PageParam } from '@/api';
/**
* 小程序广告位
*/
export interface CmsMpAd {
// ID
adId?: number;
// 页面ID
pageId?: number;
// 广告类型
adType?: string;
// 广告位名称
name?: string;
// 宽
width?: string;
// 高
height?: string;
// 广告图片
images?: string;
// 路由/链接地址
path?: string;
// 页面名称
pageName?: string;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 小程序广告位搜索条件
*/
export interface CmsMpAdParam extends PageParam {
adId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsMpField, CmsMpFieldParam } from './model';
/**
* 分页查询小程序配置
*/
export async function pageCmsMpField(params: CmsMpFieldParam) {
const res = await request.get<ApiResult<PageResult<CmsMpField>>>(
'/cms/cms-mp-field/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询小程序配置列表
*/
export async function listCmsMpField(params?: CmsMpFieldParam) {
const res = await request.get<ApiResult<CmsMpField[]>>(
'/cms/cms-mp-field',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加小程序配置
*/
export async function addCmsMpField(data: CmsMpField) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-mp-field',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改小程序配置
*/
export async function updateCmsMpField(data: CmsMpField) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-mp-field',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除小程序配置
*/
export async function removeCmsMpField(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-field/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除小程序配置
*/
export async function removeBatchCmsMpField(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-field/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询小程序配置
*/
export async function getCmsMpField(id: number) {
const res = await request.get<ApiResult<CmsMpField>>(
'/cms/cms-mp-field/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,35 @@
import type { PageParam } from '@/api';
/**
* 小程序配置
*/
export interface CmsMpField {
// 自增ID
id?: number;
// 类型0文本 1图片 2其他
type?: number;
// 名称
name?: string;
// 备注
comments?: string;
// 名称
value?: string;
// 页面ID
pageId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 小程序配置搜索条件
*/
export interface CmsMpFieldParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsMpMenu, CmsMpMenuParam } from './model';
/**
* 分页查询小程序端菜单
*/
export async function pageCmsMpMenu(params: CmsMpMenuParam) {
const res = await request.get<ApiResult<PageResult<CmsMpMenu>>>(
'/cms/cms-mp-menu/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询小程序端菜单列表
*/
export async function listCmsMpMenu(params?: CmsMpMenuParam) {
const res = await request.get<ApiResult<CmsMpMenu[]>>(
'/cms/cms-mp-menu',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加小程序端菜单
*/
export async function addCmsMpMenu(data: CmsMpMenu) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-mp-menu',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改小程序端菜单
*/
export async function updateCmsMpMenu(data: CmsMpMenu) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-mp-menu',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除小程序端菜单
*/
export async function removeCmsMpMenu(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-menu/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除小程序端菜单
*/
export async function removeBatchCmsMpMenu(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-menu/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询小程序端菜单
*/
export async function getCmsMpMenu(id: number) {
const res = await request.get<ApiResult<CmsMpMenu>>(
'/cms/cms-mp-menu/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,79 @@
import type { PageParam } from '@/api';
/**
* 小程序端菜单
*/
export interface CmsMpMenu {
// ID
menuId?: number;
// 上级id, 0是顶级
parentId?: number;
// 菜单名称
title?: string;
// 类型 0功能图标 1订单状态图标 2首页导航图标 3 商城导航图标 4管理人员功能图标
type?: number;
// 是否微信小程序菜单
isMpWeixin?: string;
// 菜单路由地址
path?: string;
// 菜单组件地址, 目录可为空
component?: string;
// 打开位置
target?: string;
// 菜单图标
avatar?: string;
// 图标颜色
color?: string;
// 上传图标
icon?: string;
// 是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)
hide?: number;
// 位置 0不限 1顶部 2底部
position?: number;
// 0 第一行 1第二行
rows?: number;
// 菜单侧栏选中的path
active?: string;
// 其它路由元信息
meta?: string;
// 绑定的页面
pageId?: number;
// 绑定的文章分类ID
articleCategoryId?: number;
// 绑定的文章ID
articleId?: number;
// 绑定的表单ID
formId?: number;
// 绑定的书籍标识
bookCode?: string;
// 绑定的商品分类ID
goodsCategoryId?: number;
// 绑定的商品ID
goodsId?: number;
// 用户ID
userId?: number;
// 是否管理人员可见
adminShow?: number;
// 设为首页
home?: number;
// 分组名称
groupName?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0正常, 1冻结
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 小程序端菜单搜索条件
*/
export interface CmsMpMenuParam extends PageParam {
menuId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsMpPages, CmsMpPagesParam } from './model';
/**
* 分页查询小程序页面
*/
export async function pageCmsMpPages(params: CmsMpPagesParam) {
const res = await request.get<ApiResult<PageResult<CmsMpPages>>>(
'/cms/cms-mp-pages/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询小程序页面列表
*/
export async function listCmsMpPages(params?: CmsMpPagesParam) {
const res = await request.get<ApiResult<CmsMpPages[]>>(
'/cms/cms-mp-pages',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加小程序页面
*/
export async function addCmsMpPages(data: CmsMpPages) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-mp-pages',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改小程序页面
*/
export async function updateCmsMpPages(data: CmsMpPages) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-mp-pages',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除小程序页面
*/
export async function removeCmsMpPages(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-pages/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除小程序页面
*/
export async function removeBatchCmsMpPages(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-mp-pages/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询小程序页面
*/
export async function getCmsMpPages(id: number) {
const res = await request.get<ApiResult<CmsMpPages>>(
'/cms/cms-mp-pages/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,47 @@
import type { PageParam } from '@/api';
/**
* 小程序页面
*/
export interface CmsMpPages {
// ID
id?: number;
// 上级id, 0是顶级
parentId?: number;
// 页面名称
title?: string;
// 页面路径
path?: string;
// 设为首页
home?: number;
// 分包
subpackage?: string;
// 图标
icon?: string;
// 未选中图标
iconPath?: string;
// 选中的图标
selectedIconPath?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 用户ID
userId?: number;
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 小程序页面搜索条件
*/
export interface CmsMpPagesParam extends PageParam {
id?: number;
keywords?: string;
}

View File

@@ -0,0 +1,133 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsNavigation, CmsNavigationParam } from './model';
/**
* 分页查询网站导航记录表
*/
export async function pageCmsNavigation(params: CmsNavigationParam) {
const res = await request.get<ApiResult<PageResult<CmsNavigation>>>(
'/cms/cms-navigation/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询网站导航记录表列表
*/
export async function listCmsNavigation(params?: CmsNavigationParam) {
const res = await request.get<ApiResult<CmsNavigation[]>>(
'/cms/cms-navigation',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询导航列表(树形结构)
*/
export async function treeNavigation(params?: CmsNavigationParam) {
const res = await request.get<ApiResult<CmsNavigation[]>>(
'/cms/cms-navigation/tree',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加网站导航记录表
*/
export async function addCmsNavigation(data: CmsNavigation) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-navigation',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改网站导航记录表
*/
export async function updateCmsNavigation(data: CmsNavigation) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-navigation',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除网站导航记录表
*/
export async function removeCmsNavigation(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-navigation/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除网站导航记录表
*/
export async function removeBatchCmsNavigation(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-navigation/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询网站导航记录表
*/
export async function getCmsNavigation(id: number) {
const res = await request.get<ApiResult<CmsNavigation>>(
'/cms/cms-navigation/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
export async function getNavigationByPath(params: CmsNavigationParam) {
const res = await request.get<ApiResult<CmsNavigation>>(
'/cms/cms-navigation/getNavigationByPath',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,117 @@
import type {PageParam} from '@/api/index';
import type {CmsDesign} from "@/api/cms/cmsDesign/model";
import type {CmsModel} from "@/api/cms/cmsModel/model";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
/**
* 网站导航记录表
*/
export interface CmsNavigation {
// ID
navigationId?: number;
// 上级id, 0是顶级
parentId?: number;
// 菜单名称
title?: string;
// 模型
model?: string;
// 标识
code?: string;
// 菜单路由地址
path?: string;
// 菜单组件地址, 目录可为空
component?: string;
// 组件路径
componentPath?: string;
// 打开位置
target?: string;
// 菜单图标
icon?: string;
// banner图片
banner?: string;
// 图标颜色
color?: string;
// 是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)
hide?: number;
// 可见类型 0所有人 1登录可见 2密码可见
permission?: number;
// 访问密码
password?: string;
// 位置 0不限 1顶部 2底部
position?: number;
// 仅在顶部显示
top?: number;
// 仅在底部显示
bottom?: number;
// 菜单侧栏选中的path
active?: string;
// 其它路由元信息
meta?: string;
// css样式
style?: string;
// 父级栏目路由
parentPath?: string;
// 父级栏目名称
parentName?: string;
// 模型名称
modelName?: string;
// 类型(已废弃)
type?: number;
// 绑定的页面(已废弃)
pageId?: number;
// 项目ID
itemId?: number;
// 是否微信小程序菜单
isMpWeixin?: string;
// 用户ID
userId?: number;
// 设为首页
home?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 是否删除, 0否, 1是
deleted?: number;
// 状态, 0正常, 1冻结
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 父级栏目
parent?: CmsNavigation;
// 子级栏目
children?: CmsNavigation[];
// 模型信息
modelInfo?: CmsModel;
// 栏目名称
categoryName?: string;
// 是否禁用
disabled?: boolean;
// 链接地址
design?: CmsDesign;
// 子级数量
childHeight?: number,
// 是否展开
showChild?: boolean
// 布局
layout?: any;
// 标题
label?: string;
// 值
value?: number;
// 文章列表
articles?: CmsArticle[];
}
/**
* 网站导航记录表搜索条件
*/
export interface CmsNavigationParam extends PageParam {
navigationId?: number;
parentId?: number;
hide?: number;
model?: string;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsOrder, CmsOrderParam } from './model';
/**
* 分页查询订单
*/
export async function pageCmsOrder(params: CmsOrderParam) {
const res = await request.get<ApiResult<PageResult<CmsOrder>>>(
'/cms/cms-order/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询订单列表
*/
export async function listCmsOrder(params?: CmsOrderParam) {
const res = await request.get<ApiResult<CmsOrder[]>>(
'/cms/cms-order',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加订单
*/
export async function addCmsOrder(data: CmsOrder) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-order',
data
);
if (res.code === 0) {
return res;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改订单
*/
export async function updateCmsOrder(data: CmsOrder) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-order',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除订单
*/
export async function removeCmsOrder(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-order/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除订单
*/
export async function removeBatchCmsOrder(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-order/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询订单
*/
export async function getCmsOrder(id: number) {
const res = await request.get<ApiResult<CmsOrder>>(
'/cms/cms-order/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,69 @@
import type { PageParam } from '@/api/index';
/**
* 订单
*/
export interface CmsOrder {
// 订单号
orderId?: number;
// 关联模型
model?: string;
// 订单标题
title?: string;
// 订单编号
orderNo?: string;
// 订单类型0商城 1询价 2留言
type?: number;
// 关联文章ID
articleId?: number;
// 真实姓名
realName?: string;
// 手机号码
phone?: string;
// 电子邮箱
email?: string;
// 收货地址
address?: string;
// 订单内容
content?: string;
// 订单总额
totalPrice?: string;
// 实际付款
payPrice?: string;
// 报价询价
price?: string;
// 购买数量
totalNum?: number;
// 二维码地址,保存订单号,支付成功后才生成
qrcode?: string;
// 下单渠道0网站 1小程序 2其他
channel?: number;
// 过期时间
expirationTime?: string;
// 订单是否已结算(0未结算 1已结算)
isSettled?: number;
// 用户id
userId?: number;
// 备注
comments?: string;
// 排序号
sortNumber?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 图像验证码
code?: string;
// 图像验证码内容
text?: string;
}
/**
* 订单搜索条件
*/
export interface CmsOrderParam extends PageParam {
orderId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsSpec, CmsSpecParam } from './model';
/**
* 分页查询规格
*/
export async function pageCmsSpec(params: CmsSpecParam) {
const res = await request.get<ApiResult<PageResult<CmsSpec>>>(
'/cms/cms-spec/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询规格列表
*/
export async function listCmsSpec(params?: CmsSpecParam) {
const res = await request.get<ApiResult<CmsSpec[]>>(
'/cms/cms-spec',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加规格
*/
export async function addCmsSpec(data: CmsSpec) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-spec',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改规格
*/
export async function updateCmsSpec(data: CmsSpec) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-spec',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除规格
*/
export async function removeCmsSpec(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-spec/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除规格
*/
export async function removeBatchCmsSpec(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-spec/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询规格
*/
export async function getCmsSpec(id: number) {
const res = await request.get<ApiResult<CmsSpec>>(
'/cms/cms-spec/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,35 @@
import type { PageParam } from '@/api';
/**
* 规格
*/
export interface CmsSpec {
// 规格ID
specId?: number;
// 规格名称
specName?: string;
// 规格值
specValue?: string;
// 创建用户
userId?: number;
// 更新者
updater?: number;
// 备注
comments?: string;
// 状态, 0正常, 1待修,2异常已修3异常未修
status?: number;
// 排序号
sortNumber?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 规格搜索条件
*/
export interface CmsSpecParam extends PageParam {
specId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsSpecValue, CmsSpecValueParam } from './model';
/**
* 分页查询规格值
*/
export async function pageCmsSpecValue(params: CmsSpecValueParam) {
const res = await request.get<ApiResult<PageResult<CmsSpecValue>>>(
'/cms/cms-spec-value/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询规格值列表
*/
export async function listCmsSpecValue(params?: CmsSpecValueParam) {
const res = await request.get<ApiResult<CmsSpecValue[]>>(
'/cms/cms-spec-value',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加规格值
*/
export async function addCmsSpecValue(data: CmsSpecValue) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-spec-value',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改规格值
*/
export async function updateCmsSpecValue(data: CmsSpecValue) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-spec-value',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除规格值
*/
export async function removeCmsSpecValue(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-spec-value/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除规格值
*/
export async function removeBatchCmsSpecValue(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-spec-value/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询规格值
*/
export async function getCmsSpecValue(id: number) {
const res = await request.get<ApiResult<CmsSpecValue>>(
'/cms/cms-spec-value/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,29 @@
import type { PageParam } from '@/api';
/**
* 规格值
*/
export interface CmsSpecValue {
// 规格值ID
specValueId?: number;
// 规格组ID
specId?: number;
// 规格值
specValue?: string;
// 备注
comments?: string;
// 排序号
sortNumber?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 规格值搜索条件
*/
export interface CmsSpecValueParam extends PageParam {
specValueId?: number;
keywords?: string;
}

View File

@@ -0,0 +1,147 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { CmsWebsite, CmsWebsiteParam } from './model';
/**
* 分页查询网站信息记录表
*/
export async function pageCmsWebsite(params: CmsWebsiteParam) {
const res = await request.get<ApiResult<PageResult<CmsWebsite>>>(
'/cms/cms-website/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询网站
*/
export async function getCmsWebsiteAll(id: number) {
const res = await request.get<ApiResult<CmsWebsite>>(
'/cms/cms-website/getAll/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询网站信息记录表列表
*/
export async function listCmsWebsite(params?: CmsWebsiteParam) {
const res = await request.get<ApiResult<CmsWebsite[]>>(
'/cms/cms-website',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加网站信息记录表
*/
export async function addCmsWebsite(data: CmsWebsite) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-website',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改网站信息记录表
*/
export async function updateCmsWebsite(data: CmsWebsite) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-website',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除网站信息记录表
*/
export async function removeCmsWebsite(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-website/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除网站信息记录表
*/
export async function removeBatchCmsWebsite(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-website/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询网站信息记录表
*/
export async function getCmsWebsite(id: number) {
const res = await request.get<ApiResult<CmsWebsite>>(
'/cms/cms-website/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 清除缓存
*/
export async function removeSiteInfoCache(key?: string) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-website/clearSiteInfo/' + key
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 分页查询网站信息记录表
* @param params
*/
export async function pageCmsWebsiteAll(params: CmsWebsiteParam) {
const res = await request.get<ApiResult<PageResult<CmsWebsite>>>(
'/cms/cms-website/pageAll',
params
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,110 @@
import type { PageParam } from '@/api/index';
import type {CmsNavigation} from "@/api/cms/cmsNavigation/model";
/**
* 网站信息记录表
*/
export interface CmsWebsite {
// 站点ID
websiteId?: number;
// 网站名称
websiteName?: string;
// 网站标识
websiteCode?: string;
// 网站LOGO
websiteIcon?: string;
// 网站LOGO
websiteLogo?: string;
// 网站LOGO(深色模式)
websiteDarkLogo?: string;
// 网站类型
websiteType?: string;
// 网站关键词
keywords?: string;
// 域名前缀
prefix?: string;
// 绑定域名
domain?: string;
// 全局样式
style?: string;
// 后台管理地址
adminUrl?: string;
// 应用版本 10免费版 20专业版 30永久授权
version?: number;
// 服务到期时间
expirationTime?: string;
// 模版ID
templateId?: number;
// 行业类型(父级)
industryParent?: string;
// 行业类型(子级)
industryChild?: string;
// 企业ID
companyId?: number;
// 所在国家
country?: string;
// 所在省份
province?: string;
// 所在城市
city?: string;
// 所在辖区
region?: string;
// 经度
longitude?: string;
// 纬度
latitude?: string;
// 街道地址
address?: string;
// 联系电话
phone?: string;
// 电子邮箱
email?: string;
// ICP备案号
icpNo?: string;
// 公安备案
policeNo?: string;
// 备注
comments?: string;
// 是否推荐
recommend?: number;
// 运行状态
running?: number;
// 状态 0未开通 1运行中 2维护中 3已关闭 4已欠费停机 5违规关停
status?: number;
// 维护说明
statusText?: string;
// 关闭说明
statusClose?: string;
// 状态图标
statusIcon?: string;
// 全局样式
styles?: string;
// 排序号
sortNumber?: number;
// 用户ID
userId?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
// 网站配置
config?: any;
topNavs?: CmsNavigation[];
bottomNavs?: CmsNavigation[];
loginUser?: any;
search?: boolean;
}
/**
* 网站信息记录表搜索条件
*/
export interface CmsWebsiteParam extends PageParam {
websiteId?: number;
status?: number;
phone?: string;
keywords?: string;
}

View File

@@ -0,0 +1,129 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type {CmsWebsiteField, CmsWebsiteFieldParam, Config} from './model';
/**
* 分页查询应用参数
*/
export async function pageCmsWebsiteField(params: CmsWebsiteFieldParam) {
const res = await request.get<ApiResult<PageResult<CmsWebsiteField>>>(
'/cms/cms-website-field/page',
params
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询应用参数列表
*/
export async function listCmsWebsiteField(params?: CmsWebsiteFieldParam) {
const res = await request.get<ApiResult<CmsWebsiteField[]>>(
'/cms/cms-website-field',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加应用参数
*/
export async function addCmsWebsiteField(data: CmsWebsiteField) {
const res = await request.post<ApiResult<unknown>>(
'/cms/cms-website-field',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改应用参数
*/
export async function updateCmsWebsiteField(data: CmsWebsiteField) {
const res = await request.put<ApiResult<unknown>>(
'/cms/cms-website-field',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除应用参数
*/
export async function removeCmsWebsiteField(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-website-field/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除应用参数
*/
export async function removeBatchCmsWebsiteField(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/cms/cms-website-field/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 根据id查询应用参数
*/
export async function getCmsWebsiteField(id: number) {
const res = await request.get<ApiResult<CmsWebsiteField>>(
'/cms/cms-website-field/' + id
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 恢复项目参数
*/
export async function undeleteWebsiteField(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/cms/website-field/undelete/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询项目参数列表
*/
export async function configWebsiteField(params?: CmsWebsiteFieldParam) {
const res = await request.get<ApiResult<Config>>(
'/cms/cms-website-field/config',
params
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}

View File

@@ -0,0 +1,57 @@
import type { PageParam } from '@/api/index';
/**
* 应用参数
*/
export interface CmsWebsiteField {
// 自增ID
id?: number;
// 类型0文本 1图片 2其他
type?: number;
// 名称
name?: string;
// 默认值
defaultValue?: string;
// 可修改的值 [on|off]
modifyRange?: string;
// 备注
comments?: string;
// css样式
style?: string;
// 名称
value?: string;
// 排序(数字越小越靠前)
sortNumber?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 应用参数搜索条件
*/
export interface CmsWebsiteFieldParam extends PageParam {
id?: number;
name?: string;
keywords?: string;
}
export interface Config {
siteName?: string;
siteLogo?: string;
domain?: string;
icpNo?: string;
copyright?: string;
loginBgImg?: string;
address?: string;
tel?: string;
workDay?: string;
kefu2?: string;
kefu1?: string;
email?: string;
loginTitle?: string;
sysLogo?: string;
}

View File

@@ -0,0 +1,113 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api/index';
import type { Link, LinkParam } from './model';
/**
* 分页查询链接
*/
export async function pageLink(params: LinkParam) {
const res = await request.get<ApiResult<PageResult<Link>>>(
'/oa/link/page',
{
params
}
);
if (res.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 查询链接列表
*/
export async function listLink(params?: LinkParam) {
const res = await request.get<ApiResult<Link[]>>(
'/oa/link',
{
params
}
);
if (res.code === 0 && res.data) {
return res.data;
}
return Promise.reject(new Error(res.message));
}
/**
* 添加链接
*/
export async function addLink(data: Link) {
const res = await request.post<ApiResult<unknown>>(
'/oa/link',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 修改链接
*/
export async function updateLink(data: Link) {
const res = await request.put<ApiResult<unknown>>(
'/oa/link',
data
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 删除链接
*/
export async function removeLink(id?: number) {
const res = await request.del<ApiResult<unknown>>(
'/oa/link/' + id
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 批量删除链接
*/
export async function removeBatchLink(data: (number | undefined)[]) {
const res = await request.del<ApiResult<unknown>>(
'/oa/link/batch',
{
data
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}
/**
* 检查IP是否存在
*/
export async function checkExistence(
field: string,
value: string,
id?: number
) {
const res = await request.get<ApiResult<unknown>>(
'/oa/link/existence',
{
params: { field, value, id }
}
);
if (res.code === 0) {
return res.message;
}
return Promise.reject(new Error(res.message));
}

Some files were not shown because too many files have changed in this diff Show More