refactor(frontend): 统一使用wd-text组件替换原生text标签,优化页面配置

1.  全局替换普通text标签为wd-text组件,统一文本样式与功能
2.  调整页面全局配置与tabBar配置,按平台动态裁剪无效配置
3.  修复微信小程序端表单item样式兼容问题,添加自定义样式隐藏空left区域
4.  移除登录页冗余的微信一键登录相关代码
This commit is contained in:
zhangtao
2026-08-11 00:49:00 +08:00
parent 50eac1872b
commit 7bbc489c59
21 changed files with 475 additions and 277 deletions
+7 -18
View File
@@ -330,6 +330,7 @@ function getGreeting() {
:interval="4500"
:autoplay="true"
:loop="true"
:adjust-height="false"
>
<template #default="{ index }">
<view class="banner-slide" :class="banners[index].cls" @click="banners[index].onClick">
@@ -398,9 +399,7 @@ function getGreeting() {
<!-- 运营概览 -->
<view class="mb-2 mt-4 flex items-center gap-2 px-3">
<view class="h-3.5 w-1 rounded-full" style="background-color: var(--primary-color, #4F8CFF);" />
<text class="text-3.5 font-bold wot-text-text-main">
{{ t('index.opsOverview') }}
</text>
<wd-text class="text-3.5 wot-text-text-main" :text="t('index.opsOverview')" bold />
</view>
<SkeletonPage v-if="loading && !dashboardStats" :rows="3" />
<view v-else class="mx-3">
@@ -454,17 +453,13 @@ function getGreeting() {
<view id="monitor-section" class="mt-4">
<view class="mb-2 flex items-center gap-2 px-3">
<view class="h-3.5 w-1 rounded-full" style="background-color: var(--danger-color, #EF4444);" />
<text class="text-3.5 font-bold wot-text-text-main">
{{ t('index.sysMonitor') }}
</text>
<wd-text class="text-3.5 wot-text-text-main" :text="t('index.sysMonitor')" bold />
</view>
<!-- 登录趋势折线图 -->
<view class="mx-3 mb-3 rounded-2 p-4 wot-bg-filled-oppo">
<view class="mb-4 flex items-center gap-2">
<text class="text-3.5 font-bold wot-text-text-main">
{{ t('index.loginTrend') }}
</text>
<wd-text class="text-3.5 wot-text-text-main" :text="t('index.loginTrend')" bold />
</view>
<uni-echarts custom-class="h-52 w-full" :option="loginTrendOption" />
</view>
@@ -474,13 +469,9 @@ function getGreeting() {
<view v-if="recentNotices.length > 0" class="mb-2 mt-4 flex items-center justify-between px-3">
<view class="flex items-center gap-2">
<view class="h-3.5 w-1 rounded-full" style="background-color: var(--success-color, #10B981);" />
<text class="text-3.5 font-bold wot-text-text-main">
{{ t('index.latestNotice') }}
</text>
<wd-text class="text-3.5 wot-text-text-main" :text="t('index.latestNotice')" bold />
</view>
<text class="text-3 wot-text-primary" @click="navigateTo('work-notices')">
{{ t('common.all') }}
</text>
<wd-text class="text-3" :text="t('common.all')" type="primary" @click="navigateTo('work-notices')" />
</view>
<view v-if="recentNotices.length > 0" class="mx-3">
<wd-cell-group border custom-class="rounded-2! overflow-hidden">
@@ -492,9 +483,7 @@ function getGreeting() {
@click="navigateTo('work-notices')"
>
<template #label>
<text class="text-2.5 wot-text-text-auxiliary">
{{ item.created_time || '' }}
</text>
<wd-text class="text-2.5 wot-text-text-auxiliary" :text="item.created_time || ''" />
</template>
</wd-cell>
</wd-cell-group>
+13 -6
View File
@@ -85,7 +85,7 @@ function goLogin() {
<view class="forget-form">
<wd-form ref="forgetFormRef" :model="forgetForm" :schema="forgetSchema">
<wd-form-item prop="username">
<wd-form-item prop="username" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="forgetForm.username"
:placeholder="t('common.form.usernamePlaceholder')"
@@ -94,7 +94,7 @@ function goLogin() {
prefix-icon="user"
/>
</wd-form-item>
<wd-form-item prop="new_password">
<wd-form-item prop="new_password" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="forgetForm.new_password"
:placeholder="t('common.form.newPasswordPlaceholder')"
@@ -104,7 +104,7 @@ function goLogin() {
prefix-icon="lock"
/>
</wd-form-item>
<wd-form-item prop="confirmPassword">
<wd-form-item prop="confirmPassword" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="forgetForm.confirmPassword"
:placeholder="t('common.form.confirmNewPlaceholder')"
@@ -121,9 +121,7 @@ function goLogin() {
</view>
<view class="forget-footer">
<text class="forget-footer__link wot-text-primary" @click="goLogin">
{{ t('forget.toLogin') }}
</text>
<wd-text class="forget-footer__link" :text="t('forget.toLogin')" type="primary" @click="goLogin" />
</view>
</view>
</view>
@@ -215,3 +213,12 @@ function goLogin() {
}
}
</style>
<style lang="scss">
/* MP 端兼容:wd-form-item 内部 wd-cell 因 uni-app 插槽静态声明(u-s)误判 label/title 插槽被使用,
showLeft=true 渲染空 left 区域(flex:1 占半宽),H5 端运行时插槽判定无此问题。
本页 form-item 无 title/label/prefix 内容,隐藏 left 安全,保证输入框与登录按钮同宽 */
.forget-card .wd-form-item .wd-cell__left {
display: none;
}
</style>
+20 -96
View File
@@ -7,7 +7,6 @@ import { computed, nextTick, reactive, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import AuthAPI from '@/api/module_system/auth'
import { useI18nNavTitle } from '@/composables/useI18nNavTitle'
import { useWxLogin } from '@/composables/useWxLogin'
import { REMEMBER_ME_KEY } from '@/constants'
import { useConfigStore } from '@/store/configStore'
import { useUserStore } from '@/store/userStore'
@@ -22,7 +21,6 @@ const sliderCaptchaRef = ref<SlideVerifyInstance>()
const loading = ref(false)
const userStore = useUserStore()
const configStore = useConfigStore()
const { wxLogin, wxPhoneLogin } = useWxLogin()
const redirect = ref('/pages/index/index')
/** 规范化 BASE_URL(保证以 / 结尾),用于拼接静态资源路径:H5 下避免 base '/app' 拼出 /appstatic/xxx */
@@ -241,43 +239,6 @@ async function handleOAuth(provider: OAuthProvider) {
uni.showToast({ title: t('login.oauthFailed'), icon: 'none' })
}
}
/** 微信一键登录(仅小程序端显示按钮) */
const wxLoading = ref(false)
async function handleWxLogin() {
if (wxLoading.value)
return
wxLoading.value = true
try {
await wxLogin()
uni.reLaunch({ url: redirect.value })
}
catch {
uni.showToast({ title: t('login.wxLoginFailed'), icon: 'none' })
}
finally {
wxLoading.value = false
}
}
/** 微信手机号登录(配合 open-type="getPhoneNumber") */
async function handleWxPhoneLogin(e: any) {
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
uni.showToast({ title: t('login.phoneAuthCancel'), icon: 'none' })
return
}
wxLoading.value = true
try {
await wxPhoneLogin(e.detail.code)
uni.reLaunch({ url: redirect.value })
}
catch {
uni.showToast({ title: t('login.phoneLoginFailed'), icon: 'none' })
}
finally {
wxLoading.value = false
}
}
</script>
<template>
@@ -288,9 +249,7 @@ async function handleWxPhoneLogin(e: any) {
<text class="brand-title">
{{ brandTitle }}
</text>
<text class="brand-subtitle">
{{ brandSubtitle }}
</text>
<wd-text class="brand-subtitle" :text="brandSubtitle" />
</view>
<!-- Form card -->
@@ -299,39 +258,9 @@ async function handleWxPhoneLogin(e: any) {
{{ t('login.cardTitle') }}
</text>
<!-- 微信一键登录(仅小程序端显示) -->
<!-- #ifdef MP-WEIXIN -->
<view class="wx-login-section">
<wd-button
type="primary"
:loading="wxLoading"
round
block
@click="handleWxLogin"
>
<wd-icon name="wechat" size="18px" color="#FFFFFF" />
<text class="ml-1">
{{ t('login.wxLogin') }}
</text>
</wd-button>
<wd-button
plain
round
block
custom-class="mt-3"
:loading="wxLoading"
open-type="getPhoneNumber"
@getphonenumber="handleWxPhoneLogin"
>
{{ t('login.phoneLogin') }}
</wd-button>
</view>
<wd-divider>{{ t('login.orAccount') }}</wd-divider>
<!-- #endif -->
<wd-form ref="loginFormRef" :model="loginFormData" :schema="loginSchema">
<!-- Username — wot 原生 wd-input,前缀图标走 prefix-icon 属性 -->
<wd-form-item prop="username">
<wd-form-item prop="username" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="loginFormData.username"
:placeholder="t('common.form.usernamePlaceholder')"
@@ -344,7 +273,7 @@ async function handleWxPhoneLogin(e: any) {
</wd-form-item>
<!-- Password — show-password 自动启用密码可见性切换 -->
<wd-form-item prop="password">
<wd-form-item prop="password" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="loginFormData.password"
:placeholder="t('common.form.passwordPlaceholder')"
@@ -358,7 +287,7 @@ async function handleWxPhoneLogin(e: any) {
</wd-form-item>
<!-- Slider Captcha — wd-slide-verify 滑块拖动验证(条件显示) -->
<wd-form-item v-if="captchaState.enable">
<wd-form-item v-if="captchaState.enable" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-slide-verify
ref="sliderCaptchaRef"
:text="t('login.sliderText')"
@@ -373,9 +302,7 @@ async function handleWxPhoneLogin(e: any) {
<wd-checkbox v-model="loginFormData.remember" size="18px">
{{ t('login.remember') }}
</wd-checkbox>
<text class="forgot-link wot-text-primary" @click="goForget">
{{ t('login.forgot') }}
</text>
<wd-text class="forgot-link" :text="t('login.forgot')" type="primary" @click="goForget" />
</view>
<!-- Submit -->
@@ -400,9 +327,7 @@ async function handleWxPhoneLogin(e: any) {
<view class="oauth-btn__icon" style="background: #07C160">
<image class="oauth-btn__iconify" src="/static/icons/wechat.svg" />
</view>
<text class="oauth-btn__label">
{{ t('login.wechat') }}
</text>
<wd-text class="oauth-btn__label" :text="t('login.wechat')" />
</wd-grid-item>
<!-- GitHub -->
@@ -410,9 +335,7 @@ async function handleWxPhoneLogin(e: any) {
<view class="oauth-btn__icon" style="background: #24292F">
<image class="oauth-btn__iconify" src="/static/icons/github.svg" />
</view>
<text class="oauth-btn__label">
{{ t('login.github') }}
</text>
<wd-text class="oauth-btn__label" :text="t('login.github')" />
</wd-grid-item>
<!-- Gitee -->
@@ -420,9 +343,7 @@ async function handleWxPhoneLogin(e: any) {
<view class="oauth-btn__icon" style="background: #C71D23">
<image class="oauth-btn__iconify" src="/static/icons/gitee.svg" />
</view>
<text class="oauth-btn__label">
{{ t('login.gitee') }}
</text>
<wd-text class="oauth-btn__label" :text="t('login.gitee')" />
</wd-grid-item>
<!-- QQ -->
@@ -430,21 +351,15 @@ async function handleWxPhoneLogin(e: any) {
<view class="oauth-btn__icon" style="background: #12B7F5">
<image class="oauth-btn__iconify" src="/static/icons/qq.svg" />
</view>
<text class="oauth-btn__label">
{{ t('login.qq') }}
</text>
<wd-text class="oauth-btn__label" :text="t('login.qq')" />
</wd-grid-item>
</wd-grid>
</view>
<!-- Footer -->
<view class="login-footer">
<text class="login-footer__text">
{{ t('login.noAccount') }}
</text>
<text class="login-footer__link wot-text-primary" @click="goRegister">
{{ t('login.toRegister') }}
</text>
<wd-text class="login-footer__text" :text="t('login.noAccount')" />
<wd-text class="login-footer__link" :text="t('login.toRegister')" type="primary" @click="goRegister" />
</view>
</view>
</template>
@@ -637,3 +552,12 @@ async function handleWxPhoneLogin(e: any) {
}
}
</style>
<style lang="scss">
/* MP 端兼容:wd-form-item 内部 wd-cell 因 uni-app 插槽静态声明(u-s)误判 label/title 插槽被使用,
showLeft=true 渲染空 left 区域(flex:1 占半宽),H5 端运行时插槽判定无此问题。
本页 form-item 无 title/label/prefix 内容,隐藏 left 安全,保证输入框与登录按钮同宽 */
.login-card .wd-form-item .wd-cell__left {
display: none;
}
</style>
+16 -13
View File
@@ -148,7 +148,7 @@ function goLogin() {
<view class="register-form">
<wd-form ref="registerFormRef" :model="registerForm" :schema="registerSchema">
<wd-form-item prop="username">
<wd-form-item prop="username" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="registerForm.username"
:placeholder="t('common.form.usernamePlaceholder')"
@@ -157,7 +157,7 @@ function goLogin() {
prefix-icon="user"
/>
</wd-form-item>
<wd-form-item prop="name">
<wd-form-item prop="name" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="registerForm.name"
:placeholder="t('common.form.nicknamePlaceholder')"
@@ -166,7 +166,7 @@ function goLogin() {
prefix-icon="user"
/>
</wd-form-item>
<wd-form-item prop="password">
<wd-form-item prop="password" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="registerForm.password"
:placeholder="t('common.form.passwordPlaceholder')"
@@ -176,7 +176,7 @@ function goLogin() {
prefix-icon="lock"
/>
</wd-form-item>
<wd-form-item prop="confirmPassword">
<wd-form-item prop="confirmPassword" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="registerForm.confirmPassword"
:placeholder="t('common.form.confirmPlaceholder')"
@@ -193,9 +193,7 @@ function goLogin() {
<wd-checkbox v-model="agreeRead" size="18px">
{{ t('register.agree') }}
</wd-checkbox>
<text class="register-agreement__link wot-text-primary" @click="handleAgreementOpen">
{{ t('register.userAgreement') }}
</text>
<wd-text class="register-agreement__link" :text="t('register.userAgreement')" type="primary" @click="handleAgreementOpen" />
</view>
<wd-button type="primary" round block :loading="submitting" @click="handleSubmit">
@@ -204,12 +202,8 @@ function goLogin() {
</view>
<view class="register-footer">
<text class="register-footer__text">
{{ t('register.hasAccount') }}
</text>
<text class="register-footer__link wot-text-primary" @click="goLogin">
{{ t('register.toLogin') }}
</text>
<wd-text class="register-footer__text" :text="t('register.hasAccount')" />
<wd-text class="register-footer__link" :text="t('register.toLogin')" type="primary" @click="goLogin" />
</view>
</view>
</view>
@@ -323,3 +317,12 @@ function goLogin() {
}
}
</style>
<style lang="scss">
/* MP 端兼容:wd-form-item 内部 wd-cell 因 uni-app 插槽静态声明(u-s)误判 label/title 插槽被使用,
showLeft=true 渲染空 left 区域(flex:1 占半宽),H5 端运行时插槽判定无此问题。
本页 form-item 无 title/label/prefix 内容,隐藏 left 安全,保证输入框与登录按钮同宽 */
.register-card .wd-form-item .wd-cell__left {
display: none;
}
</style>
+1 -3
View File
@@ -231,9 +231,7 @@ async function handleSubmitPassword() {
<view class="mx-3 mb-3">
<view class="mb-2 mt-1 flex items-center gap-2 px-3">
<view class="h-3.5 w-1 rounded-full" style="background-color: var(--primary-color, #4F8CFF);" />
<text class="text-3.5 font-bold wot-text-text-main">
{{ t('common.settings') }}
</text>
<wd-text class="text-3.5 wot-text-text-main" :text="t('common.settings')" bold />
</view>
<wd-cell-group border custom-class="rounded-2! overflow-hidden">
<wd-cell
+5 -7
View File
@@ -112,12 +112,8 @@ const filteredGroups = computed(() => {
<view v-for="(group, gi) in filteredGroups" :key="gi" class="mb-4">
<view class="mb-2 mt-1 flex items-center gap-2 px-3">
<view class="h-3.5 w-1 rounded-full" :style="{ backgroundColor: group.color }" />
<text class="text-3.5 font-bold wot-text-text-main">
{{ t(group.titleKey) }}
</text>
<text class="text-2.5 wot-text-text-auxiliary">
{{ group.items.length }}
</text>
<wd-text class="text-3.5 wot-text-text-main" :text="t(group.titleKey)" bold />
<wd-text class="text-2.5 wot-text-text-auxiliary" :text="group.items.length" />
</view>
<wd-cell-group border custom-class="mx-3 rounded-2! overflow-hidden">
<wd-cell
@@ -135,7 +131,9 @@ const filteredGroups = computed(() => {
>
<wd-icon :name="item.icon" size="16px" :color="group.color" />
</view>
<text>{{ t(item.titleKey) }}</text>
<text>
{{ t(item.titleKey) }}
</text>
</view>
</template>
</wd-cell>