diff --git a/app/components/register/PasswordStrength.vue b/app/components/register/PasswordStrength.vue
new file mode 100644
index 0000000..debcbf8
--- /dev/null
+++ b/app/components/register/PasswordStrength.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
diff --git a/app/components/register/__tests__/PasswordStrength.test.ts b/app/components/register/__tests__/PasswordStrength.test.ts
new file mode 100644
index 0000000..82b70ef
--- /dev/null
+++ b/app/components/register/__tests__/PasswordStrength.test.ts
@@ -0,0 +1,39 @@
+import { describe, it, expect } from 'vitest'
+import { mount } from '@vue/test-utils'
+import PasswordStrength from '../PasswordStrength.vue'
+
+describe('PasswordStrength', () => {
+ it('renders nothing for empty password', () => {
+ const wrapper = mount(PasswordStrength, { props: { password: '' } })
+ expect(wrapper.find('[data-testid="strength-bar"]').exists()).toBe(false)
+ })
+
+ it('score 1 for weak password (only letters, < 8)', () => {
+ const wrapper = mount(PasswordStrength, { props: { password: 'abc' } })
+ expect(wrapper.find('[data-testid="strength-bar"]').attributes('data-score')).toBe('1')
+ expect(wrapper.text()).toContain('弱')
+ })
+
+ it('score 1 for only digits', () => {
+ const wrapper = mount(PasswordStrength, { props: { password: '1234567' } })
+ expect(wrapper.find('[data-testid="strength-bar"]').attributes('data-score')).toBe('1')
+ })
+
+ it('score 2 for letters+digits >= 8 chars', () => {
+ const wrapper = mount(PasswordStrength, { props: { password: 'abc12345' } })
+ expect(wrapper.find('[data-testid="strength-bar"]').attributes('data-score')).toBe('2')
+ expect(wrapper.text()).toContain('中')
+ })
+
+ it('score 3 for upper+lower+digits >= 10 chars', () => {
+ const wrapper = mount(PasswordStrength, { props: { password: 'Abcdef1234' } })
+ expect(wrapper.find('[data-testid="strength-bar"]').attributes('data-score')).toBe('3')
+ expect(wrapper.text()).toContain('强')
+ })
+
+ it('score 4 for upper+lower+digits+special >= 12 chars', () => {
+ const wrapper = mount(PasswordStrength, { props: { password: 'Abcdef1234!@' } })
+ expect(wrapper.find('[data-testid="strength-bar"]').attributes('data-score')).toBe('4')
+ expect(wrapper.text()).toContain('很强')
+ })
+})