@hhhpyb/system-assistant-client 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # @hhhpyb/system-assistant-client
2
+
3
+ Nuxt 2 客户端插件:自动加载 [sa-guide-sdk](https://www.npmjs.com/package/sa-guide-sdk) bootstrap,并在路由切换后刷新指引。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install @hhhpyb/system-assistant-client
9
+ ```
10
+
11
+ ## Nuxt 2 接入
12
+
13
+ ### 1. 注册模块
14
+
15
+ `nuxt.config.js`:
16
+
17
+ ```js
18
+ export default {
19
+ modules: [
20
+ '@hhhpyb/system-assistant-client/nuxt',
21
+ ],
22
+ }
23
+ ```
24
+
25
+ 无需在 `nuxt.config.js` 中配置 `SA_GUIDE_APP_KEY`。模块会在构建时自动将应用标识注入 Nuxt 运行时配置。
26
+
27
+ 模块还会自动接入 `@hhhpyb/guide-compiler`:Nuxt 2/Bridge 的 Webpack 与 Vite 客户端构建均会在不重复挂载的前提下生成 `.nuxt/sa-guide-manifest.json`,无需在业务项目中配置 compiler loader 或 Vite plugin。
28
+
29
+ ### 应用标识推导
30
+
31
+ `SA_GUIDE_APP_KEY` 按以下优先级确定:
32
+
33
+ 1. `nuxt.config.js` 中已显式配置的 `env.SA_GUIDE_APP_KEY`;
34
+ 2. 构建环境变量 `SA_GUIDE_APP_KEY`;
35
+ 3. 业务项目根目录 `package.json` 的 `name`;
36
+ 4. 项目根目录名(构建时会输出明确警告)。
37
+
38
+ 包名会规范化为安全短标识:npm scope 会被移除,例如 `@company/ehr` 会得到 `ehr`。不会根据域名推导应用标识。
39
+
40
+ ### 可选配置
41
+
42
+ 仅在需要覆盖默认 API 或 Studio 管理后台 origin 时,在 `nuxt.config.js` 中配置:
43
+
44
+ ```js
45
+ export default {
46
+ env: {
47
+ SA_GUIDE_API_BASE: process.env.SA_GUIDE_API_BASE || 'http://127.0.0.1:8000',
48
+ SA_GUIDE_EDITOR_PARENT_ORIGIN: process.env.SA_GUIDE_EDITOR_PARENT_ORIGIN || '*',
49
+ },
50
+ }
51
+ ```
52
+
53
+ | 变量 | 说明 | 默认值 |
54
+ |------|------|--------|
55
+ | `SA_GUIDE_API_BASE` | 指引 API 根地址(可不含 `/system-assistant` 后缀) | `http://127.0.0.1:8000` |
56
+ | `SA_GUIDE_APP_KEY` | 可选的应用标识覆盖值 | 自动推导 |
57
+ | `SA_GUIDE_EDITOR_PARENT_ORIGIN` | Studio 配置态管理后台 origin | `*` |
58
+
59
+ ### Studio 配置态
60
+
61
+ URL 带 `?sa_studio=1` 时自动进入 Studio 点选模式,支持 `sa_app_key`、`sa_api`、`sa_origin` 查询参数覆盖。
62
+
63
+ ## 行为说明
64
+
65
+ - 仅客户端执行(`process.server` 时跳过)
66
+ - 从 `{apiBase}/sdk/v1/bootstrap.js` 加载 SDK
67
+ - 普通模式:调用 `SystemAssistantBootstrap.start()`
68
+ - 路由 `afterEach` 后自动调用 `SystemAssistant.checkAllContexts()` 刷新指引
69
+
70
+ ## 发布(维护者)
71
+
72
+ 源码:`system-assistant/deployables/sa-guide-sdk/app/v1/system-assistant.client.js`
73
+
74
+ ```bash
75
+ cd packages/system-assistant-client
76
+
77
+ # 1. 更新 sa-guide-sdk/app/v1/system-assistant.client.js 中的 SA_GUIDE_ASSET_VERSION
78
+ # 2. 同步 package.json version
79
+ npm run build
80
+ npm login
81
+ npm publish --access public --registry=<npm-registry>
82
+ ```
83
+
84
+ ## 许可证
85
+
86
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,87 @@
1
+ const DEFAULT_API_BASE = 'http://127.0.0.1:8000';
2
+ const DEFAULT_APP_KEY = 'ehr';
3
+ const SA_GUIDE_ASSET_VERSION = '1.3.9';
4
+
5
+ function normalizeApiBase(apiBase) {
6
+ const raw = (apiBase || DEFAULT_API_BASE).replace(/\/$/, '');
7
+ return raw.endsWith('/system-assistant') ? raw : `${raw}/system-assistant`;
8
+ }
9
+
10
+ function isStudioMode() {
11
+ const params = new URLSearchParams(window.location.search);
12
+ return params.get('sa_studio') === '1' || params.get('sa_studio') === 'true';
13
+ }
14
+
15
+ function loadBootstrap(apiBase) {
16
+ return new Promise((resolve, reject) => {
17
+ if (window.SystemAssistantBootstrap) {
18
+ resolve(window.SystemAssistantBootstrap);
19
+ return;
20
+ }
21
+
22
+ const existing = document.querySelector('script[data-sa-guide-bootstrap="1"]');
23
+ if (existing) {
24
+ existing.addEventListener('load', () => resolve(window.SystemAssistantBootstrap));
25
+ existing.addEventListener('error', reject);
26
+ return;
27
+ }
28
+
29
+ const script = document.createElement('script');
30
+ script.src = `${apiBase}/sdk/v1/bootstrap.js?v=${SA_GUIDE_ASSET_VERSION}`;
31
+ script.async = true;
32
+ script.dataset.saGuideBootstrap = '1';
33
+ script.onload = () => resolve(window.SystemAssistantBootstrap);
34
+ script.onerror = reject;
35
+ document.head.appendChild(script);
36
+ });
37
+ }
38
+
39
+ export default async function systemAssistantPlugin({ app, $config }) {
40
+ if (process.server) return;
41
+
42
+ const apiBase = normalizeApiBase($config && $config.SA_GUIDE_API_BASE);
43
+ const appKey = ($config && $config.SA_GUIDE_APP_KEY) || DEFAULT_APP_KEY;
44
+ const editorParentOrigin = ($config && $config.SA_GUIDE_EDITOR_PARENT_ORIGIN) || '*';
45
+
46
+ try {
47
+ window.SA_APP_KEY = appKey;
48
+ window.SA_WATCH_IFRAME = true;
49
+
50
+ const bootstrap = await loadBootstrap(apiBase);
51
+
52
+ const startStudio = async () => {
53
+ if (!isStudioMode()) return;
54
+ const params = new URLSearchParams(window.location.search);
55
+ const sdk = await bootstrap.loadSdk();
56
+ await sdk.startStudio({
57
+ appKey: params.get('sa_app_key') || appKey,
58
+ apiBase: params.get('sa_api') || apiBase,
59
+ adminOrigin: params.get('sa_origin') || editorParentOrigin,
60
+ });
61
+ };
62
+
63
+ if (isStudioMode()) {
64
+ await startStudio();
65
+ } else {
66
+ await bootstrap.start({
67
+ appKey,
68
+ apiBase,
69
+ watchIframe: true,
70
+ });
71
+ }
72
+
73
+ if (app.router) {
74
+ app.router.afterEach(() => {
75
+ window.setTimeout(() => {
76
+ if (isStudioMode()) {
77
+ startStudio();
78
+ return;
79
+ }
80
+ window.SystemAssistant && window.SystemAssistant.checkAllContexts && window.SystemAssistant.checkAllContexts();
81
+ }, 300);
82
+ });
83
+ }
84
+ } catch (error) {
85
+ console.warn('[SystemAssistant] SDK load failed', error);
86
+ }
87
+ }
package/nuxt.cjs ADDED
@@ -0,0 +1,127 @@
1
+ const { resolve } = require('node:path')
2
+ const { readFileSync } = require('node:fs')
3
+ const setupGuideCompilerNuxt2 = require('@hhhpyb/guide-compiler/nuxt2')
4
+
5
+ const APP_KEY_ENV = 'SA_GUIDE_APP_KEY'
6
+ const GUIDE_COMPILER_WEBPACK_MARKER = Symbol.for('system-assistant.guide-compiler.webpack')
7
+ const GUIDE_COMPILER_VITE_MARKER = Symbol.for('system-assistant.guide-compiler.vite')
8
+
9
+ function normalizeAppKey(value) {
10
+ if (typeof value !== 'string') return ''
11
+
12
+ const packageName = value.trim().replace(/^@[^/]+\//, '')
13
+ return packageName
14
+ .toLowerCase()
15
+ .replace(/[^a-z0-9]+/g, '-')
16
+ .replace(/^-+|-+$/g, '')
17
+ .slice(0, 64)
18
+ }
19
+
20
+ function readProvidedAppKey(value) {
21
+ return typeof value === 'string' ? value.trim() : ''
22
+ }
23
+
24
+ function readPackageName(rootDir) {
25
+ try {
26
+ const packageJson = JSON.parse(readFileSync(resolve(rootDir, 'package.json'), 'utf8'))
27
+ return normalizeAppKey(packageJson.name)
28
+ } catch (_error) {
29
+ return ''
30
+ }
31
+ }
32
+
33
+ function resolveAppKey({ configuredAppKey, environmentAppKey, rootDir }) {
34
+ const explicitAppKey = readProvidedAppKey(configuredAppKey)
35
+ if (explicitAppKey) return { appKey: explicitAppKey, source: 'configured' }
36
+
37
+ const envAppKey = readProvidedAppKey(environmentAppKey)
38
+ if (envAppKey) return { appKey: envAppKey, source: 'environment' }
39
+
40
+ const packageAppKey = readPackageName(rootDir)
41
+ if (packageAppKey) return { appKey: packageAppKey, source: 'package' }
42
+
43
+ return { appKey: normalizeAppKey(rootDir.split(/[\\/]/).filter(Boolean).pop()) || 'app', source: 'directory' }
44
+ }
45
+
46
+ function createGuideCompilerOptions(rootDir, appKey) {
47
+ return {
48
+ enabled: true,
49
+ appKey,
50
+ idPrefix: appKey,
51
+ rootDir,
52
+ include: ['pages', 'components', 'layouts'],
53
+ exclude: ['node_modules', '.nuxt', '.output'],
54
+ manifestOutput: resolve(rootDir, '.nuxt/sa-guide-manifest.json'),
55
+ manifestAsset: 'sa-guide-manifest.json',
56
+ productionDuplicatePolicy: 'block_manual',
57
+ sensitiveWords: ['薪资', '工资', '金额', '审批结论', '身份证', '手机号'],
58
+ }
59
+ }
60
+
61
+ function installGuideCompilerWebpack(config, options) {
62
+ if (!config || config[GUIDE_COMPILER_WEBPACK_MARKER]) return config
63
+ setupGuideCompilerNuxt2(config, options)
64
+ Object.defineProperty(config, GUIDE_COMPILER_WEBPACK_MARKER, { value: true })
65
+ return config
66
+ }
67
+
68
+ async function installGuideCompilerVite(config, options) {
69
+ if (!config || config[GUIDE_COMPILER_VITE_MARKER]) return config
70
+ const { systemAssistantGuideVitePlugin } = await import('@hhhpyb/guide-compiler/vite')
71
+ config.plugins = config.plugins || []
72
+ if (!config.plugins.some((plugin) => plugin && plugin.name === 'system-assistant-guide-compiler')) {
73
+ config.plugins.push(systemAssistantGuideVitePlugin(options))
74
+ }
75
+ Object.defineProperty(config, GUIDE_COMPILER_VITE_MARKER, { value: true })
76
+ return config
77
+ }
78
+
79
+ module.exports = function systemAssistantClientModule() {
80
+ const rootDir = this.options.rootDir || process.cwd()
81
+ const env = this.options.env || (this.options.env = {})
82
+ const result = resolveAppKey({
83
+ configuredAppKey: env[APP_KEY_ENV],
84
+ environmentAppKey: process.env[APP_KEY_ENV],
85
+ rootDir,
86
+ })
87
+
88
+ env[APP_KEY_ENV] = result.appKey
89
+ const guideCompilerOptions = createGuideCompilerOptions(rootDir, result.appKey)
90
+
91
+ if (this.nuxt && typeof this.nuxt.hook === 'function') {
92
+ this.nuxt.hook('webpack:config', (config) => {
93
+ installGuideCompilerWebpack(config, guideCompilerOptions)
94
+ })
95
+ this.nuxt.hook('vite:extendConfig', async (config, context) => {
96
+ if (!context || context.isClient !== true) return
97
+ await installGuideCompilerVite(config, guideCompilerOptions)
98
+ })
99
+ }
100
+
101
+ if (result.source === 'directory') {
102
+ // Nuxt builds can still proceed when a project omits package.json.name, but
103
+ // the derived key is less stable than a package name and must be visible.
104
+ // eslint-disable-next-line no-console
105
+ console.warn(`[system-assistant-client] package.json name is unavailable; using directory name as SA_GUIDE_APP_KEY: ${result.appKey}`)
106
+ }
107
+
108
+ this.addPlugin({
109
+ src: resolve(__dirname, 'dist/index.js'),
110
+ fileName: 'system-assistant.client.js',
111
+ mode: 'client',
112
+ })
113
+ }
114
+
115
+ module.exports.meta = {
116
+ name: '@hhhpyb/system-assistant-client',
117
+ }
118
+
119
+ module.exports._internal = {
120
+ normalizeAppKey,
121
+ readProvidedAppKey,
122
+ readPackageName,
123
+ resolveAppKey,
124
+ createGuideCompilerOptions,
125
+ installGuideCompilerWebpack,
126
+ installGuideCompilerVite,
127
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@hhhpyb/system-assistant-client",
3
+ "version": "1.3.6",
4
+ "description": "Nuxt 2 client plugin for System Assistant smart guide SDK",
5
+ "keywords": [
6
+ "nuxt",
7
+ "nuxt2",
8
+ "guide",
9
+ "system-assistant",
10
+ "plugin"
11
+ ],
12
+ "license": "MIT",
13
+ "type": "module",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "http://git.ymdd.tech/twg195158/smart-guide-assistant.git",
17
+ "directory": "system-assistant-front/packages/system-assistant-client"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "nuxt.cjs"
23
+ ],
24
+ "exports": {
25
+ ".": "./dist/index.js",
26
+ "./nuxt": "./nuxt.cjs"
27
+ },
28
+ "peerDependencies": {
29
+ "nuxt": "^2.0.0"
30
+ },
31
+ "peerDependenciesMeta": {
32
+ "nuxt": {
33
+ "optional": true
34
+ }
35
+ },
36
+ "dependencies": {
37
+ "@hhhpyb/guide-compiler": "0.1.0"
38
+ },
39
+ "scripts": {
40
+ "build": "node scripts/copy-dist.js",
41
+ "test": "node --test test/nuxt.test.cjs",
42
+ "prepublishOnly": "npm run build"
43
+ }
44
+ }