# cool-admin-class
**Repository Path**: CRESCENT007/cool-admin-class
## Basic Information
- **Project Name**: cool-admin-class
- **Description**: 学习使用
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: 8
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-27
- **Last Updated**: 2026-01-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Cool Admin 插件开发指南
注意如果拉取https://gitee.com/CRESCENT007/cool-admin-class.git后子模块目录下没有代码的话,则先在根目录下执行git submodule update --init --recursive进行子模块的初始化和更新
## 1. 数据库配置
修改后端数据库配置 `server\src\config\config.local.ts`,更改为自建数据库相关配置(需要先建好一个数据库):
```typescript
type: 'mysql',
host: '127.0.0.1',
port: 3306,
username: 'root',
password: '123456',
database: 'cool',
```
**注意:** 如果使用的是 PostgreSQL 的话,需要在 server 的终端下执行 `pnpm install pg --save` 来安装数据库相关依赖。MySQL、SQLite 则不用。
## 2. 后端服务启动
### 安装依赖并启动服务
```bash
pnpm i # 安装依赖
pnpm dev # 启动后端
```
### 自动建表配置
在 `server\src\config\config.local.ts` 中有一个配置项:
```typescript
// 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失
synchronize: true,
```
当该项为 `true` 时,首次执行 `pnpm dev` 会自动初始化数据库,将架构的初始数据库表和数据添加到你的数据库中。建议开发状态下,首次执行 `pnpm dev` 时将该配置打开,后续根据需要选择是否打开。
## 3. 前端服务启动
### 安装依赖并启动服务
```bash
pnpm i # 安装依赖
pnpm dev # 启动前端
```
**注意:** 后端必须在前端之前启动,否则无法运行。
## 4. 前端插件开发
前端插件应放置于 `client\src\plugins` 下。
### 目录结构
```
plugin-name/
├── components/ # 全局组件(可选)
│ └── component-name.vue
├── directives/ # 全局指令(可选)
│ └── directive-name.ts
├── locales/ # 国际化文件(可选)
│ ├── zh-cn.json
│ ├── zh-tw.json
│ └── en.json
├── hooks/ # 常用函数/Hooks(可选)
│ └── index.ts
├── utils/ # 工具函数(可选)
│ └── index.ts
├── static/ # 静态资源(可选)
│ ├── css/
│ ├── svg/
│ └── images/
├── demo/ # 示例页面(可选)
│ └── base.vue
├── types/ # TypeScript 类型定义(可选)
│ └── index.d.ts
├── config.ts # 配置文件(必需)
└── index.ts # 入口文件(必需)
```
### 必需文件
#### 1. config.ts
插件配置文件,必须导出 `ModuleConfig` 类型的配置对象。
**基本结构:**
```typescript
import { type ModuleConfig } from '/@/cool';
export default (): ModuleConfig => {
return {
// 是否启用插件
enable: true,
// 插件加载顺序,值越大越先加载
order: 0,
// 插件名称
label: '插件名称',
// 插件描述
description: '插件功能描述',
// 作者
author: 'COOL',
// 版本号
version: '1.0.0',
// 更新时间
updateTime: '2024-01-01',
// Logo 地址(可选)
logo: '',
// 文档地址(可选)
doc: 'https://example.com/docs',
// 示例页面路径(可选)
demo: '/demo/plugin-name',
// 配置参数
options: {
// 自定义配置项
},
// 全局组件注册
components: [],
// 视图路由
views: [],
// 页面路由
pages: [],
// 顶部工具栏组件(可选)
toolbar: {
order: 1,
pc: true, // PC 端是否显示
h5: false, // H5 端是否显示
component: import('./components/toolbar.vue')
},
// 注入全局组件(可选)
index: {
component: import('./components/index.vue')
},
// 安装时触发
install(app, options) {
// 插件初始化逻辑
},
// 加载时触发
async onLoad(events) {
// 异步加载逻辑
// 可以返回供其他模块使用的方法
return {
customMethod() {
// 自定义方法
}
};
},
// 忽略配置(可选)
ignore: {
// 忽略进度条的请求
NProgress: ['/api/path1', '/api/path2'],
// 忽略 token 的路由
token: ['/public/path1', '/public/path2']
}
};
};
```
**配置项说明:**
| 配置项 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `enable` | `boolean` | 否 | 是否启用插件,默认 `true` |
| `order` | `number` | 否 | 加载顺序,值越大越先加载,默认 `0` |
| `label` | `string` | 是 | 插件显示名称 |
| `description` | `string` | 是 | 插件功能描述 |
| `author` | `string` | 是 | 作者信息 |
| `version` | `string` | 是 | 版本号 |
| `updateTime` | `string` | 是 | 更新时间 |
| `logo` | `string` | 否 | Logo 图片地址 |
| `doc` | `string` | 否 | 文档地址 |
| `demo` | `string \| Array` | 否 | 示例页面路径或示例列表 |
| `options` | `object` | 否 | 插件配置参数 |
| `components` | `Array` | 否 | 全局组件列表 |
| `views` | `Array` | 否 | 视图路由配置 |
| `pages` | `Array` | 否 | 页面路由配置 |
| `toolbar` | `object` | 否 | 顶部工具栏配置 |
| `index` | `object` | 否 | 全局注入组件配置 |
| `install` | `function` | 否 | 安装时执行的函数 |
| `onLoad` | `function` | 否 | 加载时执行的异步函数 |
| `ignore` | `object` | 否 | 忽略配置 |
#### 2. index.ts
插件入口文件,导出插件需要对外暴露的变量和方法。
```typescript
// 导出工具函数
export * from './utils';
// 导出 Hooks
export * from './hooks';
// 导出类型定义
export * from './types';
// 导出自定义方法
export function usePluginName() {
return {
// 自定义方法或变量
customMethod() {
// 实现逻辑
}
};
}
```
其他目录根据需要进行创建开发。
在 `client\src\plugins\demoplugin` 中有一套示例代码以供学习使用。
### 如何使用前端插件
通常是在模块中去调用插件导出的功能或者组件。
**示例:**
在示例 `client\src\plugins\demoplugin\index.ts` 中有如下一段代码:
```typescript
/**
* 插件信息
*/
export const demoInfo = {
name: 'demo',
label: '前端插件测试',
version: '1.0.0',
author: '作者',
description: '插件描述'
};
```
这里导出了一个常量对象,包含该插件的信息,供其他模块导入使用(同理,其他由插件在 `index.ts` 中导出的变量、常量、功能函数、组件等都能被其他模块导入使用)。
现在想在测试视图 `client\src\modules\demo\views\plugintest.vue` 中导入使用这个插件提供的此常量,则过程如下:
**Step 1:在插件中导出常量 `demoInfo`**
```typescript
export const demoInfo = {
name: 'demo',
label: '前端插件测试',
version: '1.0.0',
author: '作者',
description: '插件描述'
};
```
**Step 2:在前端(需要使用该插件导出的所需功能的地方)导入该常量**
在 Vue 组件的 `
```
##### 2. 组件自动注册(插件配置)
在 `config.ts` 中通过 `import.meta.glob` 扫描 `components` 目录下的所有组件文件,自动收集到 `components` 数组。
```typescript
// 组件全注册
components: Object.values(import.meta.glob('./components/**/*.{vue,tsx}')),
```
##### 3. 模块系统注册(应用启动)
应用启动时,模块系统会:
- 遍历所有模块的 `components` 数组
- 动态加载组件模块
- 使用 `app.component()` 全局注册组件
```typescript
// 注册组件
e.components?.forEach(async (c: any) => {
const v = await (isFunction(c) ? c() : c);
const n = v.default || v;
if (n.name) {
app.component(n.name, n);
}
});
```
##### 4. 组件使用(在表单中)
**方式一:在 `cl-form` 中使用**
```typescript
Form.value?.open({
title: '选择成员',
items: [
{
label: '单选',
prop: 'userId',
component: {
name: 'cl-user-select',
props: {
multiple: false,
onChange(val) {
console.log(val);
}
}
},
required: true
},
{
label: '多选',
prop: 'userIds',
component: {
name: 'cl-user-select',
props: {
multiple: true,
onChange(val) {
console.log(val);
}
}
},
required: true
},
{
label: '回显',
prop: 'testId',
component: {
name: 'cl-user-select',
props: {
// 【很重要】立即刷新
immediate: true
}
}
}
],
form: {
// 【很重要】手动设置值,实际根据接口返回
testId: 2
}
});
```
**方式二:直接在模板中使用**
```vue
```
##### 5. 组件功能特性
组件支持的功能:
- 单选/多选:通过 `multiple` 属性控制
- 按部门/角色分组:通过标签页切换
- 搜索过滤:支持关键字搜索
- 数据回显:通过 `v-model` 绑定值,支持 `immediate` 立即加载
- 表单验证:集成 CRUD 表单验证系统
##### 6. 完整流程图
```
┌─────────────────────────────────────┐
│ 1. 组件定义 │
│ select.vue (cl-user-select) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 2. 插件配置 │
│ config.ts │
│ components: glob('./components/**')│
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 3. 模块系统加载 │
│ module.ts │
│ app.component(name, component) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 4. 全局可用 │
│ 可在任何 Vue 组件中使用 │
│ │
└─────────────────────────────────────┘
```
##### 7. 关键点总结
1. **自动注册:** 通过 `import.meta.glob` 自动扫描组件,无需手动导入
2. **全局可用:** 注册后可在任何组件中直接使用,无需导入
3. **配置灵活:** 支持通过 `component.name` 和 `component.props` 配置
4. **表单集成:** 与 CRUD 表单系统深度集成,支持验证和回显
5. **数据绑定:** 支持 `v-model` 双向绑定和 `@change` 事件
这就是 `cl-user-select` 组件从定义到使用的完整流程。
## 5. 后端插件开发
### Step 1:拉取官方提供的后端插件开发脚手架
这里已经作为子模块添加在了 `/plugin` 目录中。
**Git 地址:**
```bash
# GitHub
git clone https://github.com/cool-team-official/cool-admin-midway-plugin.git
# Gitee(如果你的网络不好,可以使用)
git clone https://gitee.com/cool-team-official/cool-admin-midway-plugin.git
```
### Step 2:认识脚手架的目录结构
```
├── .vscode # VSCode 的一些配置
├── assets # 资源文件,如图片等
├── dist # 运行编译后的时候自动生成
├── release # 打包发布的时候自动生成
├── src
│ ├── index.ts # 入口文件,所有插件的功能统一集中到这个文件,不允许重命名
│ └── other.ts # 其他文件,可自定义,不是必须的
├── test
│ └── index.ts # 开发时的测试文件
├── .gitattributes # Git 的一些配置
├── .gitignore # Git 忽略文件
├── LICENSE # 开源协议
├── package.json # 依赖管理,项目信息
├── plugin.json # 插件的配置信息
├── README.md # 插件的介绍,会展示在插件的详情中
└── tsconfig.json # TypeScript 的配置文件
```
### Step 3:插件功能开发
#### 安装依赖
脚手架中提供了一些依赖,执行 `pnpm i` 进行安装,也可以自己再在 `plugin\package.json` 中进行增删,但不建议脚手架中有过多的依赖。
#### 开发示例
这里以一个简单的控制台输出语句功能为例:
**1. 创建功能文件**
在 `plugin\src\other.ts`(允许重命名)中写一个简单的功能如下:
```typescript
export function other() {
console.log('这是另外一个文件');
}
```
**2. 在入口文件中导入**
在 `plugin\src\index.ts` 中导入 `other.ts` 提供的该功能函数:
```typescript
import * as other from "./other";
```
**3. 在方法中调用**
在 `show()` 中调用(当然可以在其他地方使用,也可以删除 `show()` 函数,`index.ts` 中的功能函数非固定):
```typescript
/**
* 展示插件信息
* @param a 参数a
* @param b 参数b
* @returns 插件信息
*/
async show(a, b) {
console.log("传参", a, b);
other.other();
return this.pluginInfo;
}
```
### Step 4:测试功能是否可用
在 `plugin\test\index.ts` 中实例化插件,调用你要测试的功能,这里我想调用 `show()` 函数验证 `plugin\src\index.ts` 和 `plugin\src\other.ts` 中的功能可用性,则代码如下:
```typescript
(async () => {
// 调用插件方法
const res = await instance.show(1, 2);
console.log(res);
})();
```
然后在 plugin 的终端执行 `pnpm test`,如果功能正常,则会输出你想要的结果,这里应该输出三句话和插件信息:
```
插件就绪
传参 1 2
这是另外一个文件
{
name: '测试',
key: 'test',
hook: '',
singleton: false,
version: '1.0.0',
description: '插件描述',
author: '作者',
logo: 'assets/logo.png',
readme: 'README.md',
config: {
appId: 'E:/workspace/cool-admin-class/cool-admin-class/plugin/1.md',
appSecret: 'xxxxx',
filePath: 'E:/workspace/cool-admin-class/cool-admin-class/plugin/xxxxx'
}
}
```
### Step 5:插件打包
在 `plugin\package.json` 中提供了三个命令:
- `test`:测试
- `build`:编译
- `release`:打包
在 plugin 的终端中执行 `pnpm release` 进行打包,会生成一个 `release` 目录,其中会生成一个以 `.cool` 为后缀的文件,这就是插件包。
**打包说明:**
- 只打包 `plugin\src` 目录下的代码
- 以 `plugin\src\index.ts` 作为入口点
- 包含所有被 `plugin\src\index.ts` 导入的模块
- `plugin\test` 目录不会被打包
### Step 6:使用插件包
#### 安装插件
在前端的扩展管理-插件列表中进行选择安装,然后根据插件的文档进行插件的安装。
#### 后端调用
这是后端插件,故而通常在后端使用,这里的示例插件包提供了一个 `show()` 方法,调用示例如下:
```typescript
@Inject()
pluginService: PluginService;
// 获取插件实例
const instance = await this.pluginService.getInstance('test');
// 调用show
await instance.show(1, 2);
```
#### 前端调用
如果想从前端进行调用,则需要在后端为前端提供接口来使用。
**后端接口示例:**
在 `server\src\modules\demo\controller\open\plugintest.ts` 中写了一个调用示例。
**前端调用示例:**
在示例文件 `client\src\modules\demo\views\plugintest.vue` 中,相关代码如下:
**控件:**
```vue
调用测试接口
```
**调用处理:**
```typescript
async function handleTest() {
loading.value = true;
result.value = '';
try {
const data = await service.request({
url: '/open/demo/plugintest/test',
method: 'GET'
});
result.value = JSON.stringify(data, null, 2);
ElMessage.success('调用成功');
console.log('接口返回数据:', data);
} catch (error: any) {
const errorMsg = error.message || error.code || '调用失败';
ElMessage.error(errorMsg);
result.value = `错误: ${errorMsg}`;
console.error('调用接口失败:', error);
} finally {
loading.value = false;
}
}
```
**预期输出:**
点击前端页面显示的调用按钮后即会调用该插件的 `show()` 方法,正确结果应该是在 server 的终端输出:
```
插件就绪
传参 1 2
这是另外一个文件
{
name: '测试',
key: 'test',
hook: '',
singleton: false,
version: '1.0.0',
description: '插件描述',
author: '作者',
logo: 'assets/logo.png',
readme: 'README.md',
config: {
appId: 'E:/workspace/cool-admin-class/cool-admin-class/plugin/1.md',
appSecret: 'xxxxx',
filePath: 'E:/workspace/cool-admin-class/cool-admin-class/plugin/xxxxx'
}
}
```
### 总结
所有的插件开发与使用的流程基本如上,基于脚手架进行自定义功能开发,然后打包成 cool 包,再安装后使用。
## 6. 模块开发
## 添加前后端模块的步骤
### 一、后端模块(cool-admin-midway)
#### 1. 创建模块目录结构
在 `cool-admin-midway/src/modules/` 下创建模块目录,例如 `my-module/`:
```
my-module/
├── config.ts # 模块配置文件(必需)
├── entity/ # 实体类目录
│ └── info.ts # 实体类
├── service/ # 服务类目录
│ └── info.ts # 服务类
├── controller/ # 控制器目录
│ └── admin/ # 后台管理接口
│ └── info.ts # 控制器
└── db.json # 数据库初始化数据(可选)
```
#### 2. 创建模块配置文件 `config.ts`
```typescript
import { ModuleConfig } from '@cool-midway/core';
export default () => {
return {
name: '我的模块',
description: '模块描述',
middlewares: [], // 模块级中间件
globalMiddlewares: [], // 全局中间件
order: 0, // 加载顺序,值越大越优先
} as ModuleConfig;
};
```
#### 3. 创建实体类 `entity/info.ts`
```typescript
import { BaseEntity } from '../../base/entity/base';
import { Column, Entity } from 'typeorm';
@Entity('my_module_info')
export class MyModuleInfoEntity extends BaseEntity {
@Column({ comment: '名称' })
name: string;
@Column({ comment: '描述', nullable: true })
description: string;
}
```
#### 4. 创建服务类 `service/info.ts`
```typescript
import { Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { MyModuleInfoEntity } from '../entity/info';
@Provide()
export class MyModuleInfoService extends BaseService {
@InjectEntityModel(MyModuleInfoEntity)
myModuleInfoEntity: Repository;
// 可以在这里添加自定义业务逻辑方法
}
```
#### 5. 创建控制器 `controller/admin/info.ts`
```typescript
import { Provide } from '@midwayjs/core';
import { CoolController, BaseController } from '@cool-midway/core';
import { MyModuleInfoEntity } from '../../entity/info';
import { MyModuleInfoService } from '../../service/info';
@Provide()
@CoolController({
api: ['add', 'delete', 'update', 'info', 'list', 'page'], // 自动生成CRUD接口
entity: MyModuleInfoEntity,
service: MyModuleInfoService,
listQueryOp: {
keyWordLikeFields: ['name'], // 关键字搜索字段
},
})
export class AdminMyModuleInfoController extends BaseController {
// 可以在这里添加自定义接口
}
```
#### 6. 数据库初始化(可选)
创建 `db.json` 文件,用于初始化菜单等数据:
```json
{
"menus": [
{
"name": "我的模块",
"router": "/my-module/list",
"perms": ["my-module:info:page", "my-module:info:list"],
"type": 1,
"icon": "icon-list",
"orderNum": 100,
"viewPath": "my-module/views/list"
}
]
}
```
---
### 二、前端模块(cool-admin-vue)
#### 1. 创建模块目录结构
在 `cool-admin-vue/src/modules/` 下创建模块目录,例如 `my-module/`:
```
my-module/
├── config.ts # 模块配置文件(必需)
├── views/ # 页面视图目录
│ └── list.vue # 列表页面
├── components/ # 组件目录(可选)
├── store/ # 状态管理(可选)
├── locales/ # 国际化文件(可选)
│ ├── zh-cn.json
│ ├── zh-tw.json
│ └── en.json
└── index.ts # 模块导出(可选)
```
#### 2. 创建模块配置文件 `config.ts`
```typescript
import { type ModuleConfig } from '/@/cool';
export default (): ModuleConfig => {
return {
// 忽略 NProgress 的路径
ignore: {
NProgress: ['/my-module/info/add']
},
// 注册组件
components: [
() => import('./components/my-component.vue')
],
// 注册路由视图
views: [
{
meta: {
label: '我的模块'
},
path: '/my-module/list',
component: () => import('./views/list.vue')
}
],
// 模块加载时的回调
onLoad({ hasToken }) {
// 可以在这里做一些初始化操作
}
};
};
```
#### 3. 创建列表页面 `views/list.vue`
```vue
```
#### 4. 国际化文件(可选)
创建 `locales/zh-cn.json`:
```json
{
"我的模块": "我的模块",
"搜索名称": "搜索名称",
"名称": "名称",
"描述": "描述"
}
```
---
### 三、关键说明
1. 后端控制器自动注册:
- 使用 `@CoolController` 装饰器的控制器会被自动扫描和注册
- 通过 `api` 参数可自动生成 CRUD 接口(add, delete, update, info, list, page)
2. 前端服务自动生成:
- 前端服务通过访问后端的 `/app/eps` 接口自动生成
- 服务路径格式:`service.模块名.控制器名`
- 例如:`service.myModule.info` 对应后端的 `AdminMyModuleInfoController`
3. 路由自动注册:
- 前端在 `config.ts` 中定义的 `views` 会自动注册到路由
- 路径需要与后端菜单配置的 `router` 字段对应
4. 模块加载顺序:
- 通过 `order` 字段控制,值越大越优先加载
- 默认值为 0
5. 权限控制:
- 后端控制器会自动生成权限标识,格式:`模块名:控制器名:操作`
- 例如:`my-module:info:add`、`my-module:info:delete`
---
### 四、参考示例
可以参考现有模块:
- 简单模块:`dict`(字典管理)
- 复杂模块:`user`(用户管理)
- 带组件的模块:`space`(文件空间)
按照以上步骤创建文件后,模块会自动被系统识别和加载。