@h-ai/cli 0.1.0-alpha.20 → 0.1.0-alpha.21
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 +10 -7
- package/dist/{chunk-GSMXGUYF.js → chunk-5IGMJVV5.js} +56 -38
- package/dist/chunk-5IGMJVV5.js.map +1 -0
- package/dist/{chunk-3BBXDQ4Y.js → chunk-CFCXOKGV.js} +24 -2
- package/dist/chunk-CFCXOKGV.js.map +1 -0
- package/dist/cli-config-templates-5J5VKWWD.js +5 -0
- package/dist/{cli-config-templates-IGGO7P45.js.map → cli-config-templates-5J5VKWWD.js.map} +1 -1
- package/dist/cli-skill-templates-JMSV2SVW.js +5 -0
- package/dist/{cli-skill-templates-IMYZPQRG.js.map → cli-skill-templates-JMSV2SVW.js.map} +1 -1
- package/dist/index.js +567 -75
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/templates/README.md +40 -29
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +38 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +33 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +3 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +12 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
- package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
- package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +17 -0
- package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +19 -0
- package/templates/apps/api/apps/{{projectName}}-service/config/_serv.yml.hbs +26 -0
- package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +55 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +98 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +21 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +184 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/app-procedures.ts.hbs +49 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/index.ts.hbs +18 -0
- package/templates/apps/api/apps/{{projectName}}-service/tests/service.test.ts.hbs +168 -0
- package/templates/apps/api/apps/{{projectName}}-service/tsconfig.json.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-service/tsup.config.ts.hbs +11 -0
- package/templates/apps/api/apps/{{projectName}}-service/vitest.config.ts.hbs +9 -0
- package/templates/apps/api/e2e/api-service.spec.ts.hbs +18 -0
- package/templates/apps/api/eslint.config.js +32 -0
- package/templates/apps/api/package.json.hbs +29 -0
- package/templates/apps/api/playwright.config.ts.hbs +58 -0
- package/templates/apps/api/pnpm-workspace.yaml.hbs +14 -0
- package/templates/apps/api/tsconfig.base.json +15 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +24 -7
- package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +51 -29
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +186 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +2 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +1 -5
- package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +10 -4
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +4 -3
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +20 -6
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +15 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +33 -30
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +152 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +1 -2
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +13 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +41 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +2 -8
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +9 -4
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +44 -21
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +15 -6
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +15 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +25 -27
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +153 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +1 -5
- package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +10 -4
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +3 -2
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +2 -1
- package/templates/apps/fullstack/eslint.config.js +0 -1
- package/templates/apps/fullstack/package.json.hbs +18 -17
- package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +3 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +2 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +2 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/{server-app.test.ts.hbs → app-server.test.ts.hbs} +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +9 -8
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +5 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +1 -1
- package/templates/apps/fullstack/playwright.config.ts.hbs +41 -4
- package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +15 -0
- package/templates/apps/mobile-app/.env.hbs +3 -0
- package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
- package/templates/apps/mobile-app/index.html.hbs +13 -0
- package/templates/apps/mobile-app/messages/en-US.json +36 -0
- package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
- package/templates/apps/mobile-app/src/App.svelte.hbs +162 -0
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +54 -0
- package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +5 -6
- package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
- package/templates/base/.gitignore.hbs +16 -0
- package/templates/base/{eslint.config.js → eslint.config.js.hbs} +4 -1
- package/templates/base/package.json.hbs +52 -33
- package/templates/base/playwright.config.ts +30 -3
- package/templates/base/pnpm-workspace.yaml.hbs +14 -0
- package/templates/base/src/app.d.ts.hbs +3 -0
- package/templates/base/src/app.html.hbs +3 -0
- package/templates/base/svelte.config.js.hbs +43 -3
- package/templates/base/tests/scaffold.test.ts.hbs +7 -0
- package/templates/base/tsconfig.json.hbs +50 -0
- package/templates/base/vite.config.ts.hbs +10 -0
- package/templates/skills/AGENTS.md +57 -24
- package/templates/skills/CLAUDE.md +18 -7
- package/templates/skills/bridges/admin/AGENTS.md +66 -0
- package/templates/skills/bridges/admin/CLAUDE.md +19 -0
- package/templates/skills/bridges/admin/copilot-instructions.md +46 -0
- package/templates/skills/bridges/api/AGENTS.md +65 -0
- package/templates/skills/bridges/api/CLAUDE.md +19 -0
- package/templates/skills/bridges/api/copilot-instructions.md +46 -0
- package/templates/skills/bridges/fullstack/AGENTS.md +84 -0
- package/templates/skills/bridges/fullstack/CLAUDE.md +19 -0
- package/templates/skills/bridges/fullstack/copilot-instructions.md +54 -0
- package/templates/skills/bridges/h5/AGENTS.md +65 -0
- package/templates/skills/bridges/h5/CLAUDE.md +19 -0
- package/templates/skills/bridges/h5/copilot-instructions.md +44 -0
- package/templates/skills/bridges/mobile-app/AGENTS.md +77 -0
- package/templates/skills/bridges/mobile-app/CLAUDE.md +19 -0
- package/templates/skills/bridges/mobile-app/copilot-instructions.md +45 -0
- package/templates/skills/bridges/website/AGENTS.md +65 -0
- package/templates/skills/bridges/website/CLAUDE.md +19 -0
- package/templates/skills/bridges/website/copilot-instructions.md +44 -0
- package/templates/skills/copilot-instructions.md +27 -64
- package/templates/skills/hai-app-create/SKILL.md +1 -0
- package/templates/skills/hai-app-review/SKILL.md +1 -1
- package/templates/skills/hai-app-tests/SKILL.md +28 -3
- package/templates/skills/hai-capacitor/SKILL.md +14 -22
- package/templates/skills/opencode.json +1 -6
- package/dist/chunk-3BBXDQ4Y.js.map +0 -1
- package/dist/chunk-GSMXGUYF.js.map +0 -1
- package/dist/cli-config-templates-IGGO7P45.js +0 -5
- package/dist/cli-skill-templates-IMYZPQRG.js +0 -5
- package/templates/apps/android-app/.env.hbs +0 -3
- package/templates/apps/android-app/messages/en-US.json +0 -24
- package/templates/apps/android-app/messages/zh-CN.json +0 -24
- package/templates/apps/android-app/src/lib/api.ts.hbs +0 -32
- package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -43
- package/templates/apps/android-app/src/routes/+layout.ts +0 -7
- package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -38
- package/templates/apps/api/src/routes/+layout.svelte +0 -14
- package/templates/apps/api/src/routes/+page.svelte +0 -11
- package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
- package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
- package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
- package/templates/apps/api/tests/health.test.ts.hbs +0 -26
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.html.hbs +0 -14
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+layout.svelte.hbs +0 -18
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+page.svelte.hbs +0 -162
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.html.hbs +0 -14
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+layout.svelte.hbs +0 -18
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+page.svelte.hbs +0 -162
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.html.hbs +0 -14
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+layout.svelte.hbs +0 -18
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+page.svelte.hbs +0 -162
- package/templates/apps/fullstack/pnpm-workspace.yaml +0 -7
- package/templates/base/tsconfig.json +0 -20
- /package/templates/apps/fullstack/packages/{{projectName}}-serv/src/{server-app.ts.hbs → app-server.ts.hbs} +0 -0
- /package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/{theme.svelte.ts.hbs → theme-store.svelte.ts.hbs} +0 -0
|
@@ -2,20 +2,37 @@
|
|
|
2
2
|
{{#if fullstack.frontends.app}}
|
|
3
3
|
# {{projectName}}-app
|
|
4
4
|
|
|
5
|
-
App/H5
|
|
5
|
+
App/H5 前端工程,参考 `apps/mobile-app` 的移动端 UI 风格,使用 Svelte 5 + Vite + Capacitor,可输出 Web 预览并同步 Android / iOS 原生工程。
|
|
6
6
|
|
|
7
7
|
## i18n 与 shared 协同
|
|
8
8
|
|
|
9
9
|
- 本端页面文案:`messages/{locale}.json` + `project.inlang/settings.json`
|
|
10
10
|
- 共享 Shell/主题/语言/API:`packages/{{fullstack.sharedPackageName}}`
|
|
11
|
-
-
|
|
11
|
+
- 语言切换通过 shared runtime 与本端 `src/lib/paraglide/runtime.js` 同步。
|
|
12
|
+
- 设置 tab 默认集成 shared 的 `ThemeSwitcher` / `LanguageSwitcher`,可直接验证主题与语言同步。
|
|
12
13
|
|
|
13
14
|
自定义建议:移动端独有引导、运营位、按钮文案放在本目录 `messages/`;跨端通用组件放到 shared。
|
|
14
15
|
|
|
15
|
-
##
|
|
16
|
+
## 编译、打包与部署
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
```bash
|
|
19
|
+
# 开发预览,默认端口 {{fullstack.ports.app}}
|
|
20
|
+
pnpm --filter {{projectName}}-app dev
|
|
21
|
+
|
|
22
|
+
# 编译静态 SPA 产物到 dist/
|
|
23
|
+
pnpm --filter {{projectName}}-app build
|
|
24
|
+
|
|
25
|
+
# 同步原生工程;首次使用前按需执行 cap:add:android / cap:add:ios
|
|
26
|
+
pnpm --filter {{projectName}}-app package
|
|
27
|
+
|
|
28
|
+
# Android / iOS 原生打包
|
|
29
|
+
pnpm --filter {{projectName}}-app cap:build:android:debug
|
|
30
|
+
pnpm --filter {{projectName}}-app cap:build:android:release
|
|
31
|
+
pnpm --filter {{projectName}}-app cap:build:ios
|
|
32
|
+
|
|
33
|
+
# 当前模板的 deploy 入口默认执行 package,可按目标商店或 CI 平台替换
|
|
34
|
+
pnpm --filter {{projectName}}-app deploy
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
部署前确认 `PUBLIC_API_BASE` 在 `.env` 中指向可访问的后端服务。Android 模拟器访问宿主机通常使用 `http://10.0.2.2:3000`。
|
|
21
38
|
{{/if}}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#if fullstack.frontends.app}}
|
|
3
|
+
import type { CapacitorConfig } from '@capacitor/cli'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
|
|
6
|
+
const config: CapacitorConfig = {
|
|
7
|
+
appId: 'com.hai.{{fullstack.nativeAppIdSegment}}.app',
|
|
8
|
+
appName: '{{projectName}} App',
|
|
9
|
+
webDir: 'dist',
|
|
10
|
+
server: {
|
|
11
|
+
// 仅用于 Capacitor live reload 前端页面;API 地址由前端配置或 shared client 参数控制。
|
|
12
|
+
url: process.env.CAPACITOR_SERVER_URL,
|
|
13
|
+
cleartext: process.env.CAPACITOR_SERVER_URL?.startsWith('http://') ?? false,
|
|
14
|
+
},
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default config
|
|
18
|
+
{{/if}}
|
|
@@ -4,7 +4,7 @@ import antfu from '@antfu/eslint-config'
|
|
|
4
4
|
|
|
5
5
|
export default antfu({
|
|
6
6
|
formatters: true,
|
|
7
|
-
ignores: ['
|
|
7
|
+
ignores: ['**/build/**', '**/dist/**', '**/*.d.ts', '**/project.inlang/**', '**/src/lib/paraglide/**'],
|
|
8
8
|
svelte: true,
|
|
9
9
|
}, {
|
|
10
10
|
files: ['**/*.ts', '**/*.svelte'],
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#if fullstack.frontends.app}}
|
|
3
|
+
<!doctype html>
|
|
4
|
+
<html lang="{{fullstack.i18n.baseLocale}}">
|
|
5
|
+
<head>
|
|
6
|
+
<meta charset="UTF-8" />
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
8
|
+
<meta name="theme-color" content="#2563eb" />
|
|
9
|
+
<title>{{projectName}} App</title>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="app"></div>
|
|
13
|
+
<script type="module" src="/src/main.ts"></script>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
16
|
+
{{/if}}
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
|
5
5
|
"page_title": "{name} · App",
|
|
6
6
|
"platform_name": "App/H5",
|
|
7
|
+
"nav_workspace": "Workspace",
|
|
8
|
+
"nav_status": "Status",
|
|
9
|
+
"nav_settings": "Settings",
|
|
10
|
+
"settings_description": "Switch theme and language here to verify shared theme and i18n state take effect instantly on mobile.",
|
|
11
|
+
"settings_theme_description": "Theme switching reuses the shared theme store and persists the preference on the device.",
|
|
12
|
+
"settings_language_description": "Language switching keeps the shared runtime and the app runtime in sync.",
|
|
7
13
|
"hero_badge": "Mobile workspace",
|
|
8
14
|
"hero_title": "{name} App Experience",
|
|
9
15
|
"hero_subtitle": "A mobile and H5 oriented entry point. This app keeps its own messages so onboarding and campaign copy can evolve independently.",
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
|
5
5
|
"page_title": "{name} · App",
|
|
6
6
|
"platform_name": "App/H5",
|
|
7
|
+
"nav_workspace": "工作台",
|
|
8
|
+
"nav_status": "状态",
|
|
9
|
+
"nav_settings": "设置",
|
|
10
|
+
"settings_description": "在这里切换主题与语言,验证 shared 的主题与 i18n 在移动端即时生效。",
|
|
11
|
+
"settings_theme_description": "主题切换复用 shared theme store,并将偏好持久化到本地设备。",
|
|
12
|
+
"settings_language_description": "语言切换会同时同步 shared runtime 与当前 App runtime。",
|
|
7
13
|
"hero_badge": "移动端工作台",
|
|
8
14
|
"hero_title": "{name} App 体验",
|
|
9
15
|
"hero_subtitle": "面向移动端与 H5 场景的轻量入口,保留本端 messages 以便独立调整文案、引导语和运营内容。",
|
|
@@ -9,42 +9,64 @@
|
|
|
9
9
|
"paraglide:compile": "paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide",
|
|
10
10
|
"paraglide:watch": "paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide --watch",
|
|
11
11
|
"dev": "vite dev --host 127.0.0.1 --port {{fullstack.ports.app}}",
|
|
12
|
-
"build": "vite build",
|
|
12
|
+
"build": "pnpm paraglide:compile && vite build",
|
|
13
|
+
"package": "pnpm cap:sync",
|
|
14
|
+
"deploy": "pnpm package",
|
|
13
15
|
"preview": "vite preview --host 127.0.0.1 --port {{fullstack.ports.app}} --strictPort",
|
|
14
|
-
"typecheck": "pnpm paraglide:compile && svelte-
|
|
16
|
+
"typecheck": "pnpm paraglide:compile && svelte-check --tsconfig ./tsconfig.json",
|
|
15
17
|
"lint": "eslint .",
|
|
16
|
-
"test": "vitest run",
|
|
17
|
-
"test:watch": "vitest",
|
|
18
|
-
"clean": "rimraf
|
|
18
|
+
"test": "pnpm paraglide:compile && vitest run",
|
|
19
|
+
"test:watch": "pnpm paraglide:compile && vitest",
|
|
20
|
+
"clean": "rimraf dist build android ios .turbo src/lib/paraglide",
|
|
21
|
+
"cap:add:android": "cap add android",
|
|
22
|
+
"cap:add:ios": "cap add ios",
|
|
23
|
+
"cap:sync": "pnpm build && cap sync",
|
|
24
|
+
"cap:sync:android": "pnpm build && cap sync android",
|
|
25
|
+
"cap:sync:ios": "pnpm build && cap sync ios",
|
|
26
|
+
"cap:android": "cap open android",
|
|
27
|
+
"cap:ios": "cap open ios",
|
|
28
|
+
"cap:run:android": "cap run android",
|
|
29
|
+
"cap:run:ios": "cap run ios",
|
|
30
|
+
"cap:build:android:debug": "pnpm build && cap sync android && cd android && gradlew.bat assembleDebug",
|
|
31
|
+
"cap:build:android:release": "pnpm build && cap sync android && cap build android --androidreleasetype APK",
|
|
32
|
+
"cap:build:ios": "pnpm build && cap sync ios && cap build ios"
|
|
19
33
|
},
|
|
20
34
|
"dependencies": {
|
|
21
|
-
"@h-ai/
|
|
22
|
-
"@h-ai/ui": "{{
|
|
23
|
-
"{{fullstack.contractPackageName}}": "workspace:*",
|
|
35
|
+
"@h-ai/capacitor": "{{haiPackageSpecifier}}",
|
|
36
|
+
"@h-ai/ui": "{{haiPackageSpecifier}}",
|
|
24
37
|
"{{fullstack.sharedPackageName}}": "workspace:*"
|
|
25
38
|
},
|
|
26
39
|
"devDependencies": {
|
|
27
|
-
"@antfu/eslint-config": "{{fullstack.
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
30
|
-
"@
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"tailwindcss": "{{fullstack.
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
40
|
+
"@antfu/eslint-config": "{{fullstack.packageSpecifiers.antfuEslintConfig}}",
|
|
41
|
+
"@aparajita/capacitor-secure-storage": "{{fullstack.packageSpecifiers.capacitorSecureStorage}}",
|
|
42
|
+
"@capacitor/android": "{{fullstack.packageSpecifiers.capacitorAndroid}}",
|
|
43
|
+
"@capacitor/app": "{{fullstack.packageSpecifiers.capacitorApp}}",
|
|
44
|
+
"@capacitor/camera": "{{fullstack.packageSpecifiers.capacitorCamera}}",
|
|
45
|
+
"@capacitor/cli": "{{fullstack.packageSpecifiers.capacitorCli}}",
|
|
46
|
+
"@capacitor/core": "{{fullstack.packageSpecifiers.capacitorCore}}",
|
|
47
|
+
"@capacitor/device": "{{fullstack.packageSpecifiers.capacitorDevice}}",
|
|
48
|
+
"@capacitor/ios": "{{fullstack.packageSpecifiers.capacitorIos}}",
|
|
49
|
+
"@capacitor/preferences": "{{fullstack.packageSpecifiers.capacitorPreferences}}",
|
|
50
|
+
"@capacitor/push-notifications": "{{fullstack.packageSpecifiers.capacitorPushNotifications}}",
|
|
51
|
+
"@capacitor/status-bar": "{{fullstack.packageSpecifiers.capacitorStatusBar}}",
|
|
52
|
+
"@iconify-json/tabler": "{{fullstack.packageSpecifiers.iconifyJsonTabler}}",
|
|
53
|
+
"@iconify/tailwind4": "{{fullstack.packageSpecifiers.iconifyTailwind}}",
|
|
54
|
+
"@inlang/paraglide-js": "{{fullstack.packageSpecifiers.inlangParaglide}}",
|
|
55
|
+
"@inlang/plugin-message-format": "{{fullstack.packageSpecifiers.inlangMessageFormat}}",
|
|
56
|
+
"@sveltejs/vite-plugin-svelte": "{{fullstack.packageSpecifiers.sveltePlugin}}",
|
|
57
|
+
"@tailwindcss/vite": "{{fullstack.packageSpecifiers.tailwindcssVite}}",
|
|
58
|
+
"bits-ui": "{{fullstack.packageSpecifiers.bitsUi}}",
|
|
59
|
+
"daisyui": "{{fullstack.packageSpecifiers.daisyui}}",
|
|
60
|
+
"eslint": "{{fullstack.packageSpecifiers.eslint}}",
|
|
61
|
+
"eslint-plugin-format": "{{fullstack.packageSpecifiers.eslintPluginFormat}}",
|
|
62
|
+
"eslint-plugin-svelte": "{{fullstack.packageSpecifiers.eslintPluginSvelte}}",
|
|
63
|
+
"svelte": "{{fullstack.packageSpecifiers.svelte}}",
|
|
64
|
+
"svelte-check": "{{fullstack.packageSpecifiers.svelteCheck}}",
|
|
65
|
+
"svelte-eslint-parser": "{{fullstack.packageSpecifiers.svelteEslintParser}}",
|
|
66
|
+
"tailwindcss": "{{fullstack.packageSpecifiers.tailwindcss}}",
|
|
67
|
+
"typescript": "{{fullstack.packageSpecifiers.typescript}}",
|
|
68
|
+
"vite": "{{fullstack.packageSpecifiers.vite}}",
|
|
69
|
+
"vitest": "{{fullstack.packageSpecifiers.vitest}}"
|
|
48
70
|
}
|
|
49
71
|
}
|
|
50
72
|
{{/if}}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#if fullstack.frontends.app}}
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import type { AppInfo } from '{{fullstack.sharedPackageName}}'
|
|
5
|
+
import * as appM from './lib/paraglide/messages.js'
|
|
6
|
+
import { setLocale } from './lib/paraglide/runtime.js'
|
|
7
|
+
import { Alert, Button, Card, Skeleton } from '@h-ai/ui'
|
|
8
|
+
import { onMount } from 'svelte'
|
|
9
|
+
import {
|
|
10
|
+
fetchAppInfo,
|
|
11
|
+
getLocale as getSharedLocale,
|
|
12
|
+
LanguageSwitcher,
|
|
13
|
+
messages as sharedM,
|
|
14
|
+
ThemeSwitcher,
|
|
15
|
+
} from '{{fullstack.sharedPackageName}}'
|
|
16
|
+
import { initCapacitor } from './lib/capacitor.js'
|
|
17
|
+
|
|
18
|
+
type TabId = 'workspace' | 'status' | 'settings'
|
|
19
|
+
|
|
20
|
+
let info = $state<AppInfo | null>(null)
|
|
21
|
+
let loading = $state(true)
|
|
22
|
+
let errorMessage = $state('')
|
|
23
|
+
let activeTab = $state<TabId>('workspace')
|
|
24
|
+
|
|
25
|
+
const navItems = $derived([
|
|
26
|
+
{ id: 'workspace', label: appM.nav_workspace(), iconClass: 'icon-[tabler--layout-dashboard]' },
|
|
27
|
+
{ id: 'status', label: appM.nav_status(), iconClass: 'icon-[tabler--activity-heartbeat]' },
|
|
28
|
+
{ id: 'settings', label: appM.nav_settings(), iconClass: 'icon-[tabler--settings]' },
|
|
29
|
+
])
|
|
30
|
+
|
|
31
|
+
function syncLocale(locale: string) {
|
|
32
|
+
setLocale(locale as Parameters<typeof setLocale>[0])
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function handleTabChange(id: string): void {
|
|
36
|
+
if (id === 'workspace' || id === 'status' || id === 'settings')
|
|
37
|
+
activeTab = id
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function refreshStatus() {
|
|
41
|
+
loading = true
|
|
42
|
+
errorMessage = ''
|
|
43
|
+
try {
|
|
44
|
+
info = await fetchAppInfo({ clientName: '{{projectName}}-app' })
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
info = null
|
|
48
|
+
errorMessage = sharedM.home_error()
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
loading = false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
onMount(() => {
|
|
56
|
+
document.title = appM.page_title({ name: sharedM.app_name() })
|
|
57
|
+
syncLocale(getSharedLocale())
|
|
58
|
+
void initCapacitor()
|
|
59
|
+
void refreshStatus()
|
|
60
|
+
})
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<div class="hai-mobile-viewport">
|
|
64
|
+
<div class="hai-mobile-shell max-w-lg">
|
|
65
|
+
<AppBar title={sharedM.app_name()} safeArea fixed={false} class="bg-base-100/95 backdrop-blur border-base-content/8" />
|
|
66
|
+
|
|
67
|
+
<main class="hai-mobile-main">
|
|
68
|
+
{#if activeTab === 'workspace'}
|
|
69
|
+
<section class="space-y-4 p-4 pb-6">
|
|
70
|
+
<div class="bg-primary text-primary-content rounded-2xl p-5 shadow-sm">
|
|
71
|
+
<p class="text-sm opacity-75">{appM.hero_badge()}</p>
|
|
72
|
+
<h1 class="mt-1 text-2xl font-bold">{appM.hero_title({ name: sharedM.app_name() })}</h1>
|
|
73
|
+
<p class="mt-2 text-sm opacity-80">{appM.hero_subtitle()}</p>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="grid grid-cols-2 gap-3">
|
|
77
|
+
<Card padding="sm" shadow="sm">
|
|
78
|
+
<div class="flex flex-col gap-2">
|
|
79
|
+
<span class="icon-[tabler--components] text-primary text-2xl"></span>
|
|
80
|
+
<span class="text-sm font-medium">{appM.preview_metric_shared()}</span>
|
|
81
|
+
<span class="text-base-content/60 text-xs">{appM.custom_shared_body()}</span>
|
|
82
|
+
</div>
|
|
83
|
+
</Card>
|
|
84
|
+
<Card padding="sm" shadow="sm">
|
|
85
|
+
<div class="flex flex-col gap-2">
|
|
86
|
+
<span class="icon-[tabler--message-language] text-primary text-2xl"></span>
|
|
87
|
+
<span class="text-sm font-medium">{appM.preview_metric_local()}</span>
|
|
88
|
+
<span class="text-base-content/60 text-xs">{appM.custom_local_body()}</span>
|
|
89
|
+
</div>
|
|
90
|
+
</Card>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<Alert variant="info">
|
|
94
|
+
{appM.flow_frontend()}
|
|
95
|
+
</Alert>
|
|
96
|
+
</section>
|
|
97
|
+
{:else if activeTab === 'status'}
|
|
98
|
+
<section class="space-y-4 p-4 pb-6">
|
|
99
|
+
<Card title={appM.status_title()} shadow="sm">
|
|
100
|
+
<p class="mb-4 text-sm text-base-content/65">{appM.status_description()}</p>
|
|
101
|
+
{#if loading}
|
|
102
|
+
<Skeleton variant="title" class="mb-3" />
|
|
103
|
+
<Skeleton count={3} />
|
|
104
|
+
<p class="sr-only" data-testid="service-status">{sharedM.home_loading()}</p>
|
|
105
|
+
{:else if info}
|
|
106
|
+
<Alert variant="success" title={appM.status_online({ name: info.name })}>
|
|
107
|
+
<p data-testid="service-status">{info.name}</p>
|
|
108
|
+
</Alert>
|
|
109
|
+
<div class="mt-4 grid grid-cols-2 gap-3 text-sm">
|
|
110
|
+
<div>
|
|
111
|
+
<p class="text-base-content/50">{appM.status_version()}</p>
|
|
112
|
+
<p class="font-medium">{info.version}</p>
|
|
113
|
+
</div>
|
|
114
|
+
<div>
|
|
115
|
+
<p class="text-base-content/50">{appM.status_frontends_count({ count: String(info.frontends.length) })}</p>
|
|
116
|
+
<p class="font-medium">{info.frontends.join(' / ')}</p>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
{:else}
|
|
120
|
+
<Alert variant="error" title={sharedM.home_error()}>
|
|
121
|
+
<p data-testid="service-status">{errorMessage}</p>
|
|
122
|
+
</Alert>
|
|
123
|
+
{/if}
|
|
124
|
+
|
|
125
|
+
{#snippet footer()}
|
|
126
|
+
<Button variant="ghost" size="sm" onclick={refreshStatus}>{sharedM.home_refresh()}</Button>
|
|
127
|
+
{/snippet}
|
|
128
|
+
</Card>
|
|
129
|
+
</section>
|
|
130
|
+
{:else}
|
|
131
|
+
<section class="space-y-4 p-4 pb-6">
|
|
132
|
+
<Card title={sharedM.settings_title()} shadow="sm">
|
|
133
|
+
<p class="mb-4 text-sm text-base-content/65">{appM.settings_description()}</p>
|
|
134
|
+
|
|
135
|
+
<div class="space-y-3">
|
|
136
|
+
<div class="rounded-2xl border border-base-300/70 bg-base-200/60 p-4">
|
|
137
|
+
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
|
138
|
+
<div class="min-w-0 flex-1">
|
|
139
|
+
<h2 class="text-sm font-semibold">{sharedM.settings_theme()}</h2>
|
|
140
|
+
<p class="mt-1 text-xs leading-5 text-base-content/65">{appM.settings_theme_description()}</p>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="shrink-0">
|
|
143
|
+
<ThemeSwitcher />
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<div class="rounded-2xl border border-base-300/70 bg-base-200/60 p-4">
|
|
149
|
+
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
|
150
|
+
<div class="min-w-0 flex-1">
|
|
151
|
+
<h2 class="text-sm font-semibold">{sharedM.settings_language()}</h2>
|
|
152
|
+
<p class="mt-1 text-xs leading-5 text-base-content/65">{appM.settings_language_description()}</p>
|
|
153
|
+
</div>
|
|
154
|
+
<div class="shrink-0">
|
|
155
|
+
<LanguageSwitcher onLocaleChange={syncLocale} />
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</Card>
|
|
161
|
+
|
|
162
|
+
<Card title={appM.flow_title()} shadow="sm">
|
|
163
|
+
<div class="space-y-3 text-sm">
|
|
164
|
+
<div class="bg-base-200 rounded-xl p-3">{appM.flow_contract()}</div>
|
|
165
|
+
<div class="bg-base-200 rounded-xl p-3">{appM.flow_service()}</div>
|
|
166
|
+
<div class="bg-base-200 rounded-xl p-3">{appM.flow_shared()}</div>
|
|
167
|
+
</div>
|
|
168
|
+
</Card>
|
|
169
|
+
</section>
|
|
170
|
+
{/if}
|
|
171
|
+
</main>
|
|
172
|
+
|
|
173
|
+
<BottomNav
|
|
174
|
+
items={navItems}
|
|
175
|
+
active={activeTab}
|
|
176
|
+
onchange={handleTabChange}
|
|
177
|
+
safeArea
|
|
178
|
+
centered
|
|
179
|
+
maxWidth="lg"
|
|
180
|
+
class="border-base-content/8 shadow-[0_-12px_32px_rgba(15,23,42,0.08)]"
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<ToastContainer />
|
|
186
|
+
{{/if}}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
@import 'tailwindcss';
|
|
4
4
|
@import '@h-ai/ui/styles/global.css';
|
|
5
5
|
@import '@h-ai/ui/styles/theme.css';
|
|
6
|
+
@import '@h-ai/ui/styles/design-tokens.css';
|
|
7
|
+
@import '@h-ai/ui/styles/mobile.css';
|
|
6
8
|
@source "../node_modules/@h-ai/ui/dist/**/*.{svelte,js,ts}";
|
|
7
9
|
@source "../../../node_modules/@h-ai/ui/dist/**/*.{svelte,js,ts}";
|
|
8
10
|
@source "../../../packages/{{fullstack.sharedPackageName}}/src/**/*.{svelte,js,ts}";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#if fullstack.frontends.app}}
|
|
3
|
+
import { capacitor } from '@h-ai/capacitor'
|
|
4
|
+
|
|
5
|
+
export async function initCapacitor(): Promise<void> {
|
|
6
|
+
const result = await capacitor.init()
|
|
7
|
+
if (!result.success) {
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (capacitor.isNative()) {
|
|
12
|
+
await capacitor.statusBar.configure({
|
|
13
|
+
style: 'dark',
|
|
14
|
+
overlay: true,
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
{{/if}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#if fullstack.frontends.app}}
|
|
3
|
+
import { mount } from 'svelte'
|
|
4
|
+
import App from './App.svelte'
|
|
5
|
+
import './app.css'
|
|
6
|
+
|
|
7
|
+
const target = document.getElementById('app')
|
|
8
|
+
if (!target)
|
|
9
|
+
throw new Error('Root element #app not found')
|
|
10
|
+
|
|
11
|
+
const app = mount(App, { target })
|
|
12
|
+
|
|
13
|
+
export default app
|
|
14
|
+
{{/if}}
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
{{! @skipIfEmpty }}
|
|
2
2
|
{{#if fullstack.frontends.app}}
|
|
3
3
|
import { autoImportHaiUi } from '@h-ai/ui/auto-import'
|
|
4
|
-
import adapter from '@sveltejs/adapter-auto'
|
|
5
4
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
|
|
6
5
|
|
|
7
|
-
/** @type {import('@sveltejs/
|
|
6
|
+
/** @type {import('@sveltejs/vite-plugin-svelte').SvelteConfig} */
|
|
8
7
|
const config = {
|
|
9
8
|
preprocess: [autoImportHaiUi(), vitePreprocess()],
|
|
10
9
|
compilerOptions: {
|
|
11
10
|
// 使用 Svelte 5 Runes,和 @h-ai/ui 组件库保持一致。
|
|
12
11
|
runes: true,
|
|
13
12
|
},
|
|
14
|
-
kit: {
|
|
15
|
-
adapter: adapter(),
|
|
16
|
-
},
|
|
17
13
|
}
|
|
18
14
|
|
|
19
15
|
export default config
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
{{! @skipIfEmpty }}
|
|
2
2
|
{{#if fullstack.frontends.app}}
|
|
3
3
|
{
|
|
4
|
-
"extends": "./.svelte-kit/tsconfig.json",
|
|
5
4
|
"compilerOptions": {
|
|
5
|
+
"target": "ES2022",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"module": "ESNext",
|
|
6
9
|
"moduleResolution": "bundler",
|
|
7
|
-
"
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"types": ["svelte", "vite/client", "node", "vitest/globals"],
|
|
8
12
|
"allowJs": true,
|
|
9
13
|
"checkJs": false,
|
|
10
14
|
"strict": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"isolatedModules": true,
|
|
11
17
|
"verbatimModuleSyntax": true,
|
|
12
18
|
"skipLibCheck": true
|
|
13
19
|
},
|
|
14
|
-
"include": ["src
|
|
15
|
-
"exclude": ["node_modules", "
|
|
20
|
+
"include": ["src/**/*.ts", "src/**/*.svelte", "tests/**/*.ts", "vite.config.ts", "svelte.config.js", "capacitor.config.ts"],
|
|
21
|
+
"exclude": ["node_modules", "dist", "build", "android", "ios"]
|
|
16
22
|
}
|
|
17
23
|
{{/if}}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
{{! @skipIfEmpty }}
|
|
2
2
|
{{#if fullstack.frontends.app}}
|
|
3
3
|
import { paraglideVitePlugin } from '@inlang/paraglide-js'
|
|
4
|
-
import {
|
|
4
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
5
5
|
import tailwindcss from '@tailwindcss/vite'
|
|
6
6
|
import { defineConfig } from 'vitest/config'
|
|
7
7
|
|
|
8
8
|
export default defineConfig({
|
|
9
9
|
plugins: [
|
|
10
|
+
svelte(),
|
|
11
|
+
tailwindcss(),
|
|
10
12
|
paraglideVitePlugin({
|
|
11
13
|
project: './project.inlang',
|
|
12
14
|
outdir: './src/lib/paraglide',
|
|
13
15
|
strategy: ['cookie', 'baseLocale'],
|
|
14
16
|
}),
|
|
15
|
-
sveltekit(),
|
|
16
|
-
tailwindcss(),
|
|
17
17
|
],
|
|
18
18
|
optimizeDeps: {
|
|
19
19
|
exclude: ['bits-ui'],
|
|
20
20
|
},
|
|
21
|
+
envPrefix: ['VITE_', 'PUBLIC_'],
|
|
21
22
|
ssr: {
|
|
22
23
|
noExternal: [/@h-ai\//, /{{fullstack.sharedPackageName}}/],
|
|
23
24
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{{#if fullstack.frontends.desktop}}
|
|
3
3
|
# {{projectName}}-desktop
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
桌面端工程,参考 `apps/desktop-app` 使用 Tauri v2 + Svelte 5 + Vite,前端通过共享 contract 调用 `{{fullstack.servPackageName}}`。
|
|
6
6
|
|
|
7
7
|
## i18n 与 shared 协同
|
|
8
8
|
|
|
@@ -12,10 +12,24 @@
|
|
|
12
12
|
|
|
13
13
|
自定义建议:桌面端菜单、状态、快捷操作文案放在本目录 `messages/`;跨端通用能力放到 shared。
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## 编译、打包与部署
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
```bash
|
|
18
|
+
# 仅前端开发,默认端口 {{fullstack.ports.desktop}}
|
|
19
|
+
pnpm --filter {{projectName}}-desktop dev
|
|
20
|
+
|
|
21
|
+
# Tauri 桌面开发
|
|
22
|
+
pnpm --filter {{projectName}}-desktop tauri:dev
|
|
23
|
+
|
|
24
|
+
# 编译 WebView 前端产物到 dist/
|
|
25
|
+
pnpm --filter {{projectName}}-desktop build
|
|
26
|
+
|
|
27
|
+
# 打包桌面安装包
|
|
28
|
+
pnpm --filter {{projectName}}-desktop package
|
|
29
|
+
|
|
30
|
+
# 当前模板的 deploy 入口默认执行 package,可按发布平台替换
|
|
31
|
+
pnpm --filter {{projectName}}-desktop deploy
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
打包前需要安装 Rust 工具链和 Tauri 平台依赖。生产环境部署时同步调整 `.env` 中的 `PUBLIC_API_BASE` 与 `src-tauri/tauri.conf.json` 的 `connect-src` 白名单。
|
|
21
35
|
{{/if}}
|
|
@@ -4,7 +4,7 @@ import antfu from '@antfu/eslint-config'
|
|
|
4
4
|
|
|
5
5
|
export default antfu({
|
|
6
6
|
formatters: true,
|
|
7
|
-
ignores: ['
|
|
7
|
+
ignores: ['**/build/**', '**/dist/**', '**/*.d.ts', '**/project.inlang/**', '**/src/lib/paraglide/**'],
|
|
8
8
|
svelte: true,
|
|
9
9
|
}, {
|
|
10
10
|
files: ['**/*.ts', '**/*.svelte'],
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#if fullstack.frontends.desktop}}
|
|
3
|
+
<!doctype html>
|
|
4
|
+
<html lang="{{fullstack.i18n.baseLocale}}" data-theme="{{fullstack.theme.defaultTheme}}">
|
|
5
|
+
<head>
|
|
6
|
+
<meta charset="UTF-8" />
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
|
+
<title>{{projectName}} Desktop</title>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app"></div>
|
|
12
|
+
<script type="module" src="/src/main.ts"></script>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
15
|
+
{{/if}}
|