优化
This commit is contained in:
@@ -4,6 +4,7 @@ import test from 'node:test'
|
||||
|
||||
const loginSource = readFileSync(new URL('./LoginView.vue', import.meta.url), 'utf8')
|
||||
const registerSource = readFileSync(new URL('./RegisterView.vue', import.meta.url), 'utf8')
|
||||
const authShellSource = readFileSync(new URL('../components/AuthShell.vue', import.meta.url), 'utf8')
|
||||
const legalSource = readFileSync(new URL('./LegalDocumentView.vue', import.meta.url), 'utf8')
|
||||
const legalDocumentsSource = readFileSync(new URL('../legalDocuments.ts', import.meta.url), 'utf8')
|
||||
const authRoutesSource = readFileSync(new URL('../routes.ts', import.meta.url), 'utf8')
|
||||
@@ -12,6 +13,22 @@ const httpSource = readFileSync(new URL('../../../api/http.ts', import.meta.url)
|
||||
const sessionSource = readFileSync(new URL('../../../api/session.ts', import.meta.url), 'utf8')
|
||||
const authApiSource = readFileSync(new URL('../api/auth.ts', import.meta.url), 'utf8')
|
||||
const mainSource = readFileSync(new URL('../../../main.ts', import.meta.url), 'utf8')
|
||||
const stylesSource = readFileSync(new URL('../../../styles/index.css', import.meta.url), 'utf8')
|
||||
|
||||
test('uses one prototype-inspired responsive shell for login and registration', () => {
|
||||
assert.match(loginSource, /<AuthShell/)
|
||||
assert.match(registerSource, /<AuthShell/)
|
||||
assert.match(authShellSource, /auth-ocean\.jpg/)
|
||||
assert.match(authShellSource, /class="auth-visual"/)
|
||||
assert.match(stylesSource, /\.auth-panel \{[^}]*grid-template-columns:/s)
|
||||
assert.match(stylesSource, /@media \(max-width: 960px\)[\s\S]*?\.auth-visual \{ display: none; \}/)
|
||||
assert.match(stylesSource, /@media \(max-width: 720px\)[\s\S]*?\.register-form-grid \{ grid-template-columns: 1fr; \}/)
|
||||
})
|
||||
|
||||
test('groups the full registration contract without adding out-of-scope sign-in methods', () => {
|
||||
for (const section of ['账号信息', '企业信息', '联系信息']) assert.match(registerSource, new RegExp(section))
|
||||
assert.doesNotMatch(loginSource + registerSource, /微信登录|企业微信登录|短信验证码|邮箱验证码|lang-switcher/)
|
||||
})
|
||||
|
||||
test('matches the backend username login contract', () => {
|
||||
assert.match(loginSource, /label="用户名"/)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { nextTick, reactive, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { ArrowRight, LockKeyhole, UserRound } from '@lucide/vue'
|
||||
import baiyueLogoDark from '@/assets/brand/baiyue-logo-dark.png'
|
||||
import { useAuthStore } from '@/modules/auth/store/auth'
|
||||
import AuthShell from '@/modules/auth/components/AuthShell.vue'
|
||||
|
||||
interface LoginForm {
|
||||
account: string
|
||||
@@ -40,7 +40,11 @@ const rules: FormRules<LoginForm> = {
|
||||
async function submit() {
|
||||
if (!formRef.value || loading.value) return
|
||||
const valid = await formRef.value.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
if (!valid) {
|
||||
await nextTick()
|
||||
document.querySelector<HTMLElement>('.auth-form-panel .el-form-item.is-error input')?.focus()
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
@@ -60,20 +64,20 @@ function showResetHint() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="auth-page">
|
||||
<header class="auth-header">
|
||||
<RouterLink to="/login" class="auth-brand"><img class="auth-brand-logo" :src="baiyueLogoDark" alt="柏悦物流" /></RouterLink>
|
||||
<div>还没有企业账号? <RouterLink to="/register">申请入驻</RouterLink></div>
|
||||
</header>
|
||||
<main class="auth-main">
|
||||
<section class="auth-copy">
|
||||
<h1>跨境物流业务<br />一个工作台完成</h1>
|
||||
<p>从企业成员协作到头程订单跟进,统一管理业务与权限。</p>
|
||||
<div class="auth-facts"><span>企业级权限</span><span>订单全程跟进</span><span>多端业务协同</span></div>
|
||||
</section>
|
||||
<section class="auth-card" aria-labelledby="login-title">
|
||||
<AuthShell
|
||||
switch-text="还没有企业账号?"
|
||||
switch-label="申请入驻"
|
||||
switch-to="/register"
|
||||
visual-title="跨境物流业务,一个工作台完成"
|
||||
visual-description="从企业协作到头程订单跟进,让业务信息与操作权限始终清晰。"
|
||||
:features="['企业级角色与权限', '头程订单全程跟进', '多成员业务协同']"
|
||||
>
|
||||
<div class="auth-form-content auth-form-content--login">
|
||||
<div class="auth-form-heading">
|
||||
<h2 id="login-title">登录客户工作台</h2>
|
||||
<p>企业注册成功后即可登录;提交订单前需完成企业资料审核</p>
|
||||
<p>使用企业账号登录,继续管理您的跨境物流业务。</p>
|
||||
</div>
|
||||
<div class="auth-account-note">企业注册成功后即可登录;提交订单前需完成企业资料审核。</div>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top" size="large" @submit.prevent="submit">
|
||||
<el-form-item label="用户名" prop="account">
|
||||
<el-input v-model="form.account" autocomplete="username" maxlength="64" placeholder="请输入用户名" :prefix-icon="UserRound" />
|
||||
@@ -87,7 +91,6 @@ function showResetHint() {
|
||||
</div>
|
||||
<el-button native-type="submit" class="auth-submit" type="primary" :loading="loading">登录 <ArrowRight :size="17" /></el-button>
|
||||
</el-form>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</AuthShell>
|
||||
</template>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { nextTick, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { ArrowLeft, Building2, CheckCircle2, Mail, Phone } from '@lucide/vue'
|
||||
import baiyueLogoDark from '@/assets/brand/baiyue-logo-dark.png'
|
||||
import { CheckCircle2, Mail, Phone } from '@lucide/vue'
|
||||
import { registerMerchant } from '@/modules/auth/api/auth'
|
||||
import AuthShell from '@/modules/auth/components/AuthShell.vue'
|
||||
|
||||
interface RegisterForm {
|
||||
username: string
|
||||
@@ -60,7 +60,11 @@ const rules: FormRules<RegisterForm> = {
|
||||
async function submit() {
|
||||
if (!formRef.value || submitting.value) return
|
||||
const valid = await formRef.value.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
if (!valid) {
|
||||
await nextTick()
|
||||
document.querySelector<HTMLElement>('.auth-form-panel .el-form-item.is-error input')?.focus()
|
||||
return
|
||||
}
|
||||
|
||||
submitting.value = true
|
||||
try {
|
||||
@@ -90,26 +94,49 @@ async function submit() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="register-page">
|
||||
<header class="register-header">
|
||||
<RouterLink to="/login"><ArrowLeft :size="18" /> 返回登录</RouterLink>
|
||||
<div class="auth-brand"><img class="auth-brand-logo" :src="baiyueLogoDark" alt="柏悦物流" /></div>
|
||||
</header>
|
||||
<main class="register-main">
|
||||
<AuthShell
|
||||
variant="register"
|
||||
switch-text="已有企业账号?"
|
||||
switch-label="立即登录"
|
||||
switch-to="/login"
|
||||
visual-title="加入柏悦,开启高效跨境物流协作"
|
||||
visual-description="创建企业账号后即可进入客户工作台,维护团队、资料与头程订单。"
|
||||
:features="['注册成功即可登录', '企业资料独立审核', '审核期间可维护订单草稿']"
|
||||
>
|
||||
<div class="auth-form-content auth-form-content--register">
|
||||
<template v-if="!submitted">
|
||||
<div class="register-title"><div><Building2 :size="22" /></div><span><h1>企业注册</h1><p>注册成功后即可登录并使用客户工作台,提交订单前需完成企业资料审核。</p></span></div>
|
||||
<div class="auth-form-heading">
|
||||
<h1>企业注册</h1>
|
||||
<p>填写账号与企业基本信息,注册成功后即可登录。</p>
|
||||
</div>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" class="register-form" label-position="top" size="large" @submit.prevent="submit">
|
||||
<div class="form-grid">
|
||||
<el-form-item label="登录用户名" prop="username" required><el-input v-model="form.username" autocomplete="username" maxlength="64" placeholder="4–64 位字母、数字或下划线" /></el-form-item>
|
||||
<el-form-item label="企业名称" prop="companyName" required><el-input v-model="form.companyName" maxlength="100" placeholder="请输入企业营业执照上的名称" /></el-form-item>
|
||||
<el-form-item label="联系人" prop="displayName" required><el-input v-model="form.displayName" maxlength="64" placeholder="请输入联系人姓名" /></el-form-item>
|
||||
<el-form-item label="法定代表人" prop="legalPerson" required><el-input v-model="form.legalPerson" maxlength="64" placeholder="请输入营业执照法定代表人" /></el-form-item>
|
||||
<el-form-item label="法人手机号" prop="legalPhone" required><el-input v-model="form.legalPhone" type="tel" autocomplete="tel" inputmode="numeric" maxlength="11" placeholder="请输入手机号" :prefix-icon="Phone" /></el-form-item>
|
||||
<el-form-item label="联系邮箱" prop="contactEmail"><el-input v-model="form.contactEmail" type="email" autocomplete="email" maxlength="128" placeholder="选填,用于接收业务通知" :prefix-icon="Mail" /></el-form-item>
|
||||
<el-form-item label="国家/地区" prop="countryCode"><el-select v-model="form.countryCode"><el-option label="中国大陆(CN)" value="CN" /></el-select></el-form-item>
|
||||
<el-form-item label="企业地址" prop="address" class="full-row"><el-input v-model="form.address" maxlength="255" placeholder="选填,最多 255 个字符" /></el-form-item>
|
||||
<el-form-item label="登录密码" prop="password" required><el-input v-model="form.password" type="password" autocomplete="new-password" maxlength="72" show-password placeholder="请设置 8–72 位密码" /></el-form-item>
|
||||
</div>
|
||||
<section class="register-section" aria-labelledby="account-section-title">
|
||||
<h2 id="account-section-title">账号信息</h2>
|
||||
<div class="register-form-grid">
|
||||
<el-form-item label="登录用户名" prop="username" required><el-input v-model="form.username" autocomplete="username" maxlength="64" placeholder="4–64 位字母、数字或下划线" /></el-form-item>
|
||||
<el-form-item label="登录密码" prop="password" required><el-input v-model="form.password" type="password" autocomplete="new-password" maxlength="72" show-password placeholder="请设置 8–72 位密码" /></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="register-section" aria-labelledby="company-section-title">
|
||||
<h2 id="company-section-title">企业信息</h2>
|
||||
<div class="register-form-grid">
|
||||
<el-form-item label="企业名称" prop="companyName" class="register-form-full" required><el-input v-model="form.companyName" maxlength="100" placeholder="请输入营业执照上的企业名称" /></el-form-item>
|
||||
<el-form-item label="法定代表人" prop="legalPerson" required><el-input v-model="form.legalPerson" maxlength="64" placeholder="请输入营业执照法定代表人" /></el-form-item>
|
||||
<el-form-item label="国家/地区" prop="countryCode"><el-select v-model="form.countryCode" class="register-select"><el-option label="中国大陆(CN)" value="CN" /></el-select></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="register-section" aria-labelledby="contact-section-title">
|
||||
<h2 id="contact-section-title">联系信息</h2>
|
||||
<div class="register-form-grid">
|
||||
<el-form-item label="联系人" prop="displayName" required><el-input v-model="form.displayName" maxlength="64" placeholder="请输入联系人姓名" /></el-form-item>
|
||||
<el-form-item label="法人手机号" prop="legalPhone" required><el-input v-model="form.legalPhone" type="tel" autocomplete="tel" inputmode="numeric" maxlength="11" placeholder="请输入 11 位手机号" :prefix-icon="Phone" /></el-form-item>
|
||||
<el-form-item label="联系邮箱" prop="contactEmail"><el-input v-model="form.contactEmail" type="email" autocomplete="email" maxlength="128" placeholder="选填,用于接收业务通知" :prefix-icon="Mail" /></el-form-item>
|
||||
<el-form-item label="企业地址" prop="address"><el-input v-model="form.address" maxlength="255" placeholder="选填,最多 255 个字符" /></el-form-item>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-form-item prop="agreement" class="agreement-item">
|
||||
<div class="agreement-control">
|
||||
<el-checkbox v-model="form.agreement"><span class="agreement-required" aria-hidden="true">*</span>我已阅读并同意</el-checkbox>
|
||||
@@ -117,7 +144,7 @@ async function submit() {
|
||||
</div>
|
||||
</el-form-item>
|
||||
<p class="register-security-note">注册成功后账号可立即登录;首次登录需上传营业执照和法人身份证,货代资质证书、银行开户许可证可选填。提交平台审核通过后才能提交订单。</p>
|
||||
<div class="register-actions"><el-button @click="$router.push('/login')">取消</el-button><el-button native-type="submit" type="primary" :loading="submitting">注册企业账号</el-button></div>
|
||||
<el-button native-type="submit" class="register-submit" type="success" :loading="submitting">注册企业账号</el-button>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
@@ -129,6 +156,6 @@ async function submit() {
|
||||
<div class="registration-next-step" role="note"><strong>提交订单前还需完成企业审核</strong><span>登录后请在“企业资料”上传营业执照和法人身份证并提交审核,其他资质可选填。审核期间仍可维护资料、成员和订单草稿。</span></div>
|
||||
<div class="registration-result-actions"><el-button type="primary" @click="router.push({ path: '/login', query: { account: form.username } })">立即登录</el-button></div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</AuthShell>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user