@h-ai/cli 0.1.0-alpha.18 → 0.1.0-alpha.20

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.
Files changed (77) hide show
  1. package/dist/{chunk-BPO34NRL.js → chunk-3BBXDQ4Y.js} +5 -5
  2. package/dist/chunk-3BBXDQ4Y.js.map +1 -0
  3. package/dist/cli-config-templates-IGGO7P45.js +5 -0
  4. package/dist/{cli-config-templates-JCS7T3NU.js.map → cli-config-templates-IGGO7P45.js.map} +1 -1
  5. package/dist/index.js +67 -39
  6. package/dist/index.js.map +1 -1
  7. package/dist/{src-N4NPS7AG.js → src-QNEJJ3BV.js} +261 -103
  8. package/dist/src-QNEJJ3BV.js.map +1 -0
  9. package/package.json +2 -2
  10. package/templates/apps/admin/messages/en-US.json +5 -0
  11. package/templates/apps/admin/messages/zh-CN.json +5 -0
  12. package/templates/apps/admin/src/routes/+layout.svelte.hbs +5 -5
  13. package/templates/apps/admin/src/routes/+page.svelte.hbs +32 -12
  14. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +37 -20
  15. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
  16. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
  17. package/templates/apps/android-app/src/lib/api.ts.hbs +5 -4
  18. package/templates/apps/android-app/src/lib/capacitor.ts +1 -1
  19. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +11 -10
  20. package/templates/apps/android-app/src/routes/+page.svelte.hbs +17 -6
  21. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +4 -1
  22. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +14 -0
  23. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +13 -0
  24. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +3 -0
  25. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server-app.ts.hbs +23 -3
  26. package/templates/apps/h5/messages/en-US.json +3 -0
  27. package/templates/apps/h5/messages/zh-CN.json +3 -0
  28. package/templates/apps/h5/src/routes/+layout.svelte.hbs +30 -29
  29. package/templates/apps/h5/src/routes/+page.svelte.hbs +17 -6
  30. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
  31. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
  32. package/templates/apps/website/src/routes/+layout.svelte.hbs +35 -26
  33. package/templates/apps/website/src/routes/+page.svelte.hbs +28 -10
  34. package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
  35. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +37 -34
  36. package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
  37. package/templates/base/package.json.hbs +30 -24
  38. package/templates/base/src/app.html.hbs +4 -0
  39. package/templates/base/src/hooks.server.ts.hbs +17 -7
  40. package/templates/base/src/lib/server/init.ts.hbs +20 -12
  41. package/templates/base/static/favicon.png +0 -0
  42. package/templates/base/tests/scaffold.test.ts.hbs +9 -1
  43. package/templates/base/vite.config.ts.hbs +3 -3
  44. package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +5 -5
  45. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +34 -32
  46. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +46 -48
  47. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +35 -31
  48. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +41 -38
  49. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +15 -7
  50. package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +1 -2
  51. package/templates/skills/AGENTS.md +11 -1
  52. package/templates/skills/CLAUDE.md +2 -1
  53. package/templates/skills/copilot-instructions.md +22 -6
  54. package/templates/skills/hai-ai/SKILL.md +115 -646
  55. package/templates/skills/hai-ai/reference.md +197 -0
  56. package/templates/skills/hai-api-client/SKILL.md +7 -1
  57. package/templates/skills/hai-app-create/SKILL.md +1 -1
  58. package/templates/skills/hai-app-review/SKILL.md +1 -1
  59. package/templates/skills/hai-audit/SKILL.md +7 -2
  60. package/templates/skills/hai-cache/SKILL.md +2 -0
  61. package/templates/skills/hai-capacitor/SKILL.md +11 -9
  62. package/templates/skills/hai-core/SKILL.md +4 -1
  63. package/templates/skills/hai-crypto/SKILL.md +42 -8
  64. package/templates/skills/hai-deploy/SKILL.md +12 -9
  65. package/templates/skills/hai-iam/SKILL.md +2 -0
  66. package/templates/skills/hai-kit/SKILL.md +14 -5
  67. package/templates/skills/hai-payment/SKILL.md +5 -0
  68. package/templates/skills/hai-reach/SKILL.md +3 -1
  69. package/templates/skills/hai-reldb/SKILL.md +2 -0
  70. package/templates/skills/hai-scheduler/SKILL.md +2 -0
  71. package/templates/skills/hai-serv/SKILL.md +5 -0
  72. package/templates/skills/hai-storage/SKILL.md +10 -1
  73. package/templates/skills/hai-ui/SKILL.md +25 -11
  74. package/templates/skills/hai-vecdb/SKILL.md +8 -1
  75. package/dist/chunk-BPO34NRL.js.map +0 -1
  76. package/dist/cli-config-templates-JCS7T3NU.js +0 -5
  77. package/dist/src-N4NPS7AG.js.map +0 -1
@@ -1,22 +1,38 @@
1
1
  {{!-- H5 应用根布局 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * H5 应用根布局
5
5
  */
6
6
  import type { Snippet } from 'svelte'
7
- import '../app.css'
8
7
  {{#if hasI18n}}
9
8
  import { browser } from '$app/environment'
10
- import { setGlobalLocale } from '@h-ai/ui'
11
- import { getLocale } from '$lib/paraglide/runtime.js'
9
+ {{/if}}
10
+ import { resolve } from '$app/paths'
11
+ import { page } from '$app/state'
12
+ {{#if hasI18n}}
12
13
  import * as m from '$lib/paraglide/messages'
14
+ import { getLocale } from '$lib/paraglide/runtime.js'
15
+ import { setGlobalLocale } from '@h-ai/ui'
13
16
  {{/if}}
17
+ import '../app.css'
14
18
 
15
19
  interface Props {
16
20
  children: Snippet
17
21
  }
18
22
 
19
- let { children }: Props = $props()
23
+ const { children }: Props = $props()
24
+
25
+ const navItems = [
26
+ {{#if hasI18n}}
27
+ { path: '/', label: m.nav_home(), icon: 'icon-[tabler--home]' },
28
+ { path: '/discover', label: m.nav_discover(), icon: 'icon-[tabler--compass]' },
29
+ { path: '/profile', label: m.nav_profile(), icon: 'icon-[tabler--user]' },
30
+ {{else}}
31
+ { path: '/', label: '首页', icon: 'icon-[tabler--home]' },
32
+ { path: '/discover', label: '发现', icon: 'icon-[tabler--compass]' },
33
+ { path: '/profile', label: '我的', icon: 'icon-[tabler--user]' },
34
+ {{/if}}
35
+ ] as const
20
36
  {{#if hasI18n}}
21
37
 
22
38
  if (browser) {
@@ -26,32 +42,17 @@
26
42
  {{/if}}
27
43
  </script>
28
44
 
29
- <div class="min-h-screen flex flex-col bg-base-200">
30
- <main class="flex-1 pb-16">
45
+ <div class='min-h-screen flex flex-col bg-base-200'>
46
+ <main class='flex-1 pb-16'>
31
47
  {@render children()}
32
48
  </main>
33
49
 
34
- <nav class="btm-nav btm-nav-sm">
35
- <a href="/" class="text-primary">
36
- {{#if hasI18n}}
37
- <span class="btm-nav-label">{m.nav_home()}</span>
38
- {{else}}
39
- <span class="btm-nav-label">首页</span>
40
- {{/if}}
41
- </a>
42
- <a href="/discover">
43
- {{#if hasI18n}}
44
- <span class="btm-nav-label">{m.nav_discover()}</span>
45
- {{else}}
46
- <span class="btm-nav-label">发现</span>
47
- {{/if}}
48
- </a>
49
- <a href="/profile">
50
- {{#if hasI18n}}
51
- <span class="btm-nav-label">{m.nav_profile()}</span>
52
- {{else}}
53
- <span class="btm-nav-label">我的</span>
54
- {{/if}}
55
- </a>
50
+ <nav class='btm-nav btm-nav-sm'>
51
+ {#each navItems as item (item.path)}
52
+ <a href={resolve(item.path, {})} class:active={page.url.pathname === item.path} class:text-primary={page.url.pathname === item.path}>
53
+ <span class='{item.icon} size-5'></span>
54
+ <span class='btm-nav-label'>{item.label}</span>
55
+ </a>
56
+ {/each}
56
57
  </nav>
57
58
  </div>
@@ -1,11 +1,12 @@
1
1
  {{!-- H5 首页 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * H5 首页
5
5
  */
6
6
  {{#if hasI18n}}
7
7
  import * as m from '$lib/paraglide/messages'
8
8
  {{/if}}
9
+ import { Card } from '@h-ai/ui'
9
10
  </script>
10
11
 
11
12
  <svelte:head>
@@ -16,12 +17,22 @@
16
17
  {{/if}}
17
18
  </svelte:head>
18
19
 
19
- <section class="p-4">
20
+ <section class='p-4 space-y-4'>
20
21
  {{#if hasI18n}}
21
- <h1 class="text-2xl font-bold mb-4">{m.page_home_title()}</h1>
22
- <p class="text-gray-600">{m.page_home_desc()}</p>
22
+ <h1 class='text-2xl font-black tracking-tight'>{m.page_home_title()}</h1>
23
+ <Card shadow='sm' class='bg-base-100'>
24
+ <div class='flex items-center gap-3'>
25
+ <span class='icon-[tabler--home] size-8 text-primary'></span>
26
+ <p class='text-base-content/70'>{m.page_home_desc()}</p>
27
+ </div>
28
+ </Card>
23
29
  {{else}}
24
- <h1 class="text-2xl font-bold mb-4">首页</h1>
25
- <p class="text-gray-600">欢迎使用 H5 应用</p>
30
+ <h1 class='text-2xl font-black tracking-tight'>首页</h1>
31
+ <Card shadow='sm' class='bg-base-100'>
32
+ <div class='flex items-center gap-3'>
33
+ <span class='icon-[tabler--home] size-8 text-primary'></span>
34
+ <p class='text-base-content/70'>欢迎使用 H5 应用</p>
35
+ </div>
36
+ </Card>
26
37
  {{/if}}
27
38
  </section>
@@ -1,11 +1,12 @@
1
1
  {{!-- 发现页面 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * 发现页面
5
5
  */
6
6
  {{#if hasI18n}}
7
7
  import * as m from '$lib/paraglide/messages'
8
8
  {{/if}}
9
+ import { Card } from '@h-ai/ui'
9
10
  </script>
10
11
 
11
12
  <svelte:head>
@@ -16,12 +17,22 @@
16
17
  {{/if}}
17
18
  </svelte:head>
18
19
 
19
- <section class="p-4">
20
+ <section class='p-4 space-y-4'>
20
21
  {{#if hasI18n}}
21
- <h1 class="text-2xl font-bold mb-4">{m.page_discover_title()}</h1>
22
- <p class="text-gray-600">{m.page_discover_desc()}</p>
22
+ <h1 class='text-2xl font-black tracking-tight'>{m.page_discover_title()}</h1>
23
+ <Card shadow='sm' class='bg-base-100'>
24
+ <div class='flex items-center gap-3'>
25
+ <span class='icon-[tabler--compass] size-8 text-primary'></span>
26
+ <p class='text-base-content/70'>{m.page_discover_desc()}</p>
27
+ </div>
28
+ </Card>
23
29
  {{else}}
24
- <h1 class="text-2xl font-bold mb-4">发现</h1>
25
- <p class="text-gray-600">探索更多精彩内容</p>
30
+ <h1 class='text-2xl font-black tracking-tight'>发现</h1>
31
+ <Card shadow='sm' class='bg-base-100'>
32
+ <div class='flex items-center gap-3'>
33
+ <span class='icon-[tabler--compass] size-8 text-primary'></span>
34
+ <p class='text-base-content/70'>探索更多精彩内容</p>
35
+ </div>
36
+ </Card>
26
37
  {{/if}}
27
38
  </section>
@@ -1,11 +1,12 @@
1
1
  {{!-- 个人中心页面 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * 个人中心页面
5
5
  */
6
6
  {{#if hasI18n}}
7
7
  import * as m from '$lib/paraglide/messages'
8
8
  {{/if}}
9
+ import { Card } from '@h-ai/ui'
9
10
  </script>
10
11
 
11
12
  <svelte:head>
@@ -16,12 +17,22 @@
16
17
  {{/if}}
17
18
  </svelte:head>
18
19
 
19
- <section class="p-4">
20
+ <section class='p-4 space-y-4'>
20
21
  {{#if hasI18n}}
21
- <h1 class="text-2xl font-bold mb-4">{m.page_profile_title()}</h1>
22
- <p class="text-gray-600">{m.page_profile_desc()}</p>
22
+ <h1 class='text-2xl font-black tracking-tight'>{m.page_profile_title()}</h1>
23
+ <Card shadow='sm' class='bg-base-100'>
24
+ <div class='flex items-center gap-3'>
25
+ <span class='icon-[tabler--user] size-8 text-primary'></span>
26
+ <p class='text-base-content/70'>{m.page_profile_desc()}</p>
27
+ </div>
28
+ </Card>
23
29
  {{else}}
24
- <h1 class="text-2xl font-bold mb-4">我的</h1>
25
- <p class="text-gray-600">管理您的个人信息</p>
30
+ <h1 class='text-2xl font-black tracking-tight'>我的</h1>
31
+ <Card shadow='sm' class='bg-base-100'>
32
+ <div class='flex items-center gap-3'>
33
+ <span class='icon-[tabler--user] size-8 text-primary'></span>
34
+ <p class='text-base-content/70'>管理您的个人信息</p>
35
+ </div>
36
+ </Card>
26
37
  {{/if}}
27
38
  </section>
@@ -1,22 +1,39 @@
1
1
  {{!-- 官网根布局 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * 官网根布局
5
5
  */
6
6
  import type { Snippet } from 'svelte'
7
- import '../app.css'
8
7
  {{#if hasI18n}}
9
8
  import { browser } from '$app/environment'
10
- import { setGlobalLocale } from '@h-ai/ui'
11
- import { getLocale } from '$lib/paraglide/runtime.js'
9
+ {{/if}}
10
+ import { resolve } from '$app/paths'
11
+ {{#if hasI18n}}
12
12
  import * as m from '$lib/paraglide/messages'
13
+ import { getLocale } from '$lib/paraglide/runtime.js'
14
+ import { setGlobalLocale } from '@h-ai/ui'
13
15
  {{/if}}
16
+ import '../app.css'
14
17
 
15
18
  interface Props {
16
19
  children: Snippet
17
20
  }
18
21
 
19
- let { children }: Props = $props()
22
+ const { children }: Props = $props()
23
+
24
+ const navItems = [
25
+ {{#if hasI18n}}
26
+ { path: '/', label: m.nav_home() },
27
+ { path: '/about', label: m.nav_about() },
28
+ { path: '/services', label: m.nav_services() },
29
+ { path: '/contact', label: m.nav_contact() },
30
+ {{else}}
31
+ { path: '/', label: '首页' },
32
+ { path: '/about', label: '关于' },
33
+ { path: '/services', label: '服务' },
34
+ { path: '/contact', label: '联系我们' },
35
+ {{/if}}
36
+ ] as const
20
37
  {{#if hasI18n}}
21
38
 
22
39
  if (browser) {
@@ -26,39 +43,31 @@
26
43
  {{/if}}
27
44
  </script>
28
45
 
29
- <div class="min-h-screen flex flex-col">
30
- <header class="navbar bg-base-100 shadow-sm">
31
- <div class="flex-1">
46
+ <div class='min-h-screen flex flex-col'>
47
+ <header class='navbar bg-base-100 shadow-sm'>
48
+ <div class='flex-1'>
32
49
  {{#if hasI18n}}
33
- <a href="/" class="btn btn-ghost text-xl">{m.app_title()}</a>
50
+ <a href={resolve('/', {})} class='btn btn-ghost text-xl font-black tracking-tight'>{m.app_title()}</a>
34
51
  {{else}}
35
- <a href="/" class="btn btn-ghost text-xl">官网</a>
52
+ <a href={resolve('/', {})} class='btn btn-ghost text-xl font-black tracking-tight'>官网</a>
36
53
  {{/if}}
37
54
  </div>
38
- <nav class="flex-none">
39
- <ul class="menu menu-horizontal px-1">
40
- {{#if hasI18n}}
41
- <li><a href="/">{m.nav_home()}</a></li>
42
- <li><a href="/about">{m.nav_about()}</a></li>
43
- <li><a href="/services">{m.nav_services()}</a></li>
44
- <li><a href="/contact">{m.nav_contact()}</a></li>
45
- {{else}}
46
- <li><a href="/">首页</a></li>
47
- <li><a href="/about">关于</a></li>
48
- <li><a href="/services">服务</a></li>
49
- <li><a href="/contact">联系我们</a></li>
50
- {{/if}}
55
+ <nav class='flex-none'>
56
+ <ul class='menu menu-horizontal px-1'>
57
+ {#each navItems as item (item.path)}
58
+ <li><a href={resolve(item.path, {})}>{item.label}</a></li>
59
+ {/each}
51
60
  </ul>
52
61
  </nav>
53
62
  </header>
54
63
 
55
- <main class="flex-1">
64
+ <main class='flex-1'>
56
65
  {@render children()}
57
66
  </main>
58
67
 
59
- <footer class="footer footer-center p-4 bg-base-300 text-base-content">
68
+ <footer class='footer footer-center p-4 bg-base-300 text-base-content'>
60
69
  {{#if hasI18n}}
61
- <p>{m.footer_copyright()}</p>
70
+ <p>{m.footer_copyright({ year: new Date().getFullYear() })}</p>
62
71
  {{else}}
63
72
  <p>Copyright © 2025 - All rights reserved</p>
64
73
  {{/if}}
@@ -1,11 +1,13 @@
1
1
  {{!-- 官网首页 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * 官网首页
5
5
  */
6
+ import { resolve } from '$app/paths'
6
7
  {{#if hasI18n}}
7
8
  import * as m from '$lib/paraglide/messages'
8
9
  {{/if}}
10
+ import { Badge } from '@h-ai/ui'
9
11
  </script>
10
12
 
11
13
  <svelte:head>
@@ -16,17 +18,33 @@
16
18
  {{/if}}
17
19
  </svelte:head>
18
20
 
19
- <section class="hero min-h-[60vh] bg-base-200">
20
- <div class="hero-content text-center">
21
- <div class="max-w-md">
21
+ <section class='hero min-h-[60vh] bg-gradient-to-b from-base-200 to-base-100'>
22
+ <div class='hero-content text-center'>
23
+ <div class='max-w-xl'>
24
+ <div class='flex justify-center'>
25
+ <Badge variant='primary'>
26
+ <span class='icon-[tabler--sparkles] size-4'></span>
22
27
  {{#if hasI18n}}
23
- <h1 class="text-5xl font-bold">{m.page_home_title()}</h1>
24
- <p class="py-6">{m.page_home_subtitle()}</p>
25
- <a href="/about" class="btn btn-primary">{m.page_home_cta()}</a>
28
+ {m.app_title()}
26
29
  {{else}}
27
- <h1 class="text-5xl font-bold">欢迎</h1>
28
- <p class="py-6">基于 hai Agent Framework 构建</p>
29
- <a href="/about" class="btn btn-primary">了解更多</a>
30
+ 由 hai 驱动
31
+ {{/if}}
32
+ </Badge>
33
+ </div>
34
+ {{#if hasI18n}}
35
+ <h1 class='mt-5 text-5xl font-black tracking-tight'>{m.page_home_title()}</h1>
36
+ <p class='py-6 text-base-content/60'>{m.page_home_subtitle()}</p>
37
+ <a href={resolve('/about', {})} class='btn btn-primary'>
38
+ <span class='icon-[tabler--arrow-right] size-5'></span>
39
+ {m.page_home_cta()}
40
+ </a>
41
+ {{else}}
42
+ <h1 class='mt-5 text-5xl font-black tracking-tight'>欢迎</h1>
43
+ <p class='py-6 text-base-content/60'>基于 hai Agent Framework 构建</p>
44
+ <a href={resolve('/about', {})} class='btn btn-primary'>
45
+ <span class='icon-[tabler--arrow-right] size-5'></span>
46
+ 了解更多
47
+ </a>
30
48
  {{/if}}
31
49
  </div>
32
50
  </div>
@@ -1,11 +1,12 @@
1
1
  {{!-- 关于页面 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * 关于页面
5
5
  */
6
6
  {{#if hasI18n}}
7
7
  import * as m from '$lib/paraglide/messages'
8
8
  {{/if}}
9
+ import { Card, PageHeader } from '@h-ai/ui'
9
10
  </script>
10
11
 
11
12
  <svelte:head>
@@ -16,12 +17,16 @@
16
17
  {{/if}}
17
18
  </svelte:head>
18
19
 
19
- <section class="py-16 px-4 max-w-4xl mx-auto">
20
+ <section class='py-16 px-4 max-w-4xl mx-auto'>
20
21
  {{#if hasI18n}}
21
- <h1 class="text-3xl font-bold mb-8">{m.page_about_title()}</h1>
22
- <p class="text-lg text-gray-600">{m.page_about_desc()}</p>
22
+ <PageHeader title={m.page_about_title()} />
23
+ <Card shadow='sm' class='bg-base-100'>
24
+ <p class='text-lg text-base-content/70'>{m.page_about_desc()}</p>
25
+ </Card>
23
26
  {{else}}
24
- <h1 class="text-3xl font-bold mb-8">关于我们</h1>
25
- <p class="text-lg text-gray-600">了解我们的团队与使命。</p>
27
+ <PageHeader title='关于我们' />
28
+ <Card shadow='sm' class='bg-base-100'>
29
+ <p class='text-lg text-base-content/70'>了解我们的团队与使命。</p>
30
+ </Card>
26
31
  {{/if}}
27
32
  </section>
@@ -1,11 +1,20 @@
1
1
  {{!-- 联系页面 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * 联系我们页面
5
5
  */
6
6
  {{#if hasI18n}}
7
7
  import * as m from '$lib/paraglide/messages'
8
8
  {{/if}}
9
+ import { Button, Card, FormField, Input, PageHeader } from '@h-ai/ui'
10
+
11
+ let name = $state('')
12
+ let email = $state('')
13
+ let message = $state('')
14
+
15
+ function handleSubmit(event: SubmitEvent) {
16
+ event.preventDefault()
17
+ }
9
18
  </script>
10
19
 
11
20
  <svelte:head>
@@ -16,44 +25,38 @@
16
25
  {{/if}}
17
26
  </svelte:head>
18
27
 
19
- <section class="py-16 px-4 max-w-2xl mx-auto">
28
+ <section class='py-16 px-4 max-w-2xl mx-auto'>
20
29
  {{#if hasI18n}}
21
- <h1 class="text-3xl font-bold mb-8">{m.page_contact_title()}</h1>
22
- <p class="text-lg text-gray-600 mb-8">{m.page_contact_desc()}</p>
30
+ <PageHeader title={m.page_contact_title()} description={m.page_contact_desc()} />
23
31
  {{else}}
24
- <h1 class="text-3xl font-bold mb-8">联系我们</h1>
25
- <p class="text-lg text-gray-600 mb-8">有任何疑问?欢迎联系我们。</p>
32
+ <PageHeader title='联系我们' description='有任何疑问?欢迎联系我们。' />
26
33
  {{/if}}
27
34
 
28
- <form class="space-y-4">
29
- <div class="form-control">
30
- {{#if hasI18n}}
31
- <label class="label" for="name"><span class="label-text">{m.page_contact_name()}</span></label>
32
- {{else}}
33
- <label class="label" for="name"><span class="label-text">姓名</span></label>
34
- {{/if}}
35
- <input id="name" type="text" class="input input-bordered w-full" />
36
- </div>
37
- <div class="form-control">
38
- {{#if hasI18n}}
39
- <label class="label" for="email"><span class="label-text">{m.page_contact_email()}</span></label>
40
- {{else}}
41
- <label class="label" for="email"><span class="label-text">邮箱</span></label>
42
- {{/if}}
43
- <input id="email" type="email" class="input input-bordered w-full" />
44
- </div>
45
- <div class="form-control">
46
- {{#if hasI18n}}
47
- <label class="label" for="message"><span class="label-text">{m.page_contact_message()}</span></label>
48
- {{else}}
49
- <label class="label" for="message"><span class="label-text">留言</span></label>
50
- {{/if}}
51
- <textarea id="message" class="textarea textarea-bordered w-full" rows="4"></textarea>
52
- </div>
35
+ <Card shadow='sm' class='bg-base-100'>
36
+ <form class='space-y-4' onsubmit={handleSubmit}>
53
37
  {{#if hasI18n}}
54
- <button type="submit" class="btn btn-primary w-full">{m.page_contact_submit()}</button>
38
+ <FormField label={m.page_contact_name()} required>
39
+ <Input id='name' type='text' bind:value={name} required />
40
+ </FormField>
41
+ <FormField label={m.page_contact_email()} required>
42
+ <Input id='email' type='email' bind:value={email} required />
43
+ </FormField>
44
+ <FormField label={m.page_contact_message()} required>
45
+ <textarea id='message' class='textarea textarea-bordered w-full' rows='4' bind:value={message}></textarea>
46
+ </FormField>
47
+ <Button type='submit' variant='primary' class='w-full'>{m.page_contact_submit()}</Button>
55
48
  {{else}}
56
- <button type="submit" class="btn btn-primary w-full">发送</button>
49
+ <FormField label='姓名' required>
50
+ <Input id='name' type='text' bind:value={name} required />
51
+ </FormField>
52
+ <FormField label='邮箱' required>
53
+ <Input id='email' type='email' bind:value={email} required />
54
+ </FormField>
55
+ <FormField label='留言' required>
56
+ <textarea id='message' class='textarea textarea-bordered w-full' rows='4' bind:value={message}></textarea>
57
+ </FormField>
58
+ <Button type='submit' variant='primary' class='w-full'>发送</Button>
57
59
  {{/if}}
58
- </form>
60
+ </form>
61
+ </Card>
59
62
  </section>
@@ -1,10 +1,25 @@
1
1
  {{!-- 服务页面 --}}
2
- <script lang="ts">
2
+ <script lang='ts'>
3
3
  /**
4
4
  * 服务页面
5
5
  */
6
6
  {{#if hasI18n}}
7
7
  import * as m from '$lib/paraglide/messages'
8
+ {{/if}}
9
+ import { Card, PageHeader } from '@h-ai/ui'
10
+
11
+ {{#if hasI18n}}
12
+ const services = $derived([
13
+ { title: m.page_services_item1(), desc: m.page_services_desc(), icon: 'icon-[tabler--message-circle]' },
14
+ { title: m.page_services_item2(), desc: m.page_services_desc(), icon: 'icon-[tabler--code]' },
15
+ { title: m.page_services_item1(), desc: m.page_services_desc(), icon: 'icon-[tabler--server-cog]' },
16
+ ])
17
+ {{else}}
18
+ const services = [
19
+ { title: '咨询服务', desc: '提供专业的技术咨询与解决方案。', icon: 'icon-[tabler--message-circle]' },
20
+ { title: '定制开发', desc: '根据需求定制开发高质量应用。', icon: 'icon-[tabler--code]' },
21
+ { title: '运维支持', desc: '提供全方位的系统运维与技术支持。', icon: 'icon-[tabler--server-cog]' },
22
+ ]
8
23
  {{/if}}
9
24
  </script>
10
25
 
@@ -16,48 +31,20 @@
16
31
  {{/if}}
17
32
  </svelte:head>
18
33
 
19
- <section class="py-16 px-4 max-w-4xl mx-auto">
34
+ <section class='py-16 px-4 max-w-4xl mx-auto'>
20
35
  {{#if hasI18n}}
21
- <h1 class="text-3xl font-bold mb-8">{m.page_services_title()}</h1>
22
- <p class="text-lg text-gray-600 mb-12">{m.page_services_desc()}</p>
36
+ <PageHeader title={m.page_services_title()} description={m.page_services_desc()} />
23
37
  {{else}}
24
- <h1 class="text-3xl font-bold mb-8">我们的服务</h1>
25
- <p class="text-lg text-gray-600 mb-12">我们提供以下专业服务。</p>
38
+ <PageHeader title='我们的服务' description='我们提供以下专业服务。' />
26
39
  {{/if}}
27
40
 
28
- <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
29
- <div class="card bg-base-100 shadow">
30
- <div class="card-body">
31
- {{#if hasI18n}}
32
- <h2 class="card-title">{m.page_services_item1()}</h2>
33
- <p>{m.page_services_desc()}</p>
34
- {{else}}
35
- <h2 class="card-title">咨询服务</h2>
36
- <p>提供专业的技术咨询与解决方案。</p>
37
- {{/if}}
38
- </div>
39
- </div>
40
- <div class="card bg-base-100 shadow">
41
- <div class="card-body">
42
- {{#if hasI18n}}
43
- <h2 class="card-title">{m.page_services_item2()}</h2>
44
- <p>{m.page_services_desc()}</p>
45
- {{else}}
46
- <h2 class="card-title">定制开发</h2>
47
- <p>根据需求定制开发高质量应用。</p>
48
- {{/if}}
49
- </div>
50
- </div>
51
- <div class="card bg-base-100 shadow">
52
- <div class="card-body">
53
- {{#if hasI18n}}
54
- <h2 class="card-title">{m.page_services_item1()}</h2>
55
- <p>{m.page_services_desc()}</p>
56
- {{else}}
57
- <h2 class="card-title">运维支持</h2>
58
- <p>提供全方位的系统运维与技术支持。</p>
59
- {{/if}}
60
- </div>
61
- </div>
41
+ <div class='grid grid-cols-1 md:grid-cols-3 gap-6'>
42
+ {#each services as service (service.title)}
43
+ <Card shadow='sm' class='bg-base-100'>
44
+ <span class='{service.icon} size-8 text-primary'></span>
45
+ <h2 class='mt-3 text-lg font-semibold'>{service.title}</h2>
46
+ <p class='mt-1 text-sm text-base-content/60'>{service.desc}</p>
47
+ </Card>
48
+ {/each}
62
49
  </div>
63
50
  </section>