init.json指南
12003快速开始
jianghu-init JSON
以JSON格式高效地管理页面结构和API接口,从而优化开发流程和提升工作效率。本指南主要介绍jianghu-init JSON
的详细教程。
安装
在开始之前,请确保您已经安装了jianghu-init
工具。可以通过以下命令进行安装:
npm uninstall -g @jianghujs/jianghu-init
# 最新版本 3.2.5
npm install -g @jianghujs/jianghu-init@latest
👉 jianghu-init 工具安装详解👈
在江湖项目中生成参考示例
- 首先,进入已有的江湖JS项目目录
👉 创建jianghujs项目 👈
- 使用以下命令生成参考示例:
cd my-jh-project
jianghu-init json --generateType=example
执行以上命令,当前项目数据库将添加 example_class 和 example_student 数据表、并在项目目录生成以下文件:
- app\view\init-json\component\exampleStudentOfClass.js
- app\view\init-json\page\exampleClass.js
- app\view\component\example\exampleStudentOfClass.html
- app\view\page\exampleClass.html
方便参考使用
步骤一:数据表生成配置文件
当有一个新的业务数据表之后,可以使用以下命令生成数据表的配置文件,例如,现在有一个名为class
的数据表:
CREATE TABLE `class` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`classId` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '班级ID',
`className` varchar(255) DEFAULT NULL,
`operation` varchar(255) COLLATE utf8mb4_bin DEFAULT 'insert' COMMENT '操作; insert, update, jhInsert, jhUpdate, jhDelete jhRestore',
`operationByUserId` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '操作者userId',
`operationByUser` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '操作者用户名',
`operationAt` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '操作时间; E.g: 2021-05-28T10:24:54+08:00 ',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
要为class
数据表生成基础配置文件,可以使用以下命令:
jianghu-init json --generateType=json --pageType=jh-page --table=class --pageId=classManagement
执行命令之后,会在项目的app/view/init-json/page/目录下生成一个名为classManagement.js
的配置文件。
步骤二:配置文件生成页面
上一步生成的配置文件,需要通过以下命令生成页面:
jianghu-init json --generateType=page --pageType=page --file=classManagement
执行以上命令,将会生成项目的app/view/page/目录下生成一个名为classManagement.html
的页面文件,并自动配置页面对应的数据库表_page和_resouce的数据。
👉 开启dev模式,修改配置文件自动更新页面 👈
👉 配置字符串代码语法高亮 👈
配置协议
结构总览
{
pageType: "jh-page", // 页面类型,可选值为jh-page、jh-mobile-page、jh-component选
pageId: "pageId", // 页面唯一标识
pageName: "班级页面", // 页面标题
template: "jhTemplateV4", // 页面模板,默认为jhTemplateV4,手机端一般设置为jhMobileTemplateV4
version: 'v3', // 版本 空 或者 v2
resourceList: [],// 页面resource { actionId, resourceType, resourceData }
headContent: [], // 页面头部,常用于配置 标题、面包屑条、服务端搜索、场景搜索等
pageContent: [], // 页面内容区域
actionContent: [], // 触发内容集合,一般会放新增、修改等弹框
includeList: [], // 页面引入资源 { type, path }
common: { // vue 原生变量 + uiAction {data, props, watch, methods, computed}
data: {},
computed: {},
watch: {},
methods: {},
doUiAction: {}, // 自定义uiAction { [key]: [method1, method2, doUiAction1]}
},
style: '', // 自定义样式
}
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
pageType | string | ✅ | 页面类型,可选值为jh-page、jh-mobile-page、jh-component、 |
pageId | string | ✅ | 页面唯一标识 |
template | string | 否 | 模版 |
version | string | 否 | 版本 (目前支持设定v2、v3) |
resourceList | array | 否 | |
headContent | array | ✅ | 面包屑 |
pageContent | array | ✅ | 页面主体内容 |
actionContent | array | ✅ | 触发内容(抽屉、弹窗、遮罩层等) |
includeList | array | ✅ | 页面引入资源 { type, path } |
common | object | ✅ | 变量、方法 |
style | string | 否 | 、 |
HTML标签
在 headContent、pageCotent、actionContent 中,可以使用使用指定的对象结构来配置一个标签,也支持直接使用HTML字符串。
对象结构
pageContent: [
{
tag: 'v-row',
attrs: {
align: "center"
"@click": "doUiAction('updateItem')"
},
quickAttrs: ['no-gutters'],
value: [
{ tag: 'v-col', attrs: { cols: 12 }, value: '' },
/*html*/`<v-col cols="12"></v-col>`
]
}
]
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
tag | string | 否 | 标签名称 |
attr | object | ✅ | 标签属性,如class、@click等 |
quickAttrs | array | 否 | 标签简洁属性,如 v-else small disabled等 |
value | object | 否 | 标签内的HTML内容 |
HTML字符串
pageContent: [
`<v-row align="center"><v-col cols="12"></v-col></v-row>`
]
接口配置
配置江湖resource,定义的resouce将自动更新到数据库中,供前端调用。
resourceList: [
{
resourceHook: { "before": [], "after": [] }, // 无需设置时可省略
actionId: 'balance-updateItem',
desc: '修改班费余额',
resourceType: 'sql',
resourceData: { "table": "class", "operation": "update" }
}
]
👉 resouce详细配置文档 👈
资源引入
当页面需要引入组件、样式、脚本等资源时,可以通过includeList配置。支持对象结构和HTML字符串。
includeList: [
{ type: 'css', path: "/<$ ctx.app.config.appId $>/public/lib/echarts.min.css" },
{ type: 'script', path: "/<$ ctx.app.config.appId $>/public/lib/echarts.min.js" },
{ type: 'html', path: "component/exampleChart/lineChart.html" },
{ type: 'html', path: 'component/courseBatchDrawer.html', includeType: 'auto', attrs: { id: 'courseBatchDrawer' } },
{ type: 'vueComponent', name: 'v-chart', component: 'VueCharts' },
`<script src="/<$ ctx.app.config.appId $>/public/lib/echarts.min.js"></script>`
]
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
type | string | ✅ | 引入类型,可选 css、js、html、vueComponent |
path | string | 否 | 引入路径,type为css、js、html时可用 |
includeType | string | 否 | 引入类型,可选 auto,当值为auto时将自动添加标签内容添加到页面末端。type为css、js、html时可用 |
attrs | object | 否 | 自定引入标签属性。type为html、includeType为auto时可用 |
name | string | 否 | 组件名,type为vueComponent时可用 |
component | string | 否 | 引入组件,type为vueComponent时可用 |
配置doUiAction
提供补充doUiAction方法的配置入口
pageContent: [
{
tag: 'v-btn',
value: '测试doUiAction1',
attrs: { '@click': 'doUiAction("doSomething")' },
quickAttrs: ['small']
},
`<v-btn @click="doUiAction('doSomething')">测试doUiAction2</v-btn>`
],
common: {
doUiAction: {
startUpdataBalance: ['async.method1', 'method2'],
doSomething: ['method3(134)', 'doUiAction.startUpdataBalance']
},
methods: {
async method1 (id) {
console.log('method1', id)
},
async method2 () {
console.log('method2')
},
async method3(actionData) {
console.log('method3')
}
}
}
- 默认方法链使用 await 同步执行,可添加 async. 进行异步修饰 例:
doUiAction: {
startUpdataBalance: ['async.method1', 'method2'],
},
// 实际执行
case 'startUpdataBalance':
this.method1(uiActionData);
await this.method2(uiActionData);
break;
- 默认方法链使用方法执行,可添加 doUiAction. 进行包含流程 例:
doUiAction: {
doSomething: ['method3(134)', 'doUiAction.startUpdataBalance'],
doSomething2: ['method3(134)', 'async.doUiAction.startUpdataBalance']
},
// 实际执行
case 'doSomething':
await this.method3(uiActionData);
await this.doUiAction('startUpdataBalance', uiActionData);
break;
case 'doSomething2':
await this.method3(uiActionData);
this.doUiAction('startUpdataBalance', uiActionData);
break;
调用链中支持配置方法名、方法名+参数、doUiAction方法名。
配置示例-PC端
基础页面
const content = {
pageType: "jh-page", pageId: "classManagement", pageName: "classManagement页面", template: 'jhTemplateV4', version: 'v3',
resourceList: [
{
actionId: "selectItemList",
resourceType: "sql",
desc: "✅查询列表-classManagement",
resourceData: { table: "class", operation: "select" }
},
// ... insertItem/updateItem/deleteItem
], // { actionId: '', resourceType: '', resourceData: {}, resourceHook: {}, desc: '' }
headContent: [
{ tag: 'jh-page-title', value: "classManagement", attrs: { cols: 12, sm: 6, md:4 }, helpBtn: true, slot: [] },
{ tag: 'v-spacer' },
{
tag: 'jh-search',
attrs: { cols: 12, sm: 6, md:8 },
searchBtn: true,
value: [
{ tag: "v-text-field", model: "serverSearchWhereLike.className", attrs: {prefix: '前缀'} },
],
// v3 版本新增特性
data: {
serverSearchWhereLike: { name: '' },
serverSearchWhere: { semester: '', segment: '小学' },
}
}
],
pageContent: [
{
tag: 'jh-table',
attrs: { },
colAttrs: { clos: 12 },
cardAttrs: { class: 'rounded-lg elevation-0' },
headActionList: [
{ tag: 'v-btn', value: '新增', attrs: { color: 'success', class: 'mr-2', '@click': 'doUiAction("startCreateItem")', small: true } },
{ tag: 'v-spacer' },
// 默认筛选
{
tag: 'v-col',
attrs: { cols: '12', sm: '6', md: '3', xs: 8, class: 'pa-0' },
value: [
{ tag: 'v-text-field', attrs: {prefix: '筛选', 'v-model': 'searchInput', class: 'jh-v-input', ':dense': true, ':filled': true, ':single-line': true} },
],
}
],
headers: [
{ text: "id", value: "id", width: 80, sortable: true, class: "fixed", cellClass: "fixed" },
{ text: "班级ID", value: "classId", width: 80, sortable: true },
{ text: "className", value: "className", width: 80, sortable: true },
{ text: "操作", value: "operation", width: 80, sortable: true },
{ text: "操作者userId", value: "operationByUserId", width: 80, sortable: true },
{ text: "操作者用户名", value: "operationByUser", width: 80, sortable: true },
{ text: "操作时间", value: "operationAt", width: 80, sortable: true },
{ text: "操作", value: "action", type: "action", width: 'window.innerWidth < 500 ? 70 : 120', align: "center", class: "fixed", cellClass: "fixed" },
// width 表达式需要使用字符串包裹
],
value: [
// vuetify table custom slot
],
rowActionList: [
{ text: '编辑', icon: 'mdi-note-edit-outline', color: 'success', click: 'doUiAction("startUpdateItem", item)' }, // 简写支持 pc 和 移动端折叠
{ text: '删除', icon: 'mdi-trash-can-outline', color: 'error', click: 'doUiAction("deleteItem", item)' } // 简写支持 pc 和 移动端折叠
],
}
],
actionContent: [
{
tag: 'jh-create-drawer',
key: "create",
attrs: {},
title: '新增',
headSlot: [
{ tag: 'v-spacer'}
],
contentList: [
{
label: "新增",
type: "form",
formItemList: [
{ label: "id", model: "id", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "班级ID", model: "classId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "className", model: "className", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作", model: "operation", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者userId", model: "operationByUserId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者用户名", model: "operationByUser", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作时间", model: "operationAt", tag: "v-text-field", rules: "validationRules.requireRules", },
],
action: [{
tag: "v-btn",
value: "新增",
attrs: {
color: "success",
':small': true,
'@click': "doUiAction('createItem')"
}
}],
},
]
},
{
tag: 'jh-update-drawer',
key: "update",
attrs: {},
title: '编辑',
headSlot: [
{ tag: 'v-spacer'}
],
contentList: [
{
label: "编辑",
type: "form",
formItemList: [
{ label: "id", model: "id", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "班级ID", model: "classId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "className", model: "className", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作", model: "operation", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者userId", model: "operationByUserId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者用户名", model: "operationByUser", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作时间", model: "operationAt", tag: "v-text-field", rules: "validationRules.requireRules", },
],
action: [{
tag: "v-btn",
value: "编辑",
attrs: {
color: "success",
':small': true,
'@click': "doUiAction('updateItem')"
}
}],
},
{ label: "操作记录", type: "component", componentPath: "recordHistory", attrs: { table: 'class', pageId: 'classManagement', ':id': 'updateItem.id' } },
]
},
],
includeList: [], // { type: < js | css | html | vueComponent >, path: ''}
common: {
data: {
constantObj: {},
validationRules: {
requireRules: [
v => !!v || '必填',
],
},
serverSearchWhereLike: { className: '' }, // 服务端like查询
serverSearchWhere: { }, // 服务端查询
serverSearchWhereIn: { }, // 服务端 in 查询
filterMap: {}, // 结果筛选条件
},
dataExpression: {
isMobile: 'window.innerWidth < 500'
}, // data 表达式
watch: {},
computed: {
tableDataComputed() {
if(this.filterMap) {
return this.tableData.filter(row => {
for (const key in this.filterMap) {
if (this.filterMap[key] && row[key] !== this.filterMap[key]) {
return false;
}
}
return true;
});
} else {
return this.tableData;
}
},
},
doUiAction: {}, // 额外uiAction { [key]: [action1, action2]}
methods: {}
},
};
module.exports = content;
标题-只有页面标题
headContent: [
{ tag: 'jh-page-title', value: "classManagement", attrs: { cols: 12, sm: 6, md:4 }, helpBtn: true, slot: [] }
]
标题-服务端搜索
headContent: [
{ tag: 'jh-page-title', value: "classManagement", attrs: { cols: 12, sm: 6, md:4 }, helpBtn: true, slot: [] },
{ tag: 'v-spacer' },
{
tag: 'jh-search',
attrs: { cols: 12, sm: 6, md:8 },
value: [
{ tag: "v-text-field", model: "serverSearchWhereLike.className", attrs: {prefix: '前缀'} },
],
searchBtn: true,
data: {
serverSearchWhereLike: { name: '' },
}
}
]
标题-场景搜索
headContent: [
{ tag: 'jh-page-title', value: "classManagement", attrs: { cols: 12, sm: 6, md:4 }, helpBtn: true, slot: [] },
{ tag: 'v-spacer' },
{
tag: 'jh-scene',
attrs: { ':showActionBtn': false, ':mobile': true },
// v3 版本新增特性
data: {
sceneCreateForm: {}, // 默认创建表单
serverSceneSearchWhere: {}, // 可预设变量或忽略
serverSceneSearchWhereIn: {},
serverSceneSearchWhereLike: {},
serverSceneSearchWhereOptions: [],
serverSceneSearchWhereOrOptions: [],
currentSceneId: '全部', // 当前场景默认name
defaultSceneList: [
{ name: "全部", where: {} },
{ name: "无跟进人", where: { "gender": "male"}, whereIn: { level: ['01', '02'] } },
],
customSceneList: [
{ label: '年级', tag: 'v-select', model: 'form.level', attrs: {":items": 'constantObj.level'} },
{ label: '性别', tag: 'v-select', model: 'form.grade', attrs: {":items": 'constantObj.grade'} },
],
maxSceneDisplay: 2,
}
},
],
内容-数据表格
pageContent: [
{
tag: 'jh-table',
props: {
serverPagination: true // 开启服务端分页、服务端分页默认 limit 50
},
attrs: {},
colAttrs: { clos: 12 },
cardAttrs: { class: 'rounded-lg elevation-0' },
headActionList: [
{ tag: 'v-btn', value: '新增', attrs: { color: 'success', class: 'mr-2', '@click': 'doUiAction("startCreateItem")', small: true } },
{ tag: 'v-spacer' }
],
headers: [
{ text: "id", value: "id", width: 80, sortable: true, class: "fixed", cellClass: "fixed" },
{ text: "班级ID", value: "classId", width: 80, sortable: true },
{ text: "className", value: "className", width: 80, sortable: true },
{ text: "操作", value: "operation", width: 80, sortable: true },
{ text: "操作", value: "action", type: "action", width: 'window.innerWidth < 500 ? 70 : 120', align: "center", class: "fixed", cellClass: "fixed" },
],
value: [
// v-table插槽
// { tag: 'template', attrs: {'slot': 'body', 'slot-scope': "item"}, value: "<div>测试插槽</div>" },
// { tag: 'template', attrs: {'slot': 'item.className', 'slot-scope': "{item, index}"}, value: "<div>{{item.className}}</div>" },
],
rowActionList: [
{ text: '编辑', icon: 'mdi-note-edit-outline', color: 'success', click: 'doUiAction("startUpdateItem", item)' }, // 简写支持 pc 和 移动端折叠
{ text: '删除', icon: 'mdi-trash-can-outline', color: 'error', click: 'doUiAction("deleteItem", item)' } // 简写支持 pc 和 移动端折叠
],
}
]
内容-数据表格(启用列设置)
常用
pageContent: [
{
tag: 'jh-table',
attrs: {}, // v-data-table attrs
colAttrs: {}, // v-data-table 父元素 v-col attrs
cardAttrs: {}, // v-data-table 父元素 v-card attrs
headers: [], // v-data-table headers
value: [],
showTableColumnSettingBtn: true,
headActionList: [], // 表格上方 v-col 插槽
rowActionList: [], // 表格操作列操作按钮列表
}
],
模式设定
pageContent: [
{
tag: 'jh-table',
attrs: {},
value: [],
showTableColumnSettingBtn: true,
headActionList: [],
rowActionList: [],
}
],
common: {
data: {
columnSettingGroup: {
'01模式': [
"netName",
"stage",
"followUpDate",
"district",
"memberId",
"followUpBy",
"currentResidence",
"openVisitationStatus",
"totalVisitationCount",
"visitorAssignInfo",
"operationAt",
"action"
],
'02模式': [
"netName",
"stage",
"duoxingRoomName",
"followUpDate",
"tag",
"projectList",
"followUpBy",
"district",
"memberId",
"currentResidence",
"operationAt",
"action"
],
'03模式': [
"netName",
"orgId",
"orgName",
"roleId",
"isDefaultOrg"
],
},
}
}
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
showTableColumnSettingBtn | boolean | 否 | 是否启用列设置,默认false |
弹框-新增编辑表单
actionContent: [
{
tag: 'jh-create-drawer',
key: "create",
attrs: {},
title: '新增',
headSlot: [
{ tag: 'v-spacer'}
],
contentList: [
{
label: "新增",
type: "form",
formItemList: [
{ label: "id", model: "id", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "班级ID", model: "classId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "className", model: "className", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作", model: "operation", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者userId", model: "operationByUserId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者用户名", model: "operationByUser", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作时间", model: "operationAt", tag: "v-text-field", rules: "validationRules.requireRules", },
],
action: [{
tag: "v-btn",
value: "新增",
attrs: {
color: "success",
'@click': "doUiAction('createItem')"
},
quickAttrs: ['small']
}],
},
]
},
{
tag: 'jh-update-drawer',
key: "update",
props: {
mergeForm: true // prepareFormData 将会合并对象表单
},
attrs: {},
title: '编辑',
headSlot: [
{ tag: 'v-spacer'}
],
contentList: [
{
label: "编辑",
type: "form",
formItemList: [
{ label: "id", model: "id", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "班级ID", model: "classId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "className", model: "className", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作", model: "operation", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者userId", model: "operationByUserId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者用户名", model: "operationByUser", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作时间", model: "operationAt", tag: "v-text-field", rules: "validationRules.requireRules", },
],
action: [{
tag: "v-btn",
value: "编辑",
attrs: {
color: "success",
'@click': "doUiAction('updateItem')"
},
quickAttrs: ['small']
}],
},
{ label: "操作记录", type: "component", componentPath: "recordHistory", attrs: { table: 'class', pageId: 'classManagement', ':id': 'updateItem.id' } },
]
},
]
弹框-详情
pageContent: [
`<v-btn @click="openTestDetailDrawer">打开测试详情弹框</v-btn>`,
],
actionContent: [
{
tag: 'jh-drawer',
key: "testDetail",
attrs: {},
title: '测试详情',
contentList: [
{
type: "form",
formItemList: [
{ tag: 'span', value: '课程信息', md: 12, attrs: {class: 'title pl-2'}},
{ tag: 'div', md: 12, value: [/*html*/ `
<div class="grey lighten-5">
<v-row class="ma-0 pa-2">
<v-col cols="12" md="3" v-for="(item, index) in courseInfoItems" :key="index">
<span>{{item.title}}:{{item.value}}</span>
</v-col>
</v-row>
</div>
`]
}
]
}
]
}
],
"common": {
data: {
courseInfoItems: [
{ title: '课程名称', value: 'IT初级课程' }
]
}
}
弹框-自定义弹框
pageContent: [
`<v-btn @click="openTestCustomDrawer">打开测试自定义弹框</v-btn>`,
],
actionContent: [
{
tag: 'jh-drawer',
key: "testCustom",
attrs: {},
title: '测试自定义弹框',
contentList: [
`自定义内容`
]
}
]
弹框-多标签
pageContent: [
`<v-btn @click="openTestMultiTabDrawer">打开测试多标签弹框</v-btn>`,
],
actionContent: [
{
tag: 'jh-drawer',
key: "testMultiTab",
attrs: {},
title: '测试多标签',
contentList: [
{ label: "操作记录", type: "component", componentPath: "recordHistory" },
{ label: "学生列表", type: "component", componentPath: "example/studentOfClass", bind: ['classId'] },
]
}
]
弹框-自定义按钮
pageContent: [
`<v-btn @click="viewTestCustomBtn">打开测试自定义按钮弹框</v-btn>`
],
actionContent: [
{
tag: 'jh-create-drawer',
key: "testCustomBtn",
attrs: {},
title: '测试自定义按钮',
headSlot: [
{ tag: 'v-spacer' },
{ tag: 'v-btn', value: '自定义按钮', attrs: { color: 'success', class: 'mr-2', '@click': 'doUiAction("123")', small: true } },
],
contentList: [ /* 内容列表 */ ]
}
]
弹框-关闭弹框检查
actionContent: [
{
tag: 'jh-create-drawer',
key: "create",
attrs: {},
title: '新增',
isCheckFormBeforeClose: true,
onCheckFormConfirm: 'doUiAction("createItem", { notConfirmed: true })',
headSlot: [
{ tag: 'v-spacer'}
],
contentList: [
{
label: "新增",
type: "form",
formItemList: [
{ label: "id", model: "id", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "班级ID", model: "classId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "className", model: "className", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作", model: "operation", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者userId", model: "operationByUserId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者用户名", model: "operationByUser", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作时间", model: "operationAt", tag: "v-text-field", rules: "validationRules.requireRules", },
],
action: [{
tag: "v-btn",
value: "新增",
attrs: {
color: "success",
':small': true,
'@click': "doUiAction('createItem')"
}
}],
},
]
}
]
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
key | string | ✅ | form标识,如:create、update 等 |
title | string | ✅ | 抽屉标题 |
props.mergeForm | boolean | 否 | 是否合并提交form |
attrs | object | 否 | v-navigation-drawer 属性 |
isCheckFormBeforeClose | boolean | 否 | 是否打开关闭弹框检查,默认false,注意检查的表单对象与弹框的key需要保持匹配,如 表单对象:createItem,弹框key:create |
onCheckFormConfirm | string | 否 | 保存内容方法名称 |
contentList | array | ✅ | 抽屉内容 |
配置示例-移动端
基础页面
const content = {
pageType: "jh-mobile-page", pageId: "mobile/classManagement", pageName: "classManagement页面", template: "jhMobileTemplateV4", version: 'v2',
resourceList: [
{
actionId: "selectItemList",
resourceType: "sql",
desc: "✅查询列表-classManagement",
resourceData: { table: "class", operation: "select" }
},
// ... insertItem/updateItem/deleteItem
], // { actionId: '', resourceType: '', resourceData: {}, resourceHook: {}, desc: '' }
headContent: [
{ tag: 'jh-page-title', value: "班级管理", helpBtn: true, slot: [] },
{
tag: 'jh-order',
// v3 新特性
data: {
tableDataOrder: [ { column: "createAt", order: "desc" } ],
tableDataOrderList: [
{ text: "报名时间↓", value: [ { column: "createAt", order: "desc" } ] },
{ text: "成绩分数↓", value: [ { column: "middleSchoolExamScore", order: "desc" } ] },
{ text: "更新时间↓", value: [ { column: "operationAt", order: "desc" } ] },
],
}
},
{
tag: 'jh-search',
searchList: [
{ tag: 'v-select', model: "serverSearchWhere.semester", colAttrs: { class: 'pb-0' }, attrs: { prefix: '学期:', color: 'success', ':items': 'constantObj.semester' } },
{ tag: 'v-select', model: "serverSearchWhere.segment", colAttrs: { class: 'pb-0' }, attrs: { prefix: '学部:', color: 'success', ':items': 'constantObj.segment' } },
{ tag: 'v-text-field', model: "serverSearchWhereLike.name", colAttrs: { class: 'pb-0' }, attrs: { label: '学生名字:', color: 'success' }, quickAttrs: ['clearable'] },
],
data: {
serverSearchWhere: { semester: '', segment: '小学' },
serverSearchWhereLike: { name: '' },
}
},
{ tag: 'v-spacer'},
{ tag: 'jh-mode', data: { viewMode: 'simple' } },
],
pageContent: [
{
tag: 'jh-list',
props: {
limit: 10,
rightArrowText: '',
},
attrs: { cols: 12, class: 'p-0 pb-7', ':style': '`height: calc(100vh - 140px); overflow-y: auto;overscroll-behavior: contain`' },
headers: [
{text: "学生Id", value: "studentId", width: 80, isSimpleMode: true},
{text: "姓名", value: "name", width: 90, isTitle: true, slot: [`
<div v-if="item.isMonitor" class="ml-1">
<v-icon color="warning" small>mdi-shield-star</v-icon>
<span>干部</span>
</div>
`]},
{text: "性别", value: "gender", width: 60, isSimpleMode: true},
{text: "学生状态", value: "studentStatus", width: 80},
{text: "年级", value: "level", width: 70},
{text: "入学-推荐人", value: "recommendBy", width: 100, isDetailMode: true},
{text: "入学-跟进人", value: "followUpByUserName", width: 100, isDetailMode: true},
{text: "跟进阶段", value: "followUpStage", width: 80},
{text: "报名时间", value: "createAt", width: 150},
{text: "操作者", value: "operationByUser", width: 90},
{text: "操作时间", value: "operationAt", width: 150},
{text: '操作', value: 'action', align: 'center', sortable: false, width: 'window.innerWidth < 500 ? 90: 180', class: 'fixed', cellClass: 'fixed'},
],
rowActionList: [
{ text: "编辑", icon: 'mdi-note-edit-outline', color: 'success', click: 'doUiAction("startUpdateItem", item)' }
],
},
{
tag: 'jh-action',
attrs: { class: 'h-16 w-16 p-2 fixed right-4 bottom-32' },
actionList: [
{ tag: 'v-btn', value: '新增', icon: 'mdi-plus', color: 'success', click: "doUiAction('startCreateItem')" },
{ tag: 'v-btn', value: '随机分配跟进人', icon: 'mdi-plus', color: 'success', click: "doUiAction('randomFollowUp')", ':disabled': '!tableSelected.length' },
]
}
],
actionContent: [
{
tag: 'jh-create-drawer',
key: "create",
attrs: {},
title: '新增',
headSlot: [
{ tag: 'v-spacer'}
],
contentList: [
{
label: "新增",
type: "form",
formItemList: [
{ label: "id", model: "id", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "班级ID", model: "classId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "className", model: "className", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作", model: "operation", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者userId", model: "operationByUserId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者用户名", model: "operationByUser", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作时间", model: "operationAt", tag: "v-text-field", rules: "validationRules.requireRules", },
],
action: [{
tag: "v-btn",
value: "新增",
attrs: {
color: "success",
':small': true,
'@click': "doUiAction('createItem')"
}
}],
},
]
},
{
tag: 'jh-update-drawer',
key: "update",
attrs: {},
title: '编辑',
headSlot: [
{ tag: 'v-spacer'}
],
contentList: [
{
label: "编辑",
type: "form",
formItemList: [
{ label: "id", model: "id", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "班级ID", model: "classId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "className", model: "className", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作", model: "operation", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者userId", model: "operationByUserId", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作者用户名", model: "operationByUser", tag: "v-text-field", rules: "validationRules.requireRules", },
{ label: "操作时间", model: "operationAt", tag: "v-text-field", rules: "validationRules.requireRules", },
],
action: [{
tag: "v-btn",
value: "编辑",
attrs: {
color: "success",
':small': true,
'@click': "doUiAction('updateItem')"
}
}],
},
{ label: "操作记录", type: "component", componentPath: "recordHistory", attrs: { table: 'class', pageId: 'classManagement', ':id': 'updateItem.id' } },
]
},
{
tag: 'jh-detail-drawer',
key: "detail",
attrs: {},
title: "详情",
headSlot: [
],
card: {
tag: 'div',
colAttrs: { class: 'pa-0' },
value: `
<div class="p-3 border-b" >
<div class="flex justify-between mb-2 items-center">
<div>
<span class="font-weight-bold text-base">{{ detailItem.name }}</span>
</div>
<span :class="'text-sm '">{{ detailItem.followUpStatus }}</span>
</div>
<div class="text-gray-500 flex justify-between">意向就读学部:{{ detailItem.segment }}</div>
<div class="text-gray-500 flex justify-between">报名日期:{{ detailItem.createAt }}</div>
</div>
<div class="pa-0 h-2 bg-gray-100" ></div>
`
},
contentList: [
{
type: 'preview',
md: 12,
formItemList: [
{ label: "性别", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.gender }}" },
{ label: "身份证件号", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.icNumber }}" },
{ label: "家庭住址", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.residentialAddress }}" },
{ label: "意向就读学部", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.segment }}" },
{ label: "意向就读年级", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.level }}" },
{ label: "意向就读方式", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.afterSchoolCareType }}" },
{ label: "原就读学校", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.schoolRoll }}" },
{ label: "中考分数", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.middleSchoolExamScore }}" },
{ label: "中考报名序号", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.middleSchoolExamSequence }}" }
],
action: [
{
tag: 'v-btn',
value: "编辑",
attrs: {
color: 'primary',
'@click': "doUiAction('startUpdateItem', detailItem); closeDetailDrawer()"
},
quickAttrs: ['small']
}
]
}
]
},
],
includeList: [], // { type: < js | css | html | vueComponent >, path: ''}
common: {
data: {
constantObj: {
},
validationRules: {
requireRules: [
v => !!v || '必填',
],
},
filterMap: {}, // 结果筛选条件
},
dataExpression: {
isMobile: 'window.innerWidth < 500'
}, // data 表达式
watch: {},
computed: {
tableDataComputed() {
if(this.filterMap) {
return this.tableData.filter(row => {
for (const key in this.filterMap) {
if (this.filterMap[key] && row[key] !== this.filterMap[key]) {
return false;
}
}
return true;
});
} else {
return this.tableData;
}
},
},
doUiAction: {}, // 额外uiAction { [key]: [action1, action2]}
async created() {
await this.doUiAction('getTableData');
},
methods: {}
},
};
module.exports = content;
标题-只有页面标题
headContent: [
{ tag: 'jh-page-title', value: "班级管理" },
],
标题-排序&筛选&模式切换
headContent: [
{ tag: 'jh-page-title', value: "班级管理" },
{
tag: 'jh-order',
data: {
tableDataOrder: [ { column: "createAt", order: "desc" } ],
tableDataOrderList: [
{ text: "报名时间↓", value: [ { column: "createAt", order: "desc" } ] },
{ text: "成绩分数↓", value: [ { column: "middleSchoolExamScore", order: "desc" } ] },
{ text: "更新时间↓", value: [ { column: "operationAt", order: "desc" } ] },
],
}
}, // 固定变量 model: 'tableDataOrder', items: 'tableDataOrderList'
{
tag: 'jh-search',
searchList: [
{ tag: 'v-select', model: "serverSearchWhere.semester", colAttrs: { class: 'pb-0' }, attrs: { prefix: '学期:', color: 'success', ':items': 'constantObj.semester' } },
{ tag: 'v-select', model: "serverSearchWhere.segment", colAttrs: { class: 'pb-0' }, attrs: { prefix: '学部:', color: 'success', ':items': 'constantObj.segment' } },
{ tag: 'v-text-field', model: "serverSearchWhereLike.name", colAttrs: { class: 'pb-0' }, attrs: { label: '学生名字:', color: 'success' }, quickAttrs: ['clearable'] },
],
data: {
serverSearchWhereLike: { name: '' },
serverSearchWhere: { semester: '', segment: '小学' },
}
},
{ tag: 'v-spacer'},
{ tag: 'jh-mode', data: { viewMode: 'simple' } },
],
common: {
data: {
constantObj: {
},
}
}
内容-数据列表
pageContent: [
{
tag: 'jh-list',
props: {
limit: 10, // 服务端搜索limit
},
attrs: { cols: 12, class: 'p-0 pb-7', ':style': '`height: calc(100vh - 140px); overflow-y: auto;overscroll-behavior: contain`' },
headers: [
{text: "学生Id", value: "studentId", width: 80, isSimpleMode: true},
{text: "姓名", value: "name", width: 90, isTitle: true, slot: [`
<div v-if="item.isMonitor" class="ml-1">
<v-icon color="warning" small>mdi-shield-star</v-icon>
<span>干部</span>
</div>
`]},
{text: "性别", value: "gender", width: 60, isSimpleMode: true},
{text: "学生状态", value: "studentStatus", width: 80},
{text: "年级", value: "level", width: 70},
{text: "入学-推荐人", value: "recommendBy", width: 100, isDetailMode: true},
{text: "入学-跟进人", value: "followUpByUserName", width: 100, isDetailMode: true},
{text: "跟进阶段", value: "followUpStage", width: 80},
{text: "报名时间", value: "createAt", width: 150},
{text: "操作者", value: "operationByUser", width: 90},
{text: "操作时间", value: "operationAt", width: 150},
{text: '操作', value: 'action'},
],
rowActionList: [
]
}
],
common: {
async created() {
await this.doUiAction('getTableData');
},
doUiAction: {
startDetailItem: ['startDetailItem']
},
methods: {
}
}
jh-list
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
props.limit | string | 否 | 分页每页数量 |
props.rightArrowText | string | 否 | 右边箭头文本 |
headers | array | ✅ | 字段内容 |
headers.isSimpleMode | boolean | 否 | 是否只在简单模式显示,默认false |
headers.isTitle | boolean | 否 | 是否作为行标题 |
rowActionList | array | 否 | 详情模式下的点击行 |
内容-数据列表(详情弹框)
pageContent: [
{
tag: 'jh-list',
props: {
limit: 10,
rightArrowText: '',
},
attrs: { cols: 12, class: 'p-0 pb-7', ':style': '`height: calc(100vh - 140px); overflow-y: auto;overscroll-behavior: contain`' },
headers: [
{text: "学生Id", value: "studentId", width: 80, isSimpleMode: true},
{text: "姓名", value: "name", width: 90, isTitle: true, slot: [`
<div v-if="item.isMonitor" class="ml-1">
<v-icon color="warning" small>mdi-shield-star</v-icon>
<span>干部</span>
</div>
`]},
{text: "性别", value: "gender", width: 60, isSimpleMode: true},
{text: "学生状态", value: "studentStatus", width: 80},
{text: "年级", value: "level", width: 70},
{text: "跟进阶段", value: "followUpStage", width: 80},
{text: "报名时间", value: "createAt", width: 150},
{text: '操作', value: 'action', align: 'center', sortable: false, width: 'window.innerWidth < 500 ? 90: 180', class: 'fixed', cellClass: 'fixed'},
],
rowActionList: [
{ text: "编辑", icon: 'mdi-note-edit-outline', color: 'success', click: 'doUiAction("startUpdateItem", item)' }
],
}
],
actionContent: [
{
tag: 'jh-detail-drawer',
key: "detail",
attrs: {},
title: "详情",
headSlot: [
],
card: {
tag: 'div',
colAttrs: { class: 'pa-0' },
value: `
<div class="p-3 border-b" >
<div class="flex justify-between mb-2 items-center">
<div>
<span class="font-weight-bold text-base">{{ detailItem.name }}</span>
</div>
<span :class="'text-sm '">{{ detailItem.followUpStatus }}</span>
</div>
<div class="text-gray-500 flex justify-between">意向就读学部:{{ detailItem.segment }}</div>
<div class="text-gray-500 flex justify-between">报名日期:{{ detailItem.createAt }}</div>
</div>
<div class="pa-0 h-2 bg-gray-100" ></div>
`
},
contentList: [
{
type: 'preview',
md: 12,
formItemList: [
{ label: "性别", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.gender }}" },
{ label: "身份证件号", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.icNumber }}" },
{ label: "家庭住址", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.residentialAddress }}" },
{ label: "意向就读学部", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.segment }}" },
{ label: "意向就读年级", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.level }}" },
{ label: "意向就读方式", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.afterSchoolCareType }}" },
{ label: "原就读学校", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.schoolRoll }}" },
{ label: "中考分数", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.middleSchoolExamScore }}" },
{ label: "中考报名序号", tag: "span", colAttrs: { class: 'border-b pb-2 flex justify-between' }, value: "{{ detailItem.middleSchoolExamSequence }}" }
],
action: [
{
tag: 'v-btn',
value: "编辑",
attrs: {
color: 'primary',
'@click': "doUiAction('startUpdateItem', detailItem); closeDetailDrawer()"
},
}
]
}
]
}
],
common: {
async created() {
await this.doUiAction('getTableData');
},
}
内容-圆点操作菜单
pageContent: [
{
tag: 'jh-action',
attrs: { class: 'h-16 w-16 p-2 fixed right-4 bottom-32' },
actionList: [
{ tag: 'v-btn', value: '新增', icon: 'mdi-plus', color: 'success', click: "doUiAction('startCreateItem')" },
{ tag: 'v-btn', value: '随机分配跟进人', icon: 'mdi-plus', color: 'success', click: "doUiAction('randomFollowUp')", ':disabled': '!tableSelected.length' },
]
}
]
弹框相关
👉参考PC端弹框相关配置 👈
命令详解
生成样例文件页面
默认生成 example_class
和 example_student
数据表、配置文件和页面,方便参考使用
jianghu-init json --generateType=example
生成页面配置文件
根据数据表生成页面配置文件
jianghu-init json --generateType=json --pageType=page --table=class --pageId=classManagement
配置渲染html
根据配置文件生成页面
jianghu-init json --generateType=page --pageType=page --file=classManagement
开启Dev模式
开启dev模式,修改配置文件将自动更新页面
jianghu-init json dev
参数说明
参数 | 描述 |
---|---|
generateType | 生成类型,可选 example(生成示例文件)、json(数据表生成配置文件)、page(配置文件生成页面) |
pageType | 页面类型,可选 page、component |
table | 数据表名,当generateType为json可用 |
dev | 启用开发模式,执行后会自动检测当前项目的json文件更新并自动更新html文件 |
其他
字符串代码语法高亮
- 在VSCode中,可以安装以下插件来实现字符串代码的语法高亮,以提高代码的可读性:
安装以上插件之后,在字符串代码前指定语法名称,即可显示语法高亮效果。
pageContent: [
/*html*/`<v-btn @click="openTestMultiTabDrawer">打开测试多标签弹框</v-btn>`,
],
style: /*css*/`
.jh-v-input {
width: 100%;
}
`
- 你可以调整 VSCode 的配置来更好地支持模板字符串的 HTML 提示。在 VSCode 的设置中,搜索 "editor.quickSuggestions" 并确保在 "strings" 中启用补全建议:
"editor.quickSuggestions": {
"strings": true
}
version v2版本升级指南
- 增加服务端搜索 jh-page
{
tag: 'jh-table',
props: {
serverPagination: true, // 需要version: v2
},
attrs: {},
}
- doUiAction.getTableData,尽量不要全部覆盖方法链,如需自定义选择相应方法复写
common.doUiAction: {
getTableData: [
'prepareTableParamsDefault', // 组合搜索条件赋值到:this.tableParams
'prepareTableParams', // 自定义条件方法
'getTableData', // 请求
'formatTableData' // 格式化 tableData
]
}
- formatTableData 方法
// 原版
formatTableData(rows) {
rows.forEach(row => {
row.operationAt = row.operationAt ? dayjs(row.operationAt).format('YYYY-MM-DD HH:mm:ss') : '';
});
return rows;
}
// v2版本
formatTableData() {
let tableData = this.tableDataFromBackend.map(row => {
row.operationAt = row.operationAt ? dayjs(row.operationAt).format('YYYY-MM-DD HH:mm:ss') : '';
return row;
});
this.tableData = tableData;
}
version v3版本升级指南
- 重构 init-json jh组件,把需要设置在 common.data 内的变量放入标签内,方便组件变量管理
- jh-order 移动端排序
{
tag: 'jh-order',
data: {
tableDataOrder: [ { column: "createAt", order: "desc" } ],
tableDataOrderList: [
{ text: "报名时间↓", value: [ { column: "createAt", order: "desc" } ] },
{ text: "成绩分数↓", value: [ { column: "middleSchoolExamScore", order: "desc" } ] },
{ text: "更新时间↓", value: [ { column: "operationAt", order: "desc" } ] },
],
}
},
- jh-search 服务端搜索
{
tag: 'jh-search',
searchList: [
{ tag: 'v-select', model: "serverSearchWhere.semester", colAttrs: { class: 'pb-0' }, attrs: { prefix: '学期:', color: 'success', ':items': 'constantObj.semester' } },
{ tag: 'v-select', model: "serverSearchWhere.segment", colAttrs: { class: 'pb-0' }, attrs: { prefix: '学部:', color: 'success', ':items': 'constantObj.segment' } },
{ tag: 'v-text-field', model: "serverSearchWhereLike.name", colAttrs: { class: 'pb-0' }, attrs: { label: '学生名字:', color: 'success' }, quickAttrs: ['clearable'] },
],
data: {
serverSearchWhereLike: { name: '' },
serverSearchWhere: { semester: '', segment: '小学' },
}
},
- jh-mode 模式切换
{ tag: 'jh-mode', data: { viewMode: 'simple' } },
- jh-scene 场景搜索
{
tag: 'jh-scene',
attrs: {
// ':showActionBtn': false,
':mobile': true
},
data: {
sceneCreateForm: {},
currentSceneId: '全部',
defaultSceneList: [
{ name: "全部", where: {} },
{ name: "无跟进人", where: { level: "01", "gender": "male"} },
],
customSceneList: [
{ label: '年级', tag: 'v-select', model: 'form.level', attrs: {":items": 'constantObj.level'} },
{ label: '性别', tag: 'v-select', model: 'form.grade', attrs: {":items": 'constantObj.grade'} },
],
maxSceneDisplay: 2,
}
}