asaihost-vue
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 等指令
目录
- 快速开始
- 在 AsaiCMS monorepo 内使用
- 独立项目集成
- LibInit 与 install 约定
- 配置文件总览
- 运行时上下文 ujt
- 扩展业务模块
- 核心组件与指令
- 开发与发布 npm 包
- 约束与后端对应
快速开始
安装
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 public
prepublishOnly 会自动执行 npm run build。发布内容仅含 dist/、README.md(见 files / .npmignore)。
版本升级
npm version patch # 或 minor / major
npm publish --access public
package.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
测试
# 本插件
npx tsx --test .youmengyu/test/unit/webclient/plugs/asaihost-vue/*.test.mjs
# 仓库全量(含全部 plugs + webserver)
node .youmengyu/test/asaitest.mjs
# 报告:.youmengyu/test/reports/latest/report.html
覆盖:routeAccess ACL、loginConflict 恢复、secureCompare/cookie、userLevels、WS cascade、AsaiWs init/resend 守卫。
配置与行为以本 README 与 useProvide.ts 中 initweb / initLink 源码为准。
Related Packages
Plugin-like lifecycle hook system for delivering shared functionality to host ap...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.0.22 | ^3.5.22 | ISC | |
| 0.0.21 | ^3.5.22 | ISC | |
| 0.0.18 | ^3.5.22 | ISC | |
| 0.0.17 | ^3.5.22 | ISC | |
| 0.0.16 | ^3.5.22 | ISC | |
| 0.0.15 | ^3.5.22 | ISC | |
| 0.0.14 | ^3.5.22 | ISC | |
| 0.0.13 | ^3.5.22 | ISC | |
| 0.0.12 | ^3.5.22 | ISC | |
| 0.0.11 | ^3.5.22 | ISC | |
| 0.0.10 | ^3.5.22 | ISC | |
| 0.0.9 | ^3.5.22 | ISC | |
| 0.0.8 | ^3.5.22 | ISC | |
| 0.0.7 | ^3.5.22 | ISC | |
| 0.0.6 | ^3.5.22 | ISC | |
| 0.0.5 | ^3.5.22 | ISC | |
| 0.0.4 | ^3.5.22 | ISC | |
| 0.0.3 | ^3.5.22 | ISC | |
| 0.0.2 | ^3.5.22 | ISC | |
| 0.0.1 | ^3.5.22 | ISC |