@aklry/koana
v1.0.16
Published
一个全栈中后台框架,使用vue+typescript+koa+webpack+express实现
Maintainers
Readme
@aklry/koana
一个全栈中后台框架,使用 Vue + TypeScript + Koa + Webpack + Express 实现。
📦 包结构
Koana 是一个 monorepo 项目,包含以下子包:
@aklry/koana-core- 核心服务端框架@aklry/koana-engineering- 前端工程化构建工具@aklry/koana-shared- 共享工具库@aklry/koana-types- TypeScript 类型定义
🚀 快速开始
安装
npm install @aklry/koana
# 或
pnpm install @aklry/koana
# 或
yarn add @aklry/koana基本使用
import koana from '@aklry/koana';
// 启动服务器
const app = await koana.serverStart({
homePage: '/',
// 其他配置...
});
// 前端构建
koana.frontedBuild('prod'); // 或 'dev'
// 使用基类
class UserController extends koana.BaseController {
// 控制器逻辑
}
class UserService extends koana.BaseService {
// 服务逻辑
}主要技术栈
- Vue
- Koa
- Express
- TypeScript
- mocha
- Webpack
- Element Plus
开发文档(模板配置)
export default {
// 模板类型,不同模板类型对应不一样的模板数据结构
mode: 'dashboard',
name: '', // 名称
desc: '', // 描述
icon: '', // 图标
homePage: '', //首页(项目配置)
// 头部菜单
menu: [
{
key: '', // 菜单唯一描述
name: '', // 菜单名称
menuType: '', // 枚举值, group / module
// 当menuType = group 时, 可填
subMenu: [
{
// 可以递归menuItem
},
],
// 当menuType = module 时, 可填
moduleType: '', // 枚举值 schema/custom/iframe/sider
// 当moduleType = schema 时, 可填
schemaConfig: {
api: '', // 数据源api 遵循RESTful规范
// 板块数据结构
schema: {
type: 'object',
properties: {
key: {
...schema, // 标准schema 配置
type: '', // 字段类型
label: '', // 字段中文名
// 字段在table中的相关配置
tableOption: {
...elTableColumnConfig, //标准el-table-column 配置
visible: true, // 默认为true(false 表示不在表单显示)
toFixed: 2, // 保留小数点后几位
},
// 字段在search-bar中的相关配置
searchOption: {
...elComponentConfig, //标准el-component(form 表单组件) 配置
comType: '', // 配置控件类型(input/select)
default: '', // 默认值
// 当comType = select 时, 可填
enumList: [],
// 当comType = dynamicSelect 时, 可填
api: '', // 枚举列表数据源api 遵循RESTful规范
},
// 字段在不同 component 中的相关配置, 前缀对应componentConfig的键
// 例如: componentConfig.createForm = createFormOption
// 字段在createForm中的相关配置
createFormOption: {
...eleFormConfig, // 标准element-ui form配置
comType: '', // 配置控件类型(input/select)
visible: true, // 是否展示(true/false),默认为true
disabled: false, // 是否禁用(true/false),默认为false
default: '', // 默认值
// 当comType = select 时, 可填
enumList: [], // 枚举列表
},
// 字段在editForm中的相关配置
editFormOption: {
...eleFormConfig, // 标准element-ui form配置
comType: '', // 配置控件类型(input/select)
visible: true, // 是否展示(true/false),默认为true
disabled: false, // 是否禁用(true/false),默认为false
default: '', // 默认值
// 当comType = select 时, 可填
enumList: [], // 枚举列表
},
detailPanelOption: {
...eleFormConfig, // 标准element-ui form配置
disabled: true, // 是否禁用(true/false),默认为true
},
},
},
required: [], // 标记哪些字段是必填的
},
// table相关配置
tableConfig: {
headerButtons: [
{
label: '', // 按钮中文名
eventKey: '', // 按钮事件名
// 按钮具体配置
eventOption: {
// 当eventKey === 'showComponent' 时
comName: '', // 组件名称
},
...elButtonConfig, // 标准el-button配置
},
],
rowButtons: [
{
label: '', // 按钮中文名
eventKey: '', // 按钮事件名
eventOption: {
// 当eventKey = remove 时, 可填
params: {
// paramKey = 参数的键值
// rowValueKey = 参数值 ,格式为 schema::xxx时,到table中找响应的字段
paramKey: rowValueKey,
},
// 当eventKey === 'showComponent' 时
comName: '', // 组件名称
}, // 按钮事件具体配置
...elButtonConfig, // 标准el-button配置
},
],
},
searchConfig: {}, // search-bar相关配置
// 动态组件 相关配置
componentConfig: {
// create-form 相关配置
createForm: {
title: '', // 表单标题
saveBtnText: '', // 保存按钮文本
},
// edit-form 相关配置
editForm: {
mainKey: '', // 主键,用于唯一标识要修改的数据对象
title: '', // 表单标题
saveBtnText: '', // 保存按钮文本
},
// detail-panel 相关配置
detailPanel: {
mainKey: '', // 主键,用于唯一标识要修改的数据对象
title: '',
},
// 支持用户动态扩展
},
},
// 当moduleType = custom 时, 可填
customConfig: {
path: '', // 自定义路径
},
// 当moduleType = iframe 时, 可填
iframeConfig: {
path: '', // iframe路径
},
// 当moduleType = sider 时, 可填
siderConfig: {
menu: [
{
// 可递归 menuItem(除moduleType = sider)
},
],
},
},
],
};sdk的使用
安装
npm i @aklry/elpis服务端启动
import main from '@aklry/koana';
main.serverStart({
// 项目名称
name: 'demo',
});自定义服务端
在server/目录下创建对应的目录
router-schema
表示接口的jsonschema规范
import type { KoanaMainTypes } from '@aklry/koana/types'; const routerSchema:KoanaMainTypes.RouterSchema { '/api/proj/list': { get: { query: { type: 'object', properties: { page: { type: 'string' }, size: { type: 'string' } }, required: ['page', 'size'] } } } } export default routerSchema
router
controller
service
遵循MVC规范,接口遵循restful规范
前端构建
项目启动
import main from '@aklry/koana';
main.frontendBuild(process.env.NODE_ENV);注:
process.env.NODE_ENV表示环境变量,可取dev或prod,在执行node脚本时附带上
自定义webpack配置
- 在
client/webpack.config.js文件编写额外的配置
自定义页面扩展
在
client/pages/**目录下写入口entry.xxx.js在
client/pages/dashboard/**目录下自定义页面在
client/pages/dashboard/complex-view/components目录下写扩展组件- 配置到
app/pages/dashboard/complex-view/components/component-config.js
- 配置到
在
client/pages/widgets/schema-form/complex-view目录下写schema-form的扩展组件- 配置到
client/pages/widgets/schema-form/form-item-config.js
在
client/pages/widgets/schema-search-bar/complex-view目录下写schema-search-bar的扩展组件- 配置到
client/pages/widgets/schema-search-bar/schema-item-config.js
TypeScript类型
import type Koa from 'koa'; import type { Context } from 'koa'; import type KoaRouter from 'koa-router'; import type log4js from 'log4js'; import type { DtoDSLModelTypes, HeaderMenu } from './extend'; /** * 启动参数 */ export interface Options { name: string; homePage?: string; } /** * 环境变量 */ export interface Env { isLocal: () => boolean; isProd: () => boolean; isBeta: () => boolean; get: () => string; } interface Property { [key: string]: { type: string; description?: string; }; } type Required = Array<keyof Property>; interface ObjectSchema { type: 'object'; properties: Property; required?: Required; $schema?: string; } interface RequestSchema { query?: ObjectSchema; params?: ObjectSchema; headers?: ObjectSchema; body?: ObjectSchema; } /** * router-schema对象的值类型 */ interface RouterSchemaValue { get?: RequestSchema; post?: RequestSchema; put?: RequestSchema; delete?: RequestSchema; patch?: RequestSchema; options?: RequestSchema; head?: RequestSchema; } export type RouterSchemaKeys = keyof RouterSchemaValue; /** * RouterSchema的值类型 * @description 用于描述router-schema的数据结构 */ export interface RouterSchema { [key: string]: RouterSchemaValue; } /** * koa拓展实例对象 */ export interface App extends Koa<Koa.DefaultState, Koa.DefaultContext> { options: Options; baseDir: string; businessDir: string; clientDir: string; koanaDir: string; businessClientDir: string; env: Env; config: Record<string, any>; service: Record<string, any>; middlewares: Record<string, any>; routerSchema: RouterSchema; controller: Record<string, any>; logger: log4js.Logger & Console; [key: string]: any; } /** * 路由实例 */ export interface Router extends KoaRouter {} /** * 中间件上下文类型 */ export interface MiddlewareContext extends Context { request: Context['request'] & { body: any; headers: { s_sign: string; s_t: number; }; }; params: { page: string; [key: string]: string; }; } /** * 中间件的next函数类型 */ export interface Next extends Koa.Next {} type Global = Window & typeof globalThis; /** * 全局类型扩展 * @description 用于在全局范围内添加额外的属性 */ export interface GlobalType extends Global { projKey?: string; } /** * ctx.headers的类型 */ export interface DtoHeaders { s_t: number; s_sign: string; proj_key?: string; [key: string]: any; } /** * DSL模板类型 */ export interface DSLTypes { // 模板类型,不同模板类型对应不一样的模板数据 mode?: string; // 模型名称 name?: string; // 模板数据 desc?: string; // icon 图标 icon?: string; // 首页配置 homePage?: string; // 头部菜单 menu?: HeaderMenu[]; } /** * Dto模型数据 */ export interface DtoDSLModelTypes extends DSLTypes { key: string; } /** * 项目数据 */ export interface DSLProjectTypes extends DSLTypes { key: string; modelKey: string; } /** * Dto项目数据 */ export interface DtoDSLProjectTypes { [key: string]: DSLProjectTypes; } /** * DSL模板结构化数据 */ export interface DtoDSLTypes { model: DtoDSLModelTypes; project: DtoDSLProjectTypes; } export interface IResponse<T = any> { success: boolean; data?: T; metadata?: Record<string, any>; message?: string; code?: number; } export interface IMain { serverStart: (options: Options) => Promise<App>; frontedBuild: (env: string) => void; BaseController: any; BaseService: any; }/** * DSL模板类型 */ export type MenuType = 'module' | 'group'; export type ModuleType = 'schema' | 'custom' | 'iframe' | 'sider'; export interface DSLIframeConfig { path: string; } export interface DSLCustomConfig { path: string; } export interface EnumListType { label: string; value: any; } export interface DSLSchemaProperties { [key: string]: { type: string; label: string; maxLength?: number; minLength?: number; required?: string[]; minimum?: number; maximum?: number; pattern?: string; tableOption?: { visible?: boolean; [key: string]: any; }; searchOption?: { comType?: string; api?: string; visible?: boolean; default?: any; enumList?: EnumListType[]; [key: string]: any; }; createFormOption?: { comType?: string; label?: string; enumList?: EnumListType[]; default?: any; [key: string]: any; }; editFormOption?: { comType?: string; label?: string; enumList?: EnumListType[]; default?: any; [key: string]: any; }; [key: string]: any; }; } export interface enumListType { label: string; value: string; } export interface DtoDSLSchemaPropertiesValue { type?: string; label?: string; maxLength?: number; minLength?: number; required?: boolean; minimum?: number; maximum?: number; pattern?: string; option?: { default?: string; toFixed?: boolean; visible?: boolean; comType?: string; enumList?: enumListType[]; api?: string; [key: string]: any; }; [key: string]: any; } export interface DtoDSLSchemaProperties { [key: string]: DtoDSLSchemaPropertiesValue; } export interface DtoSchema { type: 'object'; properties: DtoDSLSchemaProperties; } export interface DSLSchema { type: string; properties: DSLSchemaProperties; required?: string[]; } /** * 表头按钮配置 */ export interface DSLButtons { label: string; eventKey: string; eventOption: { // 当eventKey为remove时,params为删除的数据 params?: { // paramKey = 参数的键值 [key: string]: string; }; // 组件名称 comName?: string; }; params?: any; [key: string]: any; } export interface DSLTableConfig { headerButtons: DSLButtons[]; rowButtons: DSLButtons[]; } export interface DSLSearchConfig { [key: string]: any; } export interface DSLSchemaConfig { // 遵循 RESTful API 规范 api: string; schema: DSLSchema; // 表单配置 tableConfig?: DSLTableConfig; // search-bar配置 searchConfig?: DSLSearchConfig; componentConfig?: { title?: string; saveBtnText?: string; mainKey?: string; [key: string]: any; }; } /** * DSL component配置 */ export interface DtoDSLComponentConfig { schema: DtoSchema; config: DSLSchemaConfig['componentConfig']; } /** * 头部菜单 */ export interface HeaderMenu { key: string; name: string; menuType?: MenuType; // 当menuType为group时 subMenu?: HeaderMenu[] | DSLSiderConfig[]; // 当menuType为module时 moduleType?: ModuleType; // 当menuType为module且moduleType为schema时 schemaConfig?: DSLSchemaConfig; // 当menuType为module且moduleType为custom时 customConfig?: DSLCustomConfig; // 当menuType为module且moduleType为iframe时 iframeConfig?: DSLIframeConfig; // 当menuType为module且moduleType为sider时 siderConfig?: { menu: DSLSiderConfig[]; }; [key: string]: any; } export interface DSLSiderConfig extends HeaderMenu { moduleType?: Exclude<ModuleType, 'sider'>; [key: string]: any; }- 配置到
