办学质量监测教学评价系统
shenrongliang
2025-06-13 11d86cc6c26bb4f709e407acadf4805c2024e79f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<script lang="ts" setup>
import type { LoginCodeParams, VbenFormSchema } from '@vben/common-ui';
 
import type { TenantResp } from '#/api';
 
import { computed, onMounted, ref, useTemplateRef } from 'vue';
 
import { AuthenticationCodeLogin, z } from '@vben/common-ui';
import { DEFAULT_TENANT_ID } from '@vben/constants';
import { $t } from '@vben/locales';
 
import { Alert, message } from 'ant-design-vue';
 
import { tenantList } from '#/api';
import { sendSmsCode } from '#/api/core/captcha';
import { useAuthStore } from '#/store';
 
defineOptions({ name: 'CodeLogin' });
 
const loading = ref(false);
const CODE_LENGTH = 6;
 
const tenantInfo = ref<TenantResp>({
  tenantEnabled: false,
  voList: [],
});
 
const codeLoginRef = useTemplateRef('codeLoginRef');
async function loadTenant() {
  const resp = await tenantList();
  tenantInfo.value = resp;
  // 选中第一个租户
  if (resp.tenantEnabled && resp.voList.length > 0) {
    const firstTenantId = resp.voList[0]!.tenantId;
    codeLoginRef.value?.getFormApi().setFieldValue('tenantId', firstTenantId);
  }
}
 
onMounted(loadTenant);
 
const formSchema = computed((): VbenFormSchema[] => {
  return [
    {
      component: 'VbenSelect',
      componentProps: {
        class: 'bg-background h-[40px] focus:border-primary',
        contentClass: 'max-h-[256px] overflow-y-auto',
        options: tenantInfo.value.voList?.map((item) => ({
          label: item.companyName,
          value: item.tenantId,
        })),
        placeholder: $t('authentication.selectAccount'),
      },
      defaultValue: DEFAULT_TENANT_ID,
      dependencies: {
        if: () => tenantInfo.value.tenantEnabled,
        triggerFields: [''],
      },
      fieldName: 'tenantId',
      label: $t('authentication.selectAccount'),
      rules: z.string().min(1, { message: $t('authentication.selectAccount') }),
    },
    {
      component: 'VbenInput',
      componentProps: {
        placeholder: $t('authentication.mobile'),
      },
      fieldName: 'phoneNumber',
      label: $t('authentication.mobile'),
      rules: z
        .string()
        .min(1, { message: $t('authentication.mobileTip') })
        .refine((v) => /^\d{11}$/.test(v), {
          message: $t('authentication.mobileErrortip'),
        }),
    },
    {
      component: 'VbenPinInput',
      componentProps(_, form) {
        return {
          createText: (countdown: number) => {
            const text =
              countdown > 0
                ? $t('authentication.sendText', [countdown])
                : $t('authentication.sendCode');
            return text;
          },
          // 验证码长度 在这设置
          codeLength: 4,
          placeholder: $t('authentication.code'),
          handleSendCode: async () => {
            const { valid, value } = await form.validateField('phoneNumber');
            if (!valid) {
              // 必须抛异常 不能直接return
              throw new Error('未填写手机号');
            }
            // 调用接口发送
            await sendSmsCode(value);
            message.success('验证码发送成功');
          },
        };
      },
      fieldName: 'code',
      label: $t('authentication.code'),
      rules: z.string().length(CODE_LENGTH, {
        message: $t('authentication.codeTip', [CODE_LENGTH]),
      }),
    },
  ];
});
 
const authStore = useAuthStore();
async function handleLogin(values: LoginCodeParams) {
  try {
    const requestParams: any = {
      tenantId: values.tenantId,
      phonenumber: values.phoneNumber,
      smsCode: values.code,
      grantType: 'sms',
    };
    console.log('login params', requestParams);
    await authStore.authLogin(requestParams);
  } catch (error) {
    console.error(error);
  }
}
</script>
 
<template>
  <div>
    <Alert
      class="mb-4"
      how-icon
      message="测试手机号: 15888888888 正确验证码: 1234 演示使用 不会真的发送"
      type="info"
    />
    <AuthenticationCodeLogin
      ref="codeLoginRef"
      :form-schema="formSchema"
      :loading="loading"
      @submit="handleLogin"
    />
  </div>
</template>