asaihost-vue
v0.0.8
Published
AsaiWeb CMS Vue 3 host plugin — engine runtime, UI shell, directives, and webmodel bootstrap
Maintainers
Readme
asaihost-vue
Vue 3 应用宿主框架:引擎运行时(API / WebSocket / AES)、UI 壳层组件、自定义指令,以及基于 public/webmodel/ 的配置引导链。
| 项 | 值 |
|----|-----|
| npm 包名 | asaihost-vue |
| 插件入口 | index.ts(monorepo 源码)/ dist/asaihost-vue.es.js(发布后) |
| 运行时配置根 | public/webmodel/ + cfg.js |
| 对等依赖 | vue ^3.4 |
目录结构
asaihost-vue/
├── index.ts # 包入口(re-export 插件 + 类型)
├── package.json
├── vite.config.ts
└── src/
├── index.ts # Vue 插件 install(glob 注册 asengine / asui / asdirectives)
├── types.ts
├── asengine/ # API、WS、AES、provide、路由引擎
├── asui/ # 全局 UI 组件
└── asdirectives/ # v-drag、v-userlevel 等指令目录
快速开始
安装
npm install asaihost-vue vue
# 或
yarn add asaihost-vue vue
pnpm add asaihost-vue vue@noble/ciphers 已作为本包依赖声明(AES-GCM HTTP 降级路径);无需单独安装。
最小集成(main.ts)
import { createApp } from 'vue';
import App from './App.vue';
import LibInit from './lib/LibInit'; // 见下文「LibInit」
import AsaiHostVue from 'asaihost-vue';
const app = createApp(App);
const { lib } = LibInit();
app.use(AsaiHostVue, lib); // 必须最先安装
app.mount('#app');静态资源配置
在 index.html 引入 cfg.js,并将 webmodel/ 目录放到 Vite public/ 下(详见 cfg.js)。
在 AsaiCMS monorepo 内使用
本仓库 webclient 通过路径别名引用插件源码,开发时无需先 npm pack:
// webclient/src/utils/index.ts
import AsaiHostVue from '../plugs/asaihost-vue';本地构建 npm 产物:
cd webclient/src/plugs/asaihost-vue
npm install
npm run build独立项目集成
1. Vite 项目
确保 vite.config 能处理本包内的 .vue 与 import.meta.glob(默认 @vitejs/plugin-vue 即可)。
若从 npm 安装(使用 dist/ 预构建产物),直接 import AsaiHostVue from 'asaihost-vue'。
若通过 git submodule / 拷贝源码 联调,可在 package.json 使用 link: 或 file: 指向插件目录,并优先解析 development 条件到 src/index.ts。
2. 复制 LibInit
宿主插件不内置 LibInit——它由业务项目提供 loadts / loadvue / loadv 三个加载器。可从 AsaiCMS webclient/src/lib/LibInit.ts 复制或按需裁剪。
3. 环境变量(.env)
VITE_WEB_PATH=/
VITE_ASAI_AES_KEYBASE64=<与后端 ASAI_AES_KEYBASE64 一致>4. TypeScript
{
"compilerOptions": {
"moduleResolution": "bundler",
"types": ["vite/client"]
}
}可从本包导入类型:
import type { VueHostLibLoader, AsaiHostVuePlugin } from 'asaihost-vue';LibInit 与 install 约定
AsaiHostVue.install(app, lib) 在启动时注册三类资源:
| 步骤 | lib 方法 | 注册内容 |
|------|----------|----------|
| 1 | loadts | $engineasai:asengine/common/*.ts、useApi / useWs / useAES / useProvide 等 |
| 2 | loadvue | asui/*/*.vue 全局组件(懒加载) |
| 3 | loadv | asdirectives/*/index.ts 自定义指令 |
lib 最少需提供:
interface VueHostLibLoader {
loadts(params: { app; key; eager?; files }): void;
loadvue(params: { app; eager?; loadfn?; files }): unknown;
loadv(params: { app; eager?; files }): void;
loadfn?: { fnvue: typeof defineAsyncComponent };
}安装顺序:AsaiHostVue 必须早于业务 lib-install 与其它插件。
启动链
app.use(AsaiHostVue, lib)
→ AsaiInitPage.onMounted
→ initweb($vueProxy) // dirglobal + dirmodel + configrouter + server.json
→ useApi('web') / useWs('web')
→ AsaiWebServer → AsaiComponent(hash 选模块)
→ AsaiWebModule → useInitApp(module) → RouterView配置文件总览
本插件不读取单一 JSON,而是通过 initweb() 按固定顺序加载一组配置文件,合并到运行时 ujt(window.$GYS.ujt):
index.html
└── cfg.js → window.$CFG(静态资源路径、标题)
↓
initweb() 加载顺序:
1. sys/dirglobal.json → 索引全局 sys 片段
2. sys/dirmodel.json → 索引模型 JSON
3. asai/model/configrouter.json → 路由 / 权限(合并各模块 configrouter)
4. sys/server.json → API / WS 连接表 → $global.link
5. 各 webmodel 子文件 → $model.data / $global.sys
6. .env (VITE_*) → AES 密钥等构建期变量| 文件 | 典型路径 | 进 Git | 挂载到 |
|------|----------|--------|--------|
| cfg.js | public/webmodel/files/cfg.js | ✅ | window.$CFG → $global.$cfg |
| dirglobal.json | public/webmodel/sys/dirglobal.json | ✅ | $global.sys(合并) |
| dirmodel.json | public/webmodel/sys/dirmodel.json | ✅ | $model.data.sys |
| configrouter.json | public/webmodel/sys/asai/model/configrouter.json + 各模块 | ✅ | $global.sys.router |
| server.json | public/webmodel/sys/server.json | ✅ | $global.link.api / .ws |
| sysweb.json 等 | 由 dirglobal / dirmodel 索引 | ✅ | $global.sys.* |
| .env.development | 项目根 .env.development | ✅ 模板 | import.meta.env.VITE_* |
静态资源默认通过 AsaiModel.fetchPublic('webmodel/...') 加载(相对 webpath)。
完整配置 — cfg.js(页面级)
在 index.html 中 <script src="webmodel/files/cfg.js"> 引入:
window.$CFG = {
webpath: '/', // 静态资源根;设为 '/' 时需与构建 base 一致
title: '', // 空则 fallback 到语言包 configweb.webtit
};
window.$CFG.icon = window.$CFG.webpath + 'webmodel/files/favicon.ico';
window.$CFG.logo = window.$CFG.webpath + 'webmodel/files/logo.png';
if (window.$CFG.title) {
document.title = window.$CFG.title;
document.querySelector('link[rel="icon"]').href = window.$CFG.icon;
}| 字段 | 说明 |
|------|------|
| webpath | 静态资源前缀;影响 getWebPath()、AsSvg 等 |
| title | 浏览器标题(优先于语言包) |
| logo / icon | 由脚本派生,加载页/错误页使用 |
完整配置 — dirglobal.json(系统引导索引)
{
"dir": [
"asai/global/sysweb.json",
"asai/global/syspath.json",
"setting/settingsys.json",
"setting/settingweb.json"
]
}initweb()读取dir数组中每个 JSON,浅合并到$global.sys。- 业务项目按需增删路径;插件本身只约定
sysweb.json为核心全局项。
完整配置 — sysweb.json(全局行为,合成示例)
路径:public/webmodel/sys/asai/global/sysweb.json
{
"webver": "2.0",
"dttm": "2025-02-28 10:10:10",
"env": "dev",
"devlevel": 2,
"catcherror": 0,
"zoomid": "asaiwebzoomid",
"zoomwidth": 1920,
"zoomheight": 1200,
"tmbeat": 0,
"onweblog": true,
"onwebsitemap": false,
"onwebws": true,
"onckuseronline": true,
"onconsole": 1,
"tyrobot": "web",
"local": {
"lang": "as-lang",
"theme": "as-theme"
},
"aes": {
"lv": 1,
"aad": "asai aes aad",
"keylength": 256,
"ivlength": 12,
"algorithm": "AES-GCM"
}
}| 字段 | 说明 |
|------|------|
| devlevel | >0 时开发模式自动生成路由菜单 |
| catcherror | 1=全局 error / unhandledrejection 上报 |
| onwebws | 1=启动用户 WS(publish/web 监听) |
| onweblog | 远程客户端日志 |
| onconsole | WS/API 耗时控制台输出 |
| tyrobot | 默认机器人类型 → $fn.apisys / $fn.wssys 别名 |
| local.lang / local.theme | localStorage 键名 |
| aes.lv | 与后端 asaihost.json 的 aes.lv 对齐;>1 需 .env 密钥 |
禁止在 JSON 中写
aes.keybase64;使用VITE_ASAI_AES_KEYBASE64。
完整配置 — dirmodel.json(模型索引)
{
"dir": [
"asai/model/configrouter.json",
"asai/model/sysconfig.json",
"setting/settinglang.json",
"setting/settingweb.json"
]
}加载后 $model.data.sys.configrouter 等可被 initweb 用于路由合并。
完整配置 — configrouter.json(路由与权限,合成示例)
路径:public/webmodel/sys/asai/model/configrouter.json
各业务模块可追加 {module}/configrouter.json,rights 合并、其它字段浅合并。
{
"config": {
"index": "",
"login": "user/login",
"loading": "PageLoad",
"lv": 3
},
"rights": {
"lv0": ["testkdd", "testkdd/testindex", "user/login", "user/reg", "user/exit", "user/edit"],
"lv1": ["testkdd/testlv1"],
"lv2": ["testkdd/testlv2", "admin/userlist"],
"lv3": ["testkdd/testlv3", "admin/userlist"]
}
}| 字段 | 说明 |
|------|------|
| config.index | 默认首页 hash 段 |
| config.login | 未登录跳转 hash |
| config.loading | 加载组件名 |
| config.lv | 默认访问等级 |
| rights.lv0~lv3 | hash 路径片段列表;AsaiInitPage 计算 $global.rlv |
Hash 格式:#/模块名/路径/... → $global.location.hasharr。
完整配置 — server.json(API / WS 连接表,合成示例)
路径:public/webmodel/sys/server.json
经 startLink() / initLink() 解析为 $global.link,并缓存到 localStorage 键 as-link。
{
"servertype": 0,
"defaultws": "web",
"api": {
"default": "web",
"web": {
"url": "http://localhost:9198",
"port": 9198
},
"ai": {
"url": "http://localhost:11434"
}
},
"ws": {
"default": {
"close": 0,
"url": "ws://localhost:9198",
"port": 9198,
"sec": 1,
"worker": 0,
"config": {
"tmdeltask": 600000,
"resend": 0,
"resendmax": 10
}
},
"web": {
"close": 0,
"url": "ws://localhost:9198",
"port": 9198,
"sec": 1,
"worker": 0,
"config": {
"tmdeltask": 600000,
"resend": 0,
"resendmax": 10
}
}
}
}api / ws 条目字段
| 字段 | 说明 |
|------|------|
| url | 完整地址;也可仅 port,由 As.getUrlByCfg 拼 hostname |
| port | 端口(DEV 下 Vite 代理 /api 时不直连后端端口) |
| 字符串值 | 引用同名键,如 "weld": "default" |
| close | 1=不建连 |
| sec | 1=WS 需登录 token 才建连 |
| worker | 1=Web Worker 模式 WS |
| config.tmdeltask | wsApi 回调 Map 清理间隔(ms) |
| config.resend / resendmax | 重发策略 |
运行时用法
$fn.useApi(ujt, 'web'); // → $fn.api.web(AsaiApi 单例)
$fn.useWs(ujt, 'web'); // → $fn.ws.web(AsaiWs 单例)
$fn.api.web.apiPost('/api/user/login/auth/', body);
$fn.ws.web.wsApi({ ty: 'chat/web', id: '1', db: {} });完整配置 — .env(构建期,合成示例)
NODE_ENV=development
VITE_ENV_TYPE=development
VITE_OBFUSCATE_ENABLE=0
VITE_MAIN_JS=main
VITE_WEB_PATH=/
VITE_API_URL=/api
VITE_HTTP_HOST=localhost
VITE_HTTP_PORT=9060
VITE_HTTP_API=http://localhost:9198
VITE_DIST_DIR=../webserver/webclient/
VITE_ASAI_AES_KEYBASE64=AsaiFfQ1hMYYvT2N4Y1BhenJ0RjY0M2cxWTMZXdXMVY=| 变量 | 说明 |
|------|------|
| VITE_ASAI_AES_KEYBASE64 | 须与后端 ASAI_AES_KEYBASE64 一致 |
| VITE_HTTP_API | 参考用;DEV 实际 API 走 Vite 代理 /api |
| VITE_WEB_PATH | 构建 base,与 $CFG.webpath 对齐 |
配置 → 运行时映射
cfg.js → $global.$cfg
dirglobal.json → sysweb.json… → $global.sys
dirmodel.json → configrouter… → $model.data.sys, $global.sys.router
server.json → $global.link.api / .ws
└── useApi / useWs → $fn.api.* / $fn.ws.*
configrouter.rights → $global.rlv(访问等级)
VITE_ASAI_AES_KEYBASE64 → $global.sys.aesfns(lv>0 时)运行时上下文 ujt
安装完成后,各页面通过 inject / 全局属性访问 ujt:
| 键 | 职责 |
|----|------|
| $global | 用户、hash、link、sys、主题 |
| $fn | API/WS、As/AsCode、路由、登录 |
| $model | 模块 dirmodel、comps |
| $db / $dbwork | 模块响应式数据 |
| $ws | WS 推送(wssys) |
扩展业务模块
- 在
public/webmodel/{module}/放置configrouter.json、dirmodel.json - 将模块名加入
$model.webmodels(业务 bootstrap) - Hash 访问
#/{module}/... - 可选:
lib-install/index.ts的install(app, lib)注册$engine{module}
核心组件与指令
组件
| 组件 | 说明 |
|------|------|
| AsaiInitPage | 首屏:initweb / link / lang / WS |
| AsaiWebServer | 根容器 |
| AsaiWebModule | 模块:initAppModel + 模块 WS |
| PageLoadClient / Server / Ws / Err | 加载与错误态 |
| AsPageBusy | 全局 busy |
| PopBox / PopMsg / PopTip | 弹层与消息 |
指令(v-*)
| 指令 | 说明 |
|------|------|
| v-drag | 指针拖拽(绝对定位 translate) |
| v-longpress | 长按触发回调 |
| v-scrollbottom | 列表在底部时自动滚底 |
| v-fullscreen | 点击/双击切换目标全屏 class |
| v-userlevel | 用户等级不足时遮盖 |
| v-levelread | 无读权限时遮盖 |
| v-dbpointerdown | 300ms 内双击 pointerdown |
| v-dragzoom | 缩放场景下拖拽(弹窗标题栏) |
| v-popresizezoom | 缩放场景下右下角 resize |
| v-resizeflexwidthzoom | 拖拽分隔条调整宽高 |
开发与发布 npm 包
本地开发(插件目录)
cd webclient/src/plugs/asaihost-vue
npm install
npm run build # dist/asaihost-vue.es.js + dist/asaihost-vue.cjs + .d.ts发布到 npm
cd webclient/src/plugs/asaihost-vue
npm login # 首次需登录 npmjs.org,scope @asai 需有发布权限
npm publish --access publicprepublishOnly 会自动执行 npm run build。发布内容仅含 dist/、README.md(见 files / .npmignore)。
版本升级
npm version patch # 或 minor / major
npm publish --access publicpackage.json 要点
| 字段 | 说明 |
|------|------|
| name | asaihost-vue |
| peerDependencies.vue | ^3.4.0 |
| dependencies.@noble/ciphers | AES-GCM 纯 JS 降级 |
| exports.development | monorepo 源码 ./index.ts |
| publishConfig.access | public |
约束与后端对应
架构约束
- 禁止在插件内 cross-import 其它
plugs/* - 通过业务项目
LibInit的loadts/loadvue/loadfn与宿主耦合 - 与
@estun/asaihost-nodejs(后端)配对使用时,保持server.json/aes.lv/ 环境变量一致
与 asaihost-nodejs 的对应关系
| 前端 server.json | 后端 asaihost.json |
|------------------|-------------------|
| api.web.port 9198 | hosts.default.port 9198 |
| ws.web.port 9198 | hosts.default.ws: 1 |
| aes.lv | aes.lv(密钥均走 env,不进 JSON) |
| ws.sec: 1 | security.requireAuth + 登录 token |
配置文件树(monorepo 参考)
webclient/public/webmodel/
├── files/
│ ├── cfg.js ← window.$CFG
│ ├── logo.png
│ └── favicon.ico
└── sys/
├── dirglobal.json ← 引导索引
├── dirmodel.json ← 模型索引
├── server.json ← API/WS 连接表 ★
└── asai/
├── global/
│ └── sysweb.json ← 全局 sys ★
└── model/
├── configrouter.json ← 路由权限 ★
└── sysconfig.json配置与行为以本 README 与 useProvide.ts 中 initweb / initLink 源码为准。
