@liujitcn/kratos-taro-app-system 0.1.1 → 0.1.4

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 (25) hide show
  1. package/dist/module.mjs +108 -4
  2. package/package.json +3 -3
  3. package/src/components/KratosMyPage.scss +1 -1
  4. package/src/locales/en-US.json +27 -1
  5. package/src/locales/ja-JP.json +27 -1
  6. package/src/locales/zh-CN.json +27 -1
  7. package/src/locales/zh-TW.json +27 -1
  8. package/src/views/pagesMember/ai/components/Composer.tsx +3 -3
  9. package/src/views/pagesMember/ai/components/KnowledgePicker.tsx +1 -1
  10. package/src/views/pagesMember/ai/components/ModelPicker.tsx +1 -1
  11. package/src/views/pagesMember/ai/components/SessionDrawer.tsx +1 -1
  12. package/src/views/pagesMember/ai/components/WelcomePanel.tsx +1 -1
  13. package/src/views/pagesMember/ai/components/composer.scss +28 -7
  14. package/src/views/pagesMember/ai/index.scss +2 -2
  15. package/src/views/pagesMember/message/detail.tsx +3 -29
  16. package/src/views/pagesMember/message/message.scss +1 -14
  17. package/src/views/pagesMember/profile/profile.scss +17 -1
  18. package/src/views/pagesMember/settings/components/ChangePasswordEntry.scss +116 -0
  19. package/src/views/pagesMember/settings/components/ChangePasswordEntry.tsx +227 -0
  20. package/src/views/pagesMember/settings/settings.scss +1 -1
  21. package/src/views/pagesMember/settings/settings.tsx +23 -20
  22. /package/src/views/pagesMember/ai/components/{knowledge-picker.scss → KnowledgePicker.scss} +0 -0
  23. /package/src/views/pagesMember/ai/components/{model-picker.scss → ModelPicker.scss} +0 -0
  24. /package/src/views/pagesMember/ai/components/{session-drawer.scss → SessionDrawer.scss} +0 -0
  25. /package/src/views/pagesMember/ai/components/{welcome-panel.scss → WelcomePanel.scss} +0 -0
package/dist/module.mjs CHANGED
@@ -135,8 +135,34 @@ var zh_CN_default = {
135
135
  "system.settings.feedback": "\u95EE\u9898\u53CD\u9988",
136
136
  "system.settings.section_appearance": "\u5916\u89C2",
137
137
  "system.settings.section_security": "\u8D26\u6237\u5B89\u5168",
138
- "system.settings.section_more": "\u66F4\u591A \xB7 \u5C0F\u7A0B\u5E8F\u7AEF",
138
+ "system.settings.section_more": "\u66F4\u591A\u670D\u52A1",
139
139
  "system.settings.go_ask": "\u53BB\u63D0\u95EE",
140
+ "system.settings.password_title": "\u4FEE\u6539\u5BC6\u7801",
141
+ "system.settings.password_action": "\u524D\u5F80\u4FEE\u6539",
142
+ "system.settings.password_description": "\u66F4\u65B0\u5F53\u524D\u767B\u5F55\u5BC6\u7801\uFF0C\u4FDD\u6301\u8D26\u6237\u5B89\u5168\u3002",
143
+ "system.settings.password_current": "\u5F53\u524D\u5BC6\u7801",
144
+ "system.settings.password_current_placeholder": "\u8BF7\u8F93\u5165\u5F53\u524D\u5BC6\u7801",
145
+ "system.settings.password_new": "\u65B0\u5BC6\u7801",
146
+ "system.settings.password_new_placeholder": "\u8BF7\u8F93\u5165\u65B0\u5BC6\u7801",
147
+ "system.settings.password_strength": "\u5BC6\u7801\u5F3A\u5EA6",
148
+ "system.settings.password_strength_empty": "\u672A\u8F93\u5165",
149
+ "system.settings.password_strength_low": "\u8F83\u5F31",
150
+ "system.settings.password_strength_medium": "\u4E2D\u7B49",
151
+ "system.settings.password_strength_high": "\u8F83\u5F3A",
152
+ "system.settings.password_policy_default": "\u8BF7\u8BBE\u7F6E\u5305\u542B\u5927\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u7B26\u53F7\u7684\u9AD8\u5F3A\u5EA6\u5BC6\u7801\u3002",
153
+ "system.settings.password_policy_min_length": "\u81F3\u5C11 {count} \u4E2A\u5B57\u7B26",
154
+ "system.settings.password_policy_complexity": "\u81F3\u5C11\u6EE1\u8DB3 {count} \u7C7B\u5B57\u7B26",
155
+ "system.settings.password_policy_history": "\u4E0D\u80FD\u91CD\u590D\u6700\u8FD1 {count} \u4E2A\u5BC6\u7801",
156
+ "system.settings.password_policy_max_age": "\u5BC6\u7801\u6709\u6548\u671F {count} \u5929",
157
+ "system.settings.password_policy_no_expiry": "\u5BC6\u7801\u957F\u671F\u6709\u6548",
158
+ "system.settings.password_policy_separator": "\uFF1B",
159
+ "system.settings.password_confirm": "\u786E\u8BA4\u65B0\u5BC6\u7801",
160
+ "system.settings.password_confirm_placeholder": "\u8BF7\u518D\u6B21\u8F93\u5165\u65B0\u5BC6\u7801",
161
+ "system.settings.password_policy_loading": "\u6B63\u5728\u8BFB\u53D6\u5BC6\u7801\u7B56\u7565",
162
+ "system.settings.password_required": "\u8BF7\u5B8C\u6574\u586B\u5199\u5BC6\u7801",
163
+ "system.settings.password_mismatch": "\u4E24\u6B21\u8F93\u5165\u7684\u65B0\u5BC6\u7801\u4E0D\u4E00\u81F4",
164
+ "system.settings.password_submit": "\u786E\u8BA4\u4FEE\u6539",
165
+ "system.settings.password_updated": "\u5BC6\u7801\u4FEE\u6539\u6210\u529F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55",
140
166
  "system.settings.logout_confirm": "\u662F\u5426\u9000\u51FA\u767B\u5F55\uFF1F",
141
167
  "system.settings.logout_failed": "\u9000\u51FA\u767B\u5F55\u5931\u8D25",
142
168
  "system.settings.title": "\u8BBE\u7F6E",
@@ -301,8 +327,34 @@ var en_US_default = {
301
327
  "system.settings.feedback": "Feedback",
302
328
  "system.settings.section_appearance": "Appearance",
303
329
  "system.settings.section_security": "Account security",
304
- "system.settings.section_more": "More \xB7 Mini Program",
330
+ "system.settings.section_more": "More Services",
305
331
  "system.settings.go_ask": "Ask now",
332
+ "system.settings.password_title": "Change password",
333
+ "system.settings.password_action": "Change",
334
+ "system.settings.password_description": "Update your login password to keep your account secure.",
335
+ "system.settings.password_current": "Current password",
336
+ "system.settings.password_current_placeholder": "Enter your current password",
337
+ "system.settings.password_new": "New password",
338
+ "system.settings.password_new_placeholder": "Enter a new password",
339
+ "system.settings.password_strength": "Password strength",
340
+ "system.settings.password_strength_empty": "Not entered",
341
+ "system.settings.password_strength_low": "Weak",
342
+ "system.settings.password_strength_medium": "Medium",
343
+ "system.settings.password_strength_high": "Strong",
344
+ "system.settings.password_policy_default": "Use a strong password with uppercase and lowercase letters, numbers, and symbols.",
345
+ "system.settings.password_policy_min_length": "At least {count} characters",
346
+ "system.settings.password_policy_complexity": "At least {count} character types",
347
+ "system.settings.password_policy_history": "Do not reuse the last {count} passwords",
348
+ "system.settings.password_policy_max_age": "Password expires in {count} days",
349
+ "system.settings.password_policy_no_expiry": "Password does not expire",
350
+ "system.settings.password_policy_separator": "; ",
351
+ "system.settings.password_confirm": "Confirm new password",
352
+ "system.settings.password_confirm_placeholder": "Enter the new password again",
353
+ "system.settings.password_policy_loading": "Loading password policy",
354
+ "system.settings.password_required": "Complete all password fields",
355
+ "system.settings.password_mismatch": "The new passwords do not match",
356
+ "system.settings.password_submit": "Change password",
357
+ "system.settings.password_updated": "Password changed. Please sign in again",
306
358
  "system.settings.logout_confirm": "Log out now?",
307
359
  "system.settings.logout_failed": "Logout failed",
308
360
  "system.settings.title": "Settings",
@@ -467,8 +519,34 @@ var ja_JP_default = {
467
519
  "system.settings.feedback": "\u554F\u984C\u306E\u30D5\u30A3\u30FC\u30C9\u30D0\u30C3\u30AF",
468
520
  "system.settings.section_appearance": "\u5916\u89B3",
469
521
  "system.settings.section_security": "\u30A2\u30AB\u30A6\u30F3\u30C8\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3",
470
- "system.settings.section_more": "\u305D\u306E\u4ED6\u30FB\u30DF\u30CB\u30D7\u30ED\u30B0\u30E9\u30E0",
522
+ "system.settings.section_more": "\u305D\u306E\u4ED6\u306E\u30B5\u30FC\u30D3\u30B9",
471
523
  "system.settings.go_ask": "\u8CEA\u554F\u3057\u3066\u307F\u3088\u3046",
524
+ "system.settings.password_title": "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5909\u66F4",
525
+ "system.settings.password_action": "\u5909\u66F4\u3059\u308B",
526
+ "system.settings.password_description": "\u30ED\u30B0\u30A4\u30F3 \u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u66F4\u65B0\u3057\u3066\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u4FDD\u8B77\u3057\u307E\u3059\u3002",
527
+ "system.settings.password_current": "\u73FE\u5728\u306E\u30D1\u30B9\u30EF\u30FC\u30C9",
528
+ "system.settings.password_current_placeholder": "\u73FE\u5728\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
529
+ "system.settings.password_new": "\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9",
530
+ "system.settings.password_new_placeholder": "\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
531
+ "system.settings.password_strength": "\u30D1\u30B9\u30EF\u30FC\u30C9\u5F37\u5EA6",
532
+ "system.settings.password_strength_empty": "\u672A\u5165\u529B",
533
+ "system.settings.password_strength_low": "\u5F31\u3044",
534
+ "system.settings.password_strength_medium": "\u666E\u901A",
535
+ "system.settings.password_strength_high": "\u5F37\u3044",
536
+ "system.settings.password_policy_default": "\u5927\u6587\u5B57\u30FB\u5C0F\u6587\u5B57\u3001\u6570\u5B57\u3001\u8A18\u53F7\u3092\u542B\u3080\u5F37\u529B\u306A\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
537
+ "system.settings.password_policy_min_length": "{count} \u6587\u5B57\u4EE5\u4E0A",
538
+ "system.settings.password_policy_complexity": "{count} \u7A2E\u985E\u4EE5\u4E0A\u306E\u6587\u5B57",
539
+ "system.settings.password_policy_history": "\u6700\u8FD1\u306E {count} \u500B\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u518D\u5229\u7528\u3067\u304D\u307E\u305B\u3093",
540
+ "system.settings.password_policy_max_age": "\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9593\u306F {count} \u65E5\u3067\u3059",
541
+ "system.settings.password_policy_no_expiry": "\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u7121\u671F\u9650\u3067\u3059",
542
+ "system.settings.password_policy_separator": "\u3001",
543
+ "system.settings.password_confirm": "\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u78BA\u8A8D",
544
+ "system.settings.password_confirm_placeholder": "\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u3082\u3046\u4E00\u5EA6\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
545
+ "system.settings.password_policy_loading": "\u30D1\u30B9\u30EF\u30FC\u30C9 \u30DD\u30EA\u30B7\u30FC\u3092\u8AAD\u307F\u8FBC\u3093\u3067\u3044\u307E\u3059",
546
+ "system.settings.password_required": "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u3059\u3079\u3066\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
547
+ "system.settings.password_mismatch": "\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093",
548
+ "system.settings.password_submit": "\u5909\u66F4\u3092\u78BA\u5B9A",
549
+ "system.settings.password_updated": "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5909\u66F4\u3057\u307E\u3057\u305F\u3002\u518D\u5EA6\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u304F\u3060\u3055\u3044",
472
550
  "system.settings.logout_confirm": "\u30ED\u30B0\u30A2\u30A6\u30C8\u3057\u307E\u3059\u304B?",
473
551
  "system.settings.logout_failed": "\u30ED\u30B0\u30A2\u30A6\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
474
552
  "system.settings.title": "\u8A2D\u5B9A",
@@ -633,8 +711,34 @@ var zh_TW_default = {
633
711
  "system.settings.feedback": "\u554F\u984C\u53CD\u994B",
634
712
  "system.settings.section_appearance": "\u5916\u89C0",
635
713
  "system.settings.section_security": "\u5E33\u6236\u5B89\u5168",
636
- "system.settings.section_more": "\u66F4\u591A\u30FB\u5C0F\u7A0B\u5F0F\u7AEF",
714
+ "system.settings.section_more": "\u66F4\u591A\u670D\u52D9",
637
715
  "system.settings.go_ask": "\u53BB\u63D0\u554F",
716
+ "system.settings.password_title": "\u4FEE\u6539\u5BC6\u78BC",
717
+ "system.settings.password_action": "\u524D\u5F80\u4FEE\u6539",
718
+ "system.settings.password_description": "\u66F4\u65B0\u76EE\u524D\u767B\u5165\u5BC6\u78BC\uFF0C\u4FDD\u969C\u8CEC\u6236\u5B89\u5168\u3002",
719
+ "system.settings.password_current": "\u76EE\u524D\u5BC6\u78BC",
720
+ "system.settings.password_current_placeholder": "\u8ACB\u8F38\u5165\u76EE\u524D\u5BC6\u78BC",
721
+ "system.settings.password_new": "\u65B0\u5BC6\u78BC",
722
+ "system.settings.password_new_placeholder": "\u8ACB\u8F38\u5165\u65B0\u5BC6\u78BC",
723
+ "system.settings.password_strength": "\u5BC6\u78BC\u5F37\u5EA6",
724
+ "system.settings.password_strength_empty": "\u672A\u8F38\u5165",
725
+ "system.settings.password_strength_low": "\u8F03\u5F31",
726
+ "system.settings.password_strength_medium": "\u4E2D\u7B49",
727
+ "system.settings.password_strength_high": "\u8F03\u5F37",
728
+ "system.settings.password_policy_default": "\u8ACB\u8A2D\u5B9A\u5305\u542B\u5927\u5C0F\u5BEB\u5B57\u6BCD\u3001\u6578\u5B57\u548C\u7B26\u865F\u7684\u9AD8\u5F37\u5EA6\u5BC6\u78BC\u3002",
729
+ "system.settings.password_policy_min_length": "\u81F3\u5C11 {count} \u500B\u5B57\u5143",
730
+ "system.settings.password_policy_complexity": "\u81F3\u5C11\u7B26\u5408 {count} \u985E\u5B57\u5143",
731
+ "system.settings.password_policy_history": "\u4E0D\u80FD\u91CD\u8907\u6700\u8FD1 {count} \u500B\u5BC6\u78BC",
732
+ "system.settings.password_policy_max_age": "\u5BC6\u78BC\u6709\u6548\u671F {count} \u5929",
733
+ "system.settings.password_policy_no_expiry": "\u5BC6\u78BC\u9577\u671F\u6709\u6548",
734
+ "system.settings.password_policy_separator": "\uFF1B",
735
+ "system.settings.password_confirm": "\u78BA\u8A8D\u65B0\u5BC6\u78BC",
736
+ "system.settings.password_confirm_placeholder": "\u8ACB\u518D\u6B21\u8F38\u5165\u65B0\u5BC6\u78BC",
737
+ "system.settings.password_policy_loading": "\u6B63\u5728\u8B80\u53D6\u5BC6\u78BC\u7B56\u7565",
738
+ "system.settings.password_required": "\u8ACB\u5B8C\u6574\u586B\u5BEB\u5BC6\u78BC",
739
+ "system.settings.password_mismatch": "\u5169\u6B21\u8F38\u5165\u7684\u65B0\u5BC6\u78BC\u4E0D\u4E00\u81F4",
740
+ "system.settings.password_submit": "\u78BA\u8A8D\u4FEE\u6539",
741
+ "system.settings.password_updated": "\u5BC6\u78BC\u4FEE\u6539\u6210\u529F\uFF0C\u8ACB\u91CD\u65B0\u767B\u5165",
638
742
  "system.settings.logout_confirm": "\u662F\u5426\u9000\u51FA\u767B\u5165\uFF1F",
639
743
  "system.settings.logout_failed": "\u9000\u51FA\u767B\u5165\u5931\u6557",
640
744
  "system.settings.title": "\u8A2D\u5B9A",
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "type": "git",
8
8
  "url": "git@github.com:liujitcn/kratos-admin.git"
9
9
  },
10
- "version": "0.1.1",
10
+ "version": "0.1.4",
11
11
  "type": "module",
12
12
  "files": [
13
13
  "dist",
@@ -39,8 +39,8 @@
39
39
  "@tarojs/components": "4.2.1",
40
40
  "@tarojs/taro": "4.2.1",
41
41
  "react": "18.3.1",
42
- "@liujitcn/kratos-taro-app-core": "^0.1.1",
43
- "@liujitcn/kratos-taro-app-ui": "^0.1.1"
42
+ "@liujitcn/kratos-taro-app-ui": "^0.1.4",
43
+ "@liujitcn/kratos-taro-app-core": "^0.1.4"
44
44
  },
45
45
  "scripts": {
46
46
  "build": "pnpm run build:entries && pnpm pack --pack-destination ../../../dist/npm",
@@ -11,7 +11,7 @@ page {
11
11
  }
12
12
 
13
13
  .my-content {
14
- padding: 0 20px calc(40px + env(safe-area-inset-bottom));
14
+ padding: 0 20px var(--kratos-tab-bar-space, calc(104px + env(safe-area-inset-bottom)));
15
15
  }
16
16
 
17
17
  .my-stack {
@@ -101,8 +101,34 @@
101
101
  "system.settings.feedback": "Feedback",
102
102
  "system.settings.section_appearance": "Appearance",
103
103
  "system.settings.section_security": "Account security",
104
- "system.settings.section_more": "More · Mini Program",
104
+ "system.settings.section_more": "More Services",
105
105
  "system.settings.go_ask": "Ask now",
106
+ "system.settings.password_title": "Change password",
107
+ "system.settings.password_action": "Change",
108
+ "system.settings.password_description": "Update your login password to keep your account secure.",
109
+ "system.settings.password_current": "Current password",
110
+ "system.settings.password_current_placeholder": "Enter your current password",
111
+ "system.settings.password_new": "New password",
112
+ "system.settings.password_new_placeholder": "Enter a new password",
113
+ "system.settings.password_strength": "Password strength",
114
+ "system.settings.password_strength_empty": "Not entered",
115
+ "system.settings.password_strength_low": "Weak",
116
+ "system.settings.password_strength_medium": "Medium",
117
+ "system.settings.password_strength_high": "Strong",
118
+ "system.settings.password_policy_default": "Use a strong password with uppercase and lowercase letters, numbers, and symbols.",
119
+ "system.settings.password_policy_min_length": "At least {count} characters",
120
+ "system.settings.password_policy_complexity": "At least {count} character types",
121
+ "system.settings.password_policy_history": "Do not reuse the last {count} passwords",
122
+ "system.settings.password_policy_max_age": "Password expires in {count} days",
123
+ "system.settings.password_policy_no_expiry": "Password does not expire",
124
+ "system.settings.password_policy_separator": "; ",
125
+ "system.settings.password_confirm": "Confirm new password",
126
+ "system.settings.password_confirm_placeholder": "Enter the new password again",
127
+ "system.settings.password_policy_loading": "Loading password policy",
128
+ "system.settings.password_required": "Complete all password fields",
129
+ "system.settings.password_mismatch": "The new passwords do not match",
130
+ "system.settings.password_submit": "Change password",
131
+ "system.settings.password_updated": "Password changed. Please sign in again",
106
132
  "system.settings.logout_confirm": "Log out now?",
107
133
  "system.settings.logout_failed": "Logout failed",
108
134
  "system.settings.title": "Settings",
@@ -101,8 +101,34 @@
101
101
  "system.settings.feedback": "問題のフィードバック",
102
102
  "system.settings.section_appearance": "外観",
103
103
  "system.settings.section_security": "アカウントセキュリティ",
104
- "system.settings.section_more": "その他・ミニプログラム",
104
+ "system.settings.section_more": "その他のサービス",
105
105
  "system.settings.go_ask": "質問してみよう",
106
+ "system.settings.password_title": "パスワードを変更",
107
+ "system.settings.password_action": "変更する",
108
+ "system.settings.password_description": "ログイン パスワードを更新してアカウントを保護します。",
109
+ "system.settings.password_current": "現在のパスワード",
110
+ "system.settings.password_current_placeholder": "現在のパスワードを入力してください",
111
+ "system.settings.password_new": "新しいパスワード",
112
+ "system.settings.password_new_placeholder": "新しいパスワードを入力してください",
113
+ "system.settings.password_strength": "パスワード強度",
114
+ "system.settings.password_strength_empty": "未入力",
115
+ "system.settings.password_strength_low": "弱い",
116
+ "system.settings.password_strength_medium": "普通",
117
+ "system.settings.password_strength_high": "強い",
118
+ "system.settings.password_policy_default": "大文字・小文字、数字、記号を含む強力なパスワードを設定してください。",
119
+ "system.settings.password_policy_min_length": "{count} 文字以上",
120
+ "system.settings.password_policy_complexity": "{count} 種類以上の文字",
121
+ "system.settings.password_policy_history": "最近の {count} 個のパスワードは再利用できません",
122
+ "system.settings.password_policy_max_age": "パスワードの有効期間は {count} 日です",
123
+ "system.settings.password_policy_no_expiry": "パスワードは無期限です",
124
+ "system.settings.password_policy_separator": "、",
125
+ "system.settings.password_confirm": "新しいパスワードの確認",
126
+ "system.settings.password_confirm_placeholder": "新しいパスワードをもう一度入力してください",
127
+ "system.settings.password_policy_loading": "パスワード ポリシーを読み込んでいます",
128
+ "system.settings.password_required": "パスワードをすべて入力してください",
129
+ "system.settings.password_mismatch": "新しいパスワードが一致しません",
130
+ "system.settings.password_submit": "変更を確定",
131
+ "system.settings.password_updated": "パスワードを変更しました。再度ログインしてください",
106
132
  "system.settings.logout_confirm": "ログアウトしますか?",
107
133
  "system.settings.logout_failed": "ログアウトに失敗しました",
108
134
  "system.settings.title": "設定",
@@ -101,8 +101,34 @@
101
101
  "system.settings.feedback": "问题反馈",
102
102
  "system.settings.section_appearance": "外观",
103
103
  "system.settings.section_security": "账户安全",
104
- "system.settings.section_more": "更多 · 小程序端",
104
+ "system.settings.section_more": "更多服务",
105
105
  "system.settings.go_ask": "去提问",
106
+ "system.settings.password_title": "修改密码",
107
+ "system.settings.password_action": "前往修改",
108
+ "system.settings.password_description": "更新当前登录密码,保持账户安全。",
109
+ "system.settings.password_current": "当前密码",
110
+ "system.settings.password_current_placeholder": "请输入当前密码",
111
+ "system.settings.password_new": "新密码",
112
+ "system.settings.password_new_placeholder": "请输入新密码",
113
+ "system.settings.password_strength": "密码强度",
114
+ "system.settings.password_strength_empty": "未输入",
115
+ "system.settings.password_strength_low": "较弱",
116
+ "system.settings.password_strength_medium": "中等",
117
+ "system.settings.password_strength_high": "较强",
118
+ "system.settings.password_policy_default": "请设置包含大小写字母、数字和符号的高强度密码。",
119
+ "system.settings.password_policy_min_length": "至少 {count} 个字符",
120
+ "system.settings.password_policy_complexity": "至少满足 {count} 类字符",
121
+ "system.settings.password_policy_history": "不能重复最近 {count} 个密码",
122
+ "system.settings.password_policy_max_age": "密码有效期 {count} 天",
123
+ "system.settings.password_policy_no_expiry": "密码长期有效",
124
+ "system.settings.password_policy_separator": ";",
125
+ "system.settings.password_confirm": "确认新密码",
126
+ "system.settings.password_confirm_placeholder": "请再次输入新密码",
127
+ "system.settings.password_policy_loading": "正在读取密码策略",
128
+ "system.settings.password_required": "请完整填写密码",
129
+ "system.settings.password_mismatch": "两次输入的新密码不一致",
130
+ "system.settings.password_submit": "确认修改",
131
+ "system.settings.password_updated": "密码修改成功,请重新登录",
106
132
  "system.settings.logout_confirm": "是否退出登录?",
107
133
  "system.settings.logout_failed": "退出登录失败",
108
134
  "system.settings.title": "设置",
@@ -101,8 +101,34 @@
101
101
  "system.settings.feedback": "問題反饋",
102
102
  "system.settings.section_appearance": "外觀",
103
103
  "system.settings.section_security": "帳戶安全",
104
- "system.settings.section_more": "更多・小程式端",
104
+ "system.settings.section_more": "更多服務",
105
105
  "system.settings.go_ask": "去提問",
106
+ "system.settings.password_title": "修改密碼",
107
+ "system.settings.password_action": "前往修改",
108
+ "system.settings.password_description": "更新目前登入密碼,保障賬戶安全。",
109
+ "system.settings.password_current": "目前密碼",
110
+ "system.settings.password_current_placeholder": "請輸入目前密碼",
111
+ "system.settings.password_new": "新密碼",
112
+ "system.settings.password_new_placeholder": "請輸入新密碼",
113
+ "system.settings.password_strength": "密碼強度",
114
+ "system.settings.password_strength_empty": "未輸入",
115
+ "system.settings.password_strength_low": "較弱",
116
+ "system.settings.password_strength_medium": "中等",
117
+ "system.settings.password_strength_high": "較強",
118
+ "system.settings.password_policy_default": "請設定包含大小寫字母、數字和符號的高強度密碼。",
119
+ "system.settings.password_policy_min_length": "至少 {count} 個字元",
120
+ "system.settings.password_policy_complexity": "至少符合 {count} 類字元",
121
+ "system.settings.password_policy_history": "不能重複最近 {count} 個密碼",
122
+ "system.settings.password_policy_max_age": "密碼有效期 {count} 天",
123
+ "system.settings.password_policy_no_expiry": "密碼長期有效",
124
+ "system.settings.password_policy_separator": ";",
125
+ "system.settings.password_confirm": "確認新密碼",
126
+ "system.settings.password_confirm_placeholder": "請再次輸入新密碼",
127
+ "system.settings.password_policy_loading": "正在讀取密碼策略",
128
+ "system.settings.password_required": "請完整填寫密碼",
129
+ "system.settings.password_mismatch": "兩次輸入的新密碼不一致",
130
+ "system.settings.password_submit": "確認修改",
131
+ "system.settings.password_updated": "密碼修改成功,請重新登入",
106
132
  "system.settings.logout_confirm": "是否退出登入?",
107
133
  "system.settings.logout_failed": "退出登入失敗",
108
134
  "system.settings.title": "設定",
@@ -8,7 +8,7 @@ import type { AiKnowledgeOption } from '../../../../rpc/base/v1/ai_knowledge'
8
8
  import { fallbackModelDisplayName } from '../modelDisplay'
9
9
  import KnowledgePicker from './KnowledgePicker'
10
10
  import ModelPicker from './ModelPicker'
11
- import './composer.scss'
11
+ import './Composer.scss'
12
12
 
13
13
  /** AI 助手输入框与模型选择器参数。 */
14
14
  type ComposerProps = {
@@ -88,7 +88,7 @@ export default function Composer(props: ComposerProps) {
88
88
  <Text className='composer-model-chip__label'>
89
89
  {selectedModelDisplayName || props.modelPlaceholder}
90
90
  </Text>
91
- <Text className='composer-model-chip__chevron'>▾</Text>
91
+ <UniIcon type='down' size={12} color={iconColor} />
92
92
  </View>
93
93
  <View
94
94
  className={`composer-model-chip${props.sending || !props.knowledgeOptions.length ? ' is-disabled' : ''}${props.knowledgeIds.length ? ' is-selected' : ''}`}
@@ -100,7 +100,7 @@ export default function Composer(props: ComposerProps) {
100
100
  ? t('system.ai.knowledge.selected_count', { count: props.knowledgeIds.length })
101
101
  : t('system.ai.knowledge.title')}
102
102
  </Text>
103
- <Text className='composer-model-chip__chevron'>▾</Text>
103
+ <UniIcon type='down' size={12} color={iconColor} />
104
104
  </View>
105
105
  <View className='composer-main'>
106
106
  <Button className='attach-button' hoverClass='none' onClick={props.onAttach}>
@@ -1,7 +1,7 @@
1
1
  import { ScrollView, Text, View } from '@tarojs/components'
2
2
  import { t } from '@liujitcn/kratos-taro-app-core'
3
3
  import type { AiKnowledgeOption } from '../../../../rpc/base/v1/ai_knowledge'
4
- import './knowledge-picker.scss'
4
+ import './KnowledgePicker.scss'
5
5
 
6
6
  type KnowledgePickerProps = {
7
7
  options: AiKnowledgeOption[]
@@ -3,7 +3,7 @@ import { useMemo } from 'react'
3
3
  import { t } from '@liujitcn/kratos-taro-app-core'
4
4
  import type { AiProviderModelOption } from '../../../../rpc/base/v1/ai_provider'
5
5
  import { fallbackModelDisplayName } from '../modelDisplay'
6
- import './model-picker.scss'
6
+ import './ModelPicker.scss'
7
7
 
8
8
  type PickerModel = {
9
9
  name: string
@@ -2,7 +2,7 @@ import { Button, Input, ScrollView, Text, View } from '@tarojs/components'
2
2
  import { UniIcon } from '@liujitcn/kratos-taro-app-ui'
3
3
  import { t, useI18n, useThemeStore } from '@liujitcn/kratos-taro-app-core'
4
4
  import type { AiSession } from '../../../../rpc/base/v1/ai_session'
5
- import './session-drawer.scss'
5
+ import './SessionDrawer.scss'
6
6
 
7
7
  type SessionDrawerProps = {
8
8
  open: boolean
@@ -2,7 +2,7 @@ import { Button, Text, View } from '@tarojs/components'
2
2
  import { UniIcon } from '@liujitcn/kratos-taro-app-ui'
3
3
  import { t, useI18n, useThemeStore } from '@liujitcn/kratos-taro-app-core'
4
4
  import type { AiShortcut } from '../../../../rpc/base/v1/ai_tool'
5
- import './welcome-panel.scss'
5
+ import './WelcomePanel.scss'
6
6
 
7
7
  type WelcomePanelProps = {
8
8
  greetingMessage: string
@@ -13,6 +13,7 @@
13
13
  .composer {
14
14
  flex-shrink: 0;
15
15
  width: 100%;
16
+ margin-bottom: var(--kratos-tab-bar-space, calc(104px + env(safe-area-inset-bottom)));
16
17
  padding: 14px 24px calc(18px + env(safe-area-inset-bottom));
17
18
  overflow: hidden;
18
19
  background: var(--kratos-color-surface, #fff);
@@ -57,13 +58,6 @@
57
58
  white-space: nowrap;
58
59
  }
59
60
 
60
- .composer-model-chip__chevron {
61
- flex-shrink: 0;
62
- color: var(--kratos-color-text-muted, #5a7083);
63
- font-size: 22px;
64
- line-height: 22px;
65
- }
66
-
67
61
  .composer-main {
68
62
  display: flex;
69
63
  align-items: center;
@@ -145,6 +139,33 @@
145
139
 
146
140
  .composer-placeholder { color: var(--kratos-color-text-dim, #9aabbb); font-size: 29px; }
147
141
 
142
+ /* H5 的 Taro textarea 是自定义宿主,样式需要落到内部原生 textarea。 */
143
+ /* #ifdef h5 */
144
+ .composer-input {
145
+ padding: 0;
146
+ }
147
+
148
+ .composer-input .taro-textarea {
149
+ width: 100%;
150
+ min-height: 42px;
151
+ max-height: 126px;
152
+ padding: 14px 0;
153
+ border: 0;
154
+ outline: 0;
155
+ color: var(--kratos-color-text, #102232);
156
+ font-size: 29px;
157
+ line-height: 42px;
158
+ background: transparent;
159
+ resize: none;
160
+ }
161
+
162
+ .composer-input .taro-textarea::placeholder {
163
+ color: var(--kratos-color-text-dim, #9aabbb);
164
+ font-size: 29px;
165
+ opacity: 1;
166
+ }
167
+ /* #endif */
168
+
148
169
  .voice-button,
149
170
  .send-button {
150
171
  flex-shrink: 0;
@@ -18,14 +18,14 @@ page {
18
18
 
19
19
  .ai-navbar {
20
20
  flex-shrink: 0;
21
- padding: 0 24px;
21
+ padding: 0 20px;
22
22
  }
23
23
 
24
24
  .ai-body {
25
25
  flex: 1;
26
26
  min-height: 0;
27
27
  box-sizing: border-box;
28
- padding: 28px 24px 10px;
28
+ padding: 28px 20px 10px;
29
29
  }
30
30
 
31
31
  .chat-list { padding-bottom: 24px; }
@@ -1,11 +1,11 @@
1
1
  import { useLoad } from '@tarojs/taro'
2
- import { Button, RichText, Text, View } from '@tarojs/components'
2
+ import { RichText, Text, View } from '@tarojs/components'
3
3
  import { useState } from 'react'
4
- import { KratosNavBar, navigateAppView, t, useThemeStore } from '@liujitcn/kratos-taro-app-core'
4
+ import { KratosNavBar, t, useThemeStore } from '@liujitcn/kratos-taro-app-core'
5
5
  import { UniIcon } from '@liujitcn/kratos-taro-app-ui'
6
6
  import { defNotificationService } from '../../../api/base/v1/notification'
7
7
  import type { Notification } from '../../../rpc/base/v1/notification'
8
- import { MessageActionType, MessageContentFormat } from '../../../rpc/base/v1/notification'
8
+ import { MessageContentFormat } from '../../../rpc/base/v1/notification'
9
9
  import { resolvePersistedMessage } from '../../../utils/persisted-message'
10
10
  import { resolveMessageCategoryIcon } from './icons'
11
11
  import './message.scss'
@@ -27,27 +27,6 @@ export default function MessageDetailPage() {
27
27
  if (!value.read_at) await defNotificationService.MarkNotificationRead({ ids: [id] })
28
28
  }
29
29
 
30
- /** 执行通知携带的稳定 viewKey 动作。 */
31
- function openAction() {
32
- if (!detail || detail.action_type !== MessageActionType.MESSAGE_ACTION_TYPE_VIEW_KEY) return
33
- let params: Record<string, string> = {}
34
- if (detail.action_params) {
35
- try {
36
- const value = JSON.parse(detail.action_params) as Record<string, unknown>
37
- if (value && typeof value === 'object' && !Array.isArray(value)) {
38
- params = Object.fromEntries(
39
- Object.entries(value)
40
- .filter(([, item]) => typeof item === 'string' || typeof item === 'number')
41
- .map(([key, item]) => [key, String(item)]),
42
- )
43
- }
44
- } catch {
45
- params = {}
46
- }
47
- }
48
- navigateAppView(detail.action_target, params)
49
- }
50
-
51
30
  return (
52
31
  <View
53
32
  className={`detail-page ${themeStore.theme === 'light' ? 'theme-light' : 'theme-dark'}`}
@@ -74,11 +53,6 @@ export default function MessageDetailPage() {
74
53
  ) : (
75
54
  <Text className='detail-content'>{resolvePersistedMessage(detail.content)}</Text>
76
55
  )}
77
- {detail.action_type === MessageActionType.MESSAGE_ACTION_TYPE_VIEW_KEY && (
78
- <Button className='detail-action' onClick={openAction}>
79
- {t('common.action.view')}
80
- </Button>
81
- )}
82
56
  </>
83
57
  ) : (
84
58
  <View className='detail-loading'>{t('core.status.loading')}</View>
@@ -41,7 +41,7 @@
41
41
  .detail-page {
42
42
  box-sizing: border-box;
43
43
  min-height: 100vh;
44
- padding: 0 30px calc(96px + env(safe-area-inset-bottom));
44
+ padding: 0 20px var(--kratos-tab-bar-space, calc(104px + env(safe-area-inset-bottom)));
45
45
  background: var(--kratos-bg-gradient);
46
46
  color: var(--kratos-color-text);
47
47
  }
@@ -104,16 +104,3 @@
104
104
  .detail-content {
105
105
  white-space: pre-wrap;
106
106
  }
107
-
108
- .detail-action {
109
- width: 100%;
110
- height: 88px;
111
- margin-top: 36px;
112
- border: 1PX solid var(--kratos-color-border-accent);
113
- border-radius: 20px;
114
- background: var(--kratos-color-primary-soft);
115
- color: var(--kratos-color-primary);
116
- font-size: 28px;
117
- font-weight: 700;
118
- line-height: 86px;
119
- }
@@ -6,7 +6,7 @@
6
6
 
7
7
  /* 导航组件统一处理顶部空间,页面只维护内容的水平与底部留白。 */
8
8
  .profile-content {
9
- padding: 0 32px calc(40px + env(safe-area-inset-bottom));
9
+ padding: 0 20px var(--kratos-tab-bar-space, calc(104px + env(safe-area-inset-bottom)));
10
10
  }
11
11
 
12
12
  /* 头像卡 */
@@ -26,6 +26,11 @@
26
26
  min-width: 0;
27
27
  }
28
28
 
29
+ .profile-id .k-pfx__av {
30
+ background: transparent;
31
+ box-shadow: none;
32
+ }
33
+
29
34
  .profile-av-img {
30
35
  width: 100%;
31
36
  height: 100%;
@@ -62,6 +67,17 @@
62
67
  font-size: 25px;
63
68
  }
64
69
 
70
+ /* 原生 radio 在各端默认尺寸不同,只统一视觉比例,保留原生交互。 */
71
+ .profile-radio radio {
72
+ transform: scale(0.9);
73
+ transform-origin: center;
74
+ }
75
+
76
+ .profile-radio taro-radio-core {
77
+ transform: scale(0.6);
78
+ transform-origin: center;
79
+ }
80
+
65
81
  .profile-auth-button {
66
82
  height: 60px;
67
83
  margin: 0;
@@ -0,0 +1,116 @@
1
+ .change-password-entry__icon {
2
+ width: 38px;
3
+ height: 38px;
4
+ }
5
+
6
+ .change-password-dialog {
7
+ position: fixed;
8
+ z-index: 1000;
9
+ inset: 0;
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ padding: 32px;
14
+ background: rgb(0 0 0 / 45%);
15
+ }
16
+
17
+ .change-password-dialog__panel {
18
+ width: min(100%, 680px);
19
+ max-height: calc(100vh - 64px);
20
+ overflow-y: auto;
21
+ background: var(--kratos-color-surface-solid);
22
+ border-radius: 16px;
23
+ box-shadow: 0 20px 64px rgb(0 0 0 / 20%);
24
+ }
25
+
26
+ .change-password-dialog__header {
27
+ display: flex;
28
+ align-items: flex-start;
29
+ justify-content: space-between;
30
+ gap: 20px;
31
+ padding: 28px 32px;
32
+ border-bottom: 1PX solid var(--kratos-color-border);
33
+ }
34
+
35
+ .change-password-dialog__title,
36
+ .change-password-dialog__description,
37
+ .change-password-dialog__label,
38
+ .change-password-dialog__hint,
39
+ .change-password-dialog__error,
40
+ .change-password-strength__tip {
41
+ display: block;
42
+ }
43
+
44
+ .change-password-dialog__title {
45
+ color: var(--kratos-color-text);
46
+ font-size: 34px;
47
+ font-weight: 600;
48
+ }
49
+
50
+ .change-password-dialog__description {
51
+ margin-top: 8px;
52
+ color: var(--kratos-color-text-muted);
53
+ font-size: 24px;
54
+ line-height: 1.5;
55
+ }
56
+
57
+ .change-password-dialog__close {
58
+ flex-shrink: 0;
59
+ padding: 0 8px;
60
+ color: var(--kratos-color-text-muted);
61
+ font-size: 42px;
62
+ line-height: 1;
63
+ }
64
+
65
+ .change-password-dialog__body {
66
+ padding: 32px;
67
+ }
68
+
69
+ .change-password-dialog__label {
70
+ margin-bottom: 12px;
71
+ color: var(--kratos-color-text);
72
+ font-size: 28px;
73
+ }
74
+
75
+ .change-password-dialog__label:not(:first-child) { margin-top: 24px; }
76
+
77
+ .change-password-dialog__input {
78
+ box-sizing: border-box;
79
+ width: 100%;
80
+ height: 84px;
81
+ padding: 0 24px;
82
+ color: var(--kratos-color-text);
83
+ font-size: 30px;
84
+ border: 1PX solid var(--kratos-color-border);
85
+ border-radius: 8px;
86
+ background: var(--kratos-color-surface-2);
87
+ }
88
+
89
+ .change-password-strength {
90
+ margin-top: 20px;
91
+ padding: 18px 20px;
92
+ border: 1PX solid var(--kratos-color-border);
93
+ border-radius: 10px;
94
+ background: var(--kratos-color-surface-2);
95
+ }
96
+
97
+ .change-password-strength__header { display: flex; justify-content: space-between; color: var(--kratos-color-text-muted); font-size: 24px; }
98
+ .change-password-strength__label--empty { color: var(--kratos-color-text-muted); }
99
+ .change-password-strength__label--low { color: var(--kratos-color-danger); }
100
+ .change-password-strength__label--medium { color: var(--kratos-color-warning); }
101
+ .change-password-strength__label--high { color: var(--kratos-color-primary); }
102
+ .change-password-strength__bars { display: flex; gap: 10px; margin-top: 14px; }
103
+ .change-password-strength__bar { flex: 1; height: 10px; border-radius: 6px; background: var(--kratos-color-border); }
104
+ .change-password-strength__bar--low { background: var(--kratos-color-danger); }
105
+ .change-password-strength__bar--medium { background: var(--kratos-color-warning); }
106
+ .change-password-strength__bar--high { background: var(--kratos-color-primary); }
107
+ .change-password-strength__tip { margin-top: 12px; color: var(--kratos-color-text-muted); font-size: 22px; line-height: 1.6; }
108
+ .change-password-dialog__hint,
109
+ .change-password-dialog__error { margin-top: 12px; color: var(--kratos-color-text-muted); font-size: 24px; line-height: 1.5; }
110
+ .change-password-dialog__error { color: var(--kratos-color-danger); }
111
+ .change-password-dialog__footer { display: flex; justify-content: flex-end; gap: 20px; padding: 0 32px 32px; }
112
+ .change-password-dialog__button { min-width: 160px; height: 72px; margin: 0; padding: 0 24px; font-size: 28px; line-height: 72px; border: 0; border-radius: 8px; }
113
+ .change-password-dialog__button::after { border: 0; }
114
+ .change-password-dialog__button--cancel { color: var(--kratos-color-text-muted); background: var(--kratos-color-track); }
115
+ .change-password-dialog__button--confirm { color: var(--kratos-color-on-primary); background: var(--kratos-color-primary); }
116
+ .change-password-dialog__button[disabled] { opacity: 0.6; }
@@ -0,0 +1,227 @@
1
+ import { Button, Image, Input, Text, View } from '@tarojs/components'
2
+ import Taro from '@tarojs/taro'
3
+ import { useMemo, useState } from 'react'
4
+ import {
5
+ useI18n,
6
+ useThemeStore,
7
+ useUserStore,
8
+ } from '@liujitcn/kratos-taro-app-core'
9
+ import { defAccountService } from '@liujitcn/kratos-taro-app-core/api/base/v1/account'
10
+ import {
11
+ encryptWithPublicKey,
12
+ fetchSecretPublicKey,
13
+ } from '@liujitcn/kratos-taro-app-core/utils/secretCrypto'
14
+ import type { CurrentPasswordPolicy } from '@liujitcn/kratos-taro-app-core/rpc/base/v1/account'
15
+ import './ChangePasswordEntry.scss'
16
+
17
+ /** 设置页账户安全中的修改密码入口与弹层。 */
18
+ export default function ChangePasswordEntry() {
19
+ const { t } = useI18n()
20
+ const themeStore = useThemeStore()
21
+ const authenticated = useUserStore((state) => state.isAuthenticated())
22
+ const clearUserData = useUserStore((state) => state.clearUserData)
23
+ const [dialogOpen, setDialogOpen] = useState(false)
24
+ const [submitting, setSubmitting] = useState(false)
25
+ const [policyLoading, setPolicyLoading] = useState(false)
26
+ const [errorMessage, setErrorMessage] = useState('')
27
+ const [oldPassword, setOldPassword] = useState('')
28
+ const [newPassword, setNewPassword] = useState('')
29
+ const [confirmPassword, setConfirmPassword] = useState('')
30
+ const [passwordPolicy, setPasswordPolicy] = useState<CurrentPasswordPolicy>()
31
+
32
+ const passwordIcon = useMemo(
33
+ () =>
34
+ `data:image/svg+xml;charset=utf-8,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="${themeStore.colors.aiWarning}" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="10" width="16" height="10" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/><path d="M12 14v2"/></svg>`)}`,
35
+ [themeStore.colors.aiWarning],
36
+ )
37
+
38
+ const strengthScore = useMemo(() => {
39
+ if (!newPassword) return 0
40
+ let score = 0
41
+ if (/[a-z]/.test(newPassword)) score += 1
42
+ if (/[A-Z]/.test(newPassword)) score += 1
43
+ if (/\d/.test(newPassword)) score += 1
44
+ if (/[^A-Za-z0-9]/.test(newPassword)) score += 1
45
+ if (score >= 4) return 3
46
+ if (score === 3) return 2
47
+ return 1
48
+ }, [newPassword])
49
+
50
+ const strengthLevel = strengthScore === 0 ? 'empty' : strengthScore === 1 ? 'low' : strengthScore === 2 ? 'medium' : 'high'
51
+ const policyTip = passwordPolicy
52
+ ? [
53
+ t('system.settings.password_policy_min_length', { count: passwordPolicy.min_length }),
54
+ t('system.settings.password_policy_complexity', {
55
+ count: passwordPolicy.min_complexity_classes,
56
+ }),
57
+ ...(passwordPolicy.history_count > 0
58
+ ? [t('system.settings.password_policy_history', { count: passwordPolicy.history_count })]
59
+ : []),
60
+ passwordPolicy.max_age_days > 0
61
+ ? t('system.settings.password_policy_max_age', { count: passwordPolicy.max_age_days })
62
+ : t('system.settings.password_policy_no_expiry'),
63
+ ].join(t('system.settings.password_policy_separator'))
64
+ : t('system.settings.password_policy_default')
65
+
66
+ const loadPasswordPolicy = async () => {
67
+ setPolicyLoading(true)
68
+ try {
69
+ setPasswordPolicy(await defAccountService.GetCurrentPasswordPolicy({}))
70
+ } catch {
71
+ setPasswordPolicy(undefined)
72
+ } finally {
73
+ setPolicyLoading(false)
74
+ }
75
+ }
76
+
77
+ const openDialog = () => {
78
+ if (!authenticated) return
79
+ setDialogOpen(true)
80
+ setErrorMessage('')
81
+ if (!passwordPolicy && !policyLoading) void loadPasswordPolicy()
82
+ }
83
+
84
+ const closeDialog = () => {
85
+ if (submitting) return
86
+ setDialogOpen(false)
87
+ setOldPassword('')
88
+ setNewPassword('')
89
+ setConfirmPassword('')
90
+ setErrorMessage('')
91
+ }
92
+
93
+ const handleSubmit = async () => {
94
+ if (submitting) return
95
+ if (!oldPassword || !newPassword || !confirmPassword) {
96
+ setErrorMessage(t('system.settings.password_required'))
97
+ return
98
+ }
99
+ if (newPassword !== confirmPassword) {
100
+ setErrorMessage(t('system.settings.password_mismatch'))
101
+ return
102
+ }
103
+ setSubmitting(true)
104
+ setErrorMessage('')
105
+ try {
106
+ const publicKey = await fetchSecretPublicKey()
107
+ await defAccountService.UpdateUserPassword({
108
+ user_password: {
109
+ old_pwd: await encryptWithPublicKey(publicKey, oldPassword),
110
+ new_pwd: await encryptWithPublicKey(publicKey, newPassword),
111
+ },
112
+ })
113
+ setDialogOpen(false)
114
+ setOldPassword('')
115
+ setNewPassword('')
116
+ setConfirmPassword('')
117
+ await Taro.showToast({ icon: 'none', title: t('system.settings.password_updated') })
118
+ await clearUserData()
119
+ await Taro.reLaunch({ url: '/pages/login/login' })
120
+ } catch (error) {
121
+ setErrorMessage(error instanceof Error ? error.message : t('common.message.request_error'))
122
+ } finally {
123
+ setSubmitting(false)
124
+ }
125
+ }
126
+
127
+ if (!authenticated) return null
128
+
129
+ return (
130
+ <>
131
+ <View className='k-set-row k-set-row--arrow' onClick={openDialog}>
132
+ <View className='k-set-row__lead'>
133
+ <View className='k-set-row__icon'>
134
+ <Image className='change-password-entry__icon' src={passwordIcon} mode='aspectFit' />
135
+ </View>
136
+ <Text className='k-set-row__title'>{t('system.settings.password_title')}</Text>
137
+ </View>
138
+ <Text className='k-set-row__value settings-row__value'>
139
+ {t('system.settings.password_action')}
140
+ </Text>
141
+ </View>
142
+
143
+ {dialogOpen ? (
144
+ <View className='change-password-dialog' onClick={closeDialog}>
145
+ <View className='change-password-dialog__panel' onClick={(event) => event.stopPropagation()}>
146
+ <View className='change-password-dialog__header'>
147
+ <View>
148
+ <Text className='change-password-dialog__title'>{t('system.settings.password_title')}</Text>
149
+ <Text className='change-password-dialog__description'>
150
+ {t('system.settings.password_description')}
151
+ </Text>
152
+ </View>
153
+ <Text className='change-password-dialog__close' onClick={closeDialog}>×</Text>
154
+ </View>
155
+ <View className='change-password-dialog__body'>
156
+ <Text className='change-password-dialog__label'>{t('system.settings.password_current')}</Text>
157
+ <Input
158
+ className='change-password-dialog__input'
159
+ password
160
+ value={oldPassword}
161
+ placeholder={t('system.settings.password_current_placeholder')}
162
+ onInput={(event) => {
163
+ setOldPassword(event.detail.value)
164
+ setErrorMessage('')
165
+ }}
166
+ />
167
+ <Text className='change-password-dialog__label'>{t('system.settings.password_new')}</Text>
168
+ <Input
169
+ className='change-password-dialog__input'
170
+ password
171
+ value={newPassword}
172
+ placeholder={t('system.settings.password_new_placeholder')}
173
+ onInput={(event) => {
174
+ setNewPassword(event.detail.value)
175
+ setErrorMessage('')
176
+ }}
177
+ />
178
+ <View className='change-password-strength'>
179
+ <View className='change-password-strength__header'>
180
+ <Text>{t('system.settings.password_strength')}</Text>
181
+ <Text className={`change-password-strength__label--${strengthLevel}`}>
182
+ {t(`system.settings.password_strength_${strengthLevel}`)}
183
+ </Text>
184
+ </View>
185
+ <View className='change-password-strength__bars'>
186
+ {[1, 2, 3].map((segment) => (
187
+ <View
188
+ key={segment}
189
+ className={`change-password-strength__bar${segment <= strengthScore ? ` change-password-strength__bar--${strengthLevel}` : ''}`}
190
+ />
191
+ ))}
192
+ </View>
193
+ <Text className='change-password-strength__tip'>{policyTip}</Text>
194
+ </View>
195
+ <Text className='change-password-dialog__label'>{t('system.settings.password_confirm')}</Text>
196
+ <Input
197
+ className='change-password-dialog__input'
198
+ password
199
+ value={confirmPassword}
200
+ placeholder={t('system.settings.password_confirm_placeholder')}
201
+ onInput={(event) => {
202
+ setConfirmPassword(event.detail.value)
203
+ setErrorMessage('')
204
+ }}
205
+ onConfirm={() => void handleSubmit()}
206
+ />
207
+ {policyLoading ? (
208
+ <Text className='change-password-dialog__hint'>
209
+ {t('system.settings.password_policy_loading')}
210
+ </Text>
211
+ ) : null}
212
+ {errorMessage ? <Text className='change-password-dialog__error'>{errorMessage}</Text> : null}
213
+ </View>
214
+ <View className='change-password-dialog__footer'>
215
+ <Button className='change-password-dialog__button change-password-dialog__button--cancel' disabled={submitting} onClick={closeDialog}>
216
+ {t('common.action.cancel')}
217
+ </Button>
218
+ <Button className='change-password-dialog__button change-password-dialog__button--confirm' loading={submitting} onClick={() => void handleSubmit()}>
219
+ {t('system.settings.password_submit')}
220
+ </Button>
221
+ </View>
222
+ </View>
223
+ </View>
224
+ ) : null}
225
+ </>
226
+ )
227
+ }
@@ -6,7 +6,7 @@ page {
6
6
  .settings-viewport {
7
7
  min-height: 100vh;
8
8
  box-sizing: border-box;
9
- padding: 0 32px calc(40px + env(safe-area-inset-bottom));
9
+ padding: 0 20px var(--kratos-tab-bar-space, calc(104px + env(safe-area-inset-bottom)));
10
10
  background: var(--kratos-bg-gradient);
11
11
  }
12
12
 
@@ -14,6 +14,7 @@ import {
14
14
  import { defMfaService } from '@liujitcn/kratos-taro-app-core/api/base/v1/mfa'
15
15
  import { isAuthExpiredError } from '@liujitcn/kratos-taro-app-core/utils/http'
16
16
  import PasswordVerifyDialog from './components/PasswordVerifyDialog'
17
+ import ChangePasswordEntry from './components/ChangePasswordEntry'
17
18
  import './settings.scss'
18
19
 
19
20
  /** SettingsPage 展示应用设置与账号安全操作。 */
@@ -67,7 +68,7 @@ export default function SettingsPage() {
67
68
  feedback: createIcon('<path d="M4 5h16v12H8l-4 4z"/>', violet),
68
69
  contact: createIcon('<path d="M4 5c0 9 6 15 15 15 1 0 2-1 2-2v-2l-4-2-2 2a11 11 0 0 1-5-5l2-2-2-4H6c-1 0-2 1-2 2Z"/>', primary),
69
70
  }
70
- }, [themeStore.theme])
71
+ }, [themeStore.colors.aiPrimary, themeStore.colors.aiWarning, themeStore.colors.aiViolet])
71
72
 
72
73
  const loadMfaStatus = async (force = false) => {
73
74
  if (!useUserStore.getState().isAuthenticated() || (mfaStatusLoading && !force)) return
@@ -172,6 +173,27 @@ export default function SettingsPage() {
172
173
  <KratosNavBar title={t('system.settings.title')} />
173
174
 
174
175
  <View className='settings-content'>
176
+ <View className='k-set-cat'>{t('system.settings.section_security')}</View>
177
+ {authenticated ? (
178
+ <View className='k-set-row k-set-row--arrow' onClick={onMfaTap}>
179
+ <View className='k-set-row__lead'>
180
+ <View className='k-set-row__icon'>
181
+ <Image className='settings-row__icon' src={settingsIcons.mfa} mode='aspectFit' />
182
+ </View>
183
+ <Text className='k-set-row__title'>{t('system.settings.mfa_title')}</Text>
184
+ </View>
185
+ <Text
186
+ className={`k-set-row__value settings-row__value ${
187
+ mfaEnabled ? 'k-set-row__value--on' : ''
188
+ }`}
189
+ >
190
+ {mfaStatusText}
191
+ </Text>
192
+ </View>
193
+ ) : null}
194
+
195
+ {process.env.TARO_ENV === 'h5' ? <ChangePasswordEntry /> : null}
196
+
175
197
  <View className='k-set-cat'>{t('system.settings.section_appearance')}</View>
176
198
  <Picker
177
199
  mode='selector'
@@ -194,25 +216,6 @@ export default function SettingsPage() {
194
216
  </Text>
195
217
  </View>
196
218
  </Picker>
197
-
198
- <View className='k-set-cat'>{t('system.settings.section_security')}</View>
199
- {authenticated ? (
200
- <View className='k-set-row k-set-row--arrow' onClick={onMfaTap}>
201
- <View className='k-set-row__lead'>
202
- <View className='k-set-row__icon'>
203
- <Image className='settings-row__icon' src={settingsIcons.mfa} mode='aspectFit' />
204
- </View>
205
- <Text className='k-set-row__title'>{t('system.settings.mfa_title')}</Text>
206
- </View>
207
- <Text
208
- className={`k-set-row__value settings-row__value ${
209
- mfaEnabled ? 'k-set-row__value--on' : ''
210
- }`}
211
- >
212
- {mfaStatusText}
213
- </Text>
214
- </View>
215
- ) : null}
216
219
  <Picker
217
220
  mode='selector'
218
221
  range={localeLabels}