重构TailwindCSS配置与登录页面样式
This commit is contained in:
parent
7c91dc42ae
commit
487b3e2ebc
@ -20,10 +20,12 @@
|
||||
"vue3-cookies": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/vite": "^4.1.3",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"nprogress": "^0.2.0",
|
||||
"postcss": "^8.5.3",
|
||||
"qs": "^6.14.0",
|
||||
"tailwindcss": "3.4.17",
|
||||
"vite": "^6.2.4",
|
||||
"vite-svg-loader": "^5.1.0"
|
||||
}
|
||||
|
6
postcss.config.cjs
Normal file
6
postcss.config.cjs
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.2 KiB |
@ -1,4 +1,3 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
|
||||
@primary: #0070f3;
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
11
src/assets/global.less
Normal file
11
src/assets/global.less
Normal file
@ -0,0 +1,11 @@
|
||||
// 主题色
|
||||
|
||||
// 通用色
|
||||
|
||||
// 成功色
|
||||
|
||||
// 警告色
|
||||
|
||||
// 危险色
|
||||
|
||||
// 二级色
|
@ -1 +1,12 @@
|
||||
@import './base.less';
|
||||
|
||||
body {
|
||||
--td-brand-color: theme('colors.pp.500');
|
||||
--td-brand-color-hover: theme('colors.pp.400');
|
||||
--td-brand-color-focus: theme('colors.pp.200');
|
||||
--td-brand-color-active: theme('colors.pp.400');
|
||||
--td-brand-color-disabled: theme('colors.pp.200');
|
||||
--td-brand-color-light: theme('colors.pp.300');
|
||||
--td-brand-color-light-hover: theme('colors.pp.400');
|
||||
|
||||
}
|
167
src/assets/tx.css
Normal file
167
src/assets/tx.css
Normal file
@ -0,0 +1,167 @@
|
||||
:root[theme-mode="dark"] {
|
||||
--td-brand-color-1: #1b2f51;
|
||||
--td-brand-color-2: #173463;
|
||||
--td-brand-color-3: #143975;
|
||||
--td-brand-color-4: #103d88;
|
||||
--td-brand-color-5: #0d429a;
|
||||
--td-brand-color-6: #054bbe;
|
||||
--td-brand-color-7: #2667d4;
|
||||
--td-brand-color-8: #4582e6;
|
||||
--td-brand-color-9: #699ef5;
|
||||
--td-brand-color-10: #96bbf8;
|
||||
--td-warning-color-1: #4f2a1d;
|
||||
--td-warning-color-2: #582f21;
|
||||
--td-warning-color-3: #733c23;
|
||||
--td-warning-color-4: #a75d2b;
|
||||
--td-warning-color-5: #cf6e2d;
|
||||
--td-warning-color-6: #dc7633;
|
||||
--td-warning-color-7: #e8935c;
|
||||
--td-warning-color-8: #ecbf91;
|
||||
--td-warning-color-9: #eed7bf;
|
||||
--td-warning-color-10: #f3e9dc;
|
||||
--td-error-color-1: #472324;
|
||||
--td-error-color-2: #5e2a2d;
|
||||
--td-error-color-3: #703439;
|
||||
--td-error-color-4: #83383e;
|
||||
--td-error-color-5: #a03f46;
|
||||
--td-error-color-6: #c64751;
|
||||
--td-error-color-7: #de6670;
|
||||
--td-error-color-8: #ec888e;
|
||||
--td-error-color-9: #edb1b6;
|
||||
--td-error-color-10: #eeced0;
|
||||
--td-success-color-1: #193a2a;
|
||||
--td-success-color-2: #1a4230;
|
||||
--td-success-color-3: #17533d;
|
||||
--td-success-color-4: #0d7a55;
|
||||
--td-success-color-5: #059465;
|
||||
--td-success-color-6: #43af8a;
|
||||
--td-success-color-7: #46bf96;
|
||||
--td-success-color-8: #80d2b6;
|
||||
--td-success-color-9: #b4e1d3;
|
||||
--td-success-color-10: #deede8;
|
||||
--td-gray-color-1: #f3f3f3;
|
||||
--td-gray-color-2: #eee;
|
||||
--td-gray-color-3: #e8e8e8;
|
||||
--td-gray-color-4: #ddd;
|
||||
--td-gray-color-5: #c6c6c6;
|
||||
--td-gray-color-6: #a6a6a6;
|
||||
--td-gray-color-7: #8b8b8b;
|
||||
--td-gray-color-8: #777;
|
||||
--td-gray-color-9: #5e5e5e;
|
||||
--td-gray-color-10: #4b4b4b;
|
||||
--td-gray-color-11: #393939;
|
||||
--td-gray-color-12: #2c2c2c;
|
||||
--td-gray-color-13: #242424;
|
||||
--td-gray-color-14: #181818;
|
||||
|
||||
// 文字 & 图标 颜色
|
||||
--td-font-white-1: rgba(255, 255, 255, 90%);
|
||||
--td-font-white-2: rgba(255, 255, 255, 55%);
|
||||
--td-font-white-3: rgba(255, 255, 255, 35%);
|
||||
--td-font-white-4: rgba(255, 255, 255, 22%);
|
||||
--td-font-gray-1: rgba(0, 0, 0, 90%);
|
||||
--td-font-gray-2: rgba(0, 0, 0, 60%);
|
||||
--td-font-gray-3: rgba(0, 0, 0, 40%);
|
||||
--td-font-gray-4: rgba(0, 0, 0, 26%);
|
||||
|
||||
// 基础颜色
|
||||
--td-brand-color: var(--td-brand-color-8); // 色彩-品牌-可操作
|
||||
--td-warning-color: var(--td-warning-color-5); // 色彩-功能-警告
|
||||
--td-error-color: var(--td-error-color-6); // 色彩-功能-失败
|
||||
--td-success-color: var(--td-success-color-5); // 色彩-功能-成功
|
||||
|
||||
// 基础颜色的扩展 用于 hover / 聚焦 / 禁用 / 点击 等状态
|
||||
--td-brand-color-hover: var(--td-brand-color-7); // hover态
|
||||
--td-brand-color-focus: var(--td-brand-color-2); // focus态,包括鼠标和键盘
|
||||
--td-brand-color-active: var(--td-brand-color-9); // 点击态
|
||||
--td-brand-color-disabled: var(--td-brand-color-3); // 禁用态
|
||||
--td-brand-color-light: var(--td-brand-color-1); // 浅色的选中态
|
||||
--td-brand-color-light-hover: var(--td-brand-color-2);
|
||||
|
||||
// 警告色扩展
|
||||
--td-warning-color-hover: var(--td-warning-color-4);
|
||||
--td-warning-color-focus: var(--td-warning-color-2);
|
||||
--td-warning-color-active: var(--td-warning-color-6);
|
||||
--td-warning-color-disabled: var(--td-warning-color-3);
|
||||
--td-warning-color-light: var(--td-warning-color-1);
|
||||
--td-warning-color-light-hover: var(--td-warning-color-2);
|
||||
|
||||
// 失败/错误色扩展
|
||||
--td-error-color-hover: var(--td-error-color-5);
|
||||
--td-error-color-focus: var(--td-error-color-2);
|
||||
--td-error-color-active: var(--td-error-color-7);
|
||||
--td-error-color-disabled: var(--td-error-color-3);
|
||||
--td-error-color-light: var(--td-error-color-1);
|
||||
--td-error-color-light-hover: var(--td-error-color-2);
|
||||
|
||||
// 成功色扩展
|
||||
--td-success-color-hover: var(--td-success-color-4);
|
||||
--td-success-color-focus: var(--td-success-color-2);
|
||||
--td-success-color-active: var(--td-success-color-6);
|
||||
--td-success-color-disabled: var(--td-success-color-3);
|
||||
--td-success-color-light: var(--td-success-color-1);
|
||||
--td-success-color-light-hover: var(--td-success-color-2);
|
||||
|
||||
// 遮罩
|
||||
--td-mask-active: rgba(0, 0, 0, 40%); // 遮罩-弹出
|
||||
--td-mask-disabled: rgba(0, 0, 0, 60%); // 遮罩-禁用
|
||||
|
||||
// 背景色
|
||||
--td-bg-color-page: var(--td-gray-color-14); // 色彩 - page
|
||||
--td-bg-color-container: var(--td-gray-color-13); // 色彩 - 容器
|
||||
--td-bg-color-container-hover: var(--td-gray-color-12); // 色彩 - 容器 - hover
|
||||
--td-bg-color-container-active: var(--td-gray-color-10); // 色彩 - 容器 - active
|
||||
--td-bg-color-container-select: var(--td-gray-color-9); // 色彩 - 容器 - select
|
||||
--td-bg-color-secondarycontainer: var(--td-gray-color-12); // 色彩 - 次级容器
|
||||
--td-bg-color-secondarycontainer-hover: var(--td-gray-color-11); // 色彩 - 次级容器 - hover
|
||||
--td-bg-color-secondarycontainer-active: var(--td-gray-color-9); // 色彩 - 次级容器 - active
|
||||
--td-bg-color-component: var(--td-gray-color-11); // 色彩 - 组件
|
||||
--td-bg-color-component-hover: var(--td-gray-color-10); // 色彩 - 组件 - hover
|
||||
--td-bg-color-component-active: var(--td-gray-color-9); // 色彩 - 组件 - active
|
||||
--td-bg-color-secondarycomponent: var(--td-gray-color-10); // 色彩 - 次级组件
|
||||
--td-bg-color-secondarycomponent-hover: var(--td-gray-color-9); // 色彩 - 次级组件 - hover
|
||||
--td-bg-color-secondarycomponent-active: var(--td-gray-color-8); // 色彩 - 次级组件 - active
|
||||
--td-bg-color-component-disabled: var(--td-gray-color-12); // 色彩 - 组件 - disabled
|
||||
|
||||
// 特殊组件背景色,目前只用于 button、input 组件多主题场景,浅色主题下固定为白色,深色主题下为 transparent 适配背景颜色
|
||||
--td-bg-color-specialcomponent: transparent;
|
||||
|
||||
// 文本颜色
|
||||
--td-text-color-primary: var(--td-font-white-1); // 色彩-文字-主要
|
||||
--td-text-color-secondary: var(--td-font-white-2); // 色彩-文字-次要
|
||||
--td-text-color-placeholder: var(--td-font-white-3); // 色彩-文字-占位符/说明
|
||||
--td-text-color-disabled: var(--td-font-white-4); // 色彩-文字-禁用
|
||||
--td-text-color-anti: #fff; // 色彩-文字-反色
|
||||
--td-text-color-brand: var(--td-brand-color-8); // 色彩-文字-品牌
|
||||
--td-text-color-link: var(--td-brand-color-8); // 色彩-文字-链接
|
||||
|
||||
// 分割线
|
||||
--td-border-level-1-color: var(--td-gray-color-11);
|
||||
--td-component-stroke: var(--td-gray-color-11);
|
||||
// 边框
|
||||
--td-border-level-2-color: var(--td-gray-color-9);
|
||||
--td-component-border: var(--td-gray-color-9);
|
||||
|
||||
// 基础/下层 投影 hover 使用的组件包括:表格 /
|
||||
--td-shadow-1: 0 4px 6px rgba(0, 0, 0, 6%), 0 1px 10px rgba(0, 0, 0, 8%), 0 2px 4px rgba(0, 0, 0, 12%);
|
||||
// 中层投影 下拉 使用的组件包括:下拉菜单 / 气泡确认框 / 选择器 /
|
||||
--td-shadow-2: 0 8px 10px rgba(0, 0, 0, 12%), 0 3px 14px rgba(0, 0, 0, 10%), 0 5px 5px rgba(0, 0, 0, 16%);
|
||||
// 上层投影(警示/弹窗)使用的组件包括:全局提示 / 消息通知
|
||||
--td-shadow-3: 0 16px 24px rgba(0, 0, 0, 14%), 0 6px 30px rgba(0, 0, 0, 12%), 0 8px 10px rgba(0, 0, 0, 20%);
|
||||
// 内投影 用于弹窗类组件(气泡确认框 / 全局提示 / 消息通知)的内描边
|
||||
|
||||
--td-shadow-inset-top: inset 0 .5px 0 #5e5e5e;
|
||||
--td-shadow-inset-right: inset .5px 0 0 #5e5e5e;
|
||||
--td-shadow-inset-bottom: inset 0 -.5px 0 #5e5e5e;
|
||||
--td-shadow-inset-left: inset -.5px 0 0 #5e5e5e;
|
||||
|
||||
// table 特定阴影
|
||||
--td-table-shadow-color: rgba(0, 0, 0, 55%);
|
||||
|
||||
// 滚动条颜色
|
||||
--td-scrollbar-color: rgba(255, 255, 255, 10%);
|
||||
// 滚动条悬浮颜色( hover )
|
||||
--td-scrollbar-hover-color: rgba(255, 255, 255, 30%);
|
||||
// 滚动条轨道颜色,不能是带透明度,否则纵向滚动时,横向滚动条会穿透
|
||||
--td-scroll-track-color: #333;
|
||||
}
|
3
src/config/msg.js
Normal file
3
src/config/msg.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { MessagePlugin } from 'tdesign-vue-next'
|
||||
|
||||
export default MessagePlugin
|
@ -1,4 +1,4 @@
|
||||
import './assets/main.less';
|
||||
|
||||
|
||||
import { useConfig } from '@/config';
|
||||
import { createPinia } from 'pinia';
|
||||
@ -6,21 +6,23 @@ import TDesign from 'tdesign-vue-next';
|
||||
import 'tdesign-vue-next/es/style/index.css';
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import './assets/main.less';
|
||||
import icon from './icon/index.js';
|
||||
import router from "./router/guard.js";
|
||||
|
||||
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
app.use(TDesign)
|
||||
|
||||
// 全局定义
|
||||
useConfig()
|
||||
for (const key in icon) {
|
||||
// console.log(key, icon[key]);
|
||||
app.component('icon-'+key, icon[key]);
|
||||
}
|
||||
|
||||
|
||||
app.mount('#app')
|
||||
|
@ -4,7 +4,7 @@
|
||||
}
|
||||
|
||||
#nprogress .bar {
|
||||
background: @primary;
|
||||
background: theme('colors.purple.500');
|
||||
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
|
@ -7,10 +7,16 @@ export default {
|
||||
{
|
||||
path:'home',
|
||||
component: home,
|
||||
meta:{
|
||||
title:'首页'
|
||||
}
|
||||
},
|
||||
{
|
||||
path:"login",
|
||||
component:()=>import('@/views/login/index.vue')
|
||||
component:()=>import('@/views/login/index.vue'),
|
||||
meta:{
|
||||
title:'登录'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
BIN
src/views/login/img/05.jpeg
Normal file
BIN
src/views/login/img/05.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 854 KiB |
@ -1,21 +1,199 @@
|
||||
<template>
|
||||
<div>
|
||||
这是登录页
|
||||
<div class="page">
|
||||
<t-card v-if="tabActive == 'forgetPassword'" class="w-[400px] absolute top-[12%] right-[8%] bg-[#ffffff60] rounded-[10px]" :bordered="false" shadow>
|
||||
<resetPass @back="tabActive = 'login'" />
|
||||
</t-card>
|
||||
<t-card v-else class="w-[400px] absolute top-[12%] right-[8%] bg-[#ffffff60] rounded-[10px]" :bordered="false" shadow>
|
||||
<div class="flex justify-between items-center w-1/3 mx-auto py-2 text-lg">
|
||||
<div class="text-blue-400 cursor-pointer" :class="{ 'text-pp-500': tabActive == 'login' }" @click="loginClick">
|
||||
登录
|
||||
</div>
|
||||
<div class="text-blue-400 cursor-pointer" :class="{ 'text-pp-500': tabActive == 'register' }"
|
||||
@click="registerClick">注册</div>
|
||||
</div>
|
||||
|
||||
|
||||
<t-form v-if="tabActive == 'login'" :rules="loginRules" :data="loginData" colon showErrorMessage labelAlign="top"
|
||||
scroll-to-first-error="smooth" @submit="loginSubmit">
|
||||
<t-form-item label="用户名" name="username">
|
||||
<t-input v-model="loginData.username" placeholder="请输入邮箱或者手机号" />
|
||||
</t-form-item>
|
||||
<t-form-item label="密码" name="password">
|
||||
<t-input v-model="loginData.password" placeholder="请输入密码" />
|
||||
</t-form-item>
|
||||
<div @click="tabActive = 'forgetPassword'" class="cursor-pointer text-right text-[12px] mr-1 mb-2 text-pp-500 underline italic">忘记密码?去找回
|
||||
</div>
|
||||
<t-form-item name="btn">
|
||||
<t-button type="submit" block>登录</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
|
||||
<t-form v-if="tabActive == 'register'" :rules="regRules" :data="regData" colon showErrorMessage labelAlign="top"
|
||||
scroll-to-first-error="smooth" @submit="regSubmit">
|
||||
<t-form-item label="昵称" name="nickname">
|
||||
<t-input v-model="regData.nickname" placeholder="请输入昵称" />
|
||||
</t-form-item>
|
||||
<t-form-item label="邮箱" name="username">
|
||||
<t-input v-model="regData.username" placeholder="请输入邮箱" />
|
||||
</t-form-item>
|
||||
<t-form-item label="验证码" name="code">
|
||||
<t-input v-model="regData.code" type="number" placeholder="请输验证码" />
|
||||
<t-button theme="primary" @click="getCode">获取验证码</t-button>
|
||||
</t-form-item>
|
||||
<t-form-item label="密码" name="password">
|
||||
<t-input v-model="regData.password" type="password" placeholder="请输入密码" />
|
||||
</t-form-item>
|
||||
<t-form-item label="重复密码" name="repassword">
|
||||
<t-input v-model="regData.repassword" type="password" placeholder="请再次输入密码" />
|
||||
</t-form-item>
|
||||
<t-form-item class="pt-4" name="btn">
|
||||
<t-button type="submit" block>注册</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
|
||||
|
||||
</t-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
//mark import
|
||||
|
||||
import resetPass from "./resetPass.vue"
|
||||
//mark data
|
||||
const router = useRouter()
|
||||
|
||||
const tabActive = ref('login') // tab切换: login、register、forgetPassword
|
||||
const loginData = reactive({
|
||||
username: '',
|
||||
password: ''
|
||||
}) // 登录表单数据
|
||||
const regData = reactive({
|
||||
nickname: '',
|
||||
username: '',
|
||||
code: '',
|
||||
password: '',
|
||||
repassword: ''
|
||||
}) // 注册表单数据
|
||||
|
||||
const loginRules = reactive({
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ validator: validateUsername, message: '请输入正确的邮箱或者手机号', trigger: 'blur' },
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ validator: validatePassword, message: '密码长度为6-12位,且必须包含数字和字母', trigger: 'blur' }
|
||||
]
|
||||
}) // 登录表单验证规则
|
||||
const regRules = reactive({
|
||||
nickname: [
|
||||
{ required: true, message: '请输入昵称', trigger: 'blur' },
|
||||
],
|
||||
username: [
|
||||
{ required: true, message: '请输入邮箱', trigger: 'blur' },
|
||||
{ validator: validateMail, message: '请输入正确的邮箱', trigger: 'blur' },
|
||||
],
|
||||
code: [
|
||||
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
||||
{ len: 6, message: "验证码长度为6", trigger: "blur" },
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ validator: validatePassword, message: '密码长度为6-12位,且必须包含数字和字母', trigger: 'blur' }
|
||||
],
|
||||
repassword: [
|
||||
{ required: true, message: '请再次输入密码', trigger: 'blur' },
|
||||
{ validator: validatePassword, message: "必须是含有数字,字母的6-12位密码", trigger: "blur" },
|
||||
{ validator: validatePasswordStartWith, message: "两次密码输入不一致", trigger: "input" },
|
||||
{ validator: validatePasswordSame, message: '两次密码输入不一致', trigger: 'blur' },
|
||||
]
|
||||
}) // 注册表单验证规则
|
||||
|
||||
|
||||
//mark method
|
||||
function loginClick() {
|
||||
tabActive.value = 'login'
|
||||
}
|
||||
function registerClick() {
|
||||
tabActive.value = 'register'
|
||||
}
|
||||
|
||||
async function loginSubmit({ validateResult, firstError }) {
|
||||
console.log(validateResult, firstError);
|
||||
if (validateResult === true) {
|
||||
const res = await $http.user.login(loginData)
|
||||
if (res.code == 1) {
|
||||
$cookies.set('token', res.token, 60 * 60 * 24 * 7)
|
||||
$cookies.set('userInfo', res.data, 60 * 60 * 24 * 7)
|
||||
$msg.success(res.msg)
|
||||
router.push('/')
|
||||
return
|
||||
}
|
||||
$msg.error(res.msg)
|
||||
|
||||
return
|
||||
}
|
||||
$msg.error(firstError)
|
||||
}
|
||||
async function regSubmit({ validateResult, firstError }) {
|
||||
console.log(validateResult, firstError);
|
||||
if (validateResult === true) {
|
||||
const res = await $http.user.regis(regData)
|
||||
if (res.code == 1) {
|
||||
$msg.success(res.msg)
|
||||
tabActive.value = 'login'
|
||||
resetRegData()
|
||||
return
|
||||
}
|
||||
$msg.error(res.msg)
|
||||
return
|
||||
}
|
||||
$msg.error(firstError)
|
||||
}
|
||||
async function getCode() {
|
||||
if (!regData.username) {
|
||||
$msg.error("请输入邮箱");
|
||||
return;
|
||||
}
|
||||
const res = await $http.addr.sendMail({ mail: regData.username });
|
||||
if (res.code == "1") $msg.success(res.msg);
|
||||
else if (res.code == "0") $msg.error(res.msg);
|
||||
}
|
||||
|
||||
function resetRegData() {
|
||||
regData.nickname = ''
|
||||
regData.username = ''
|
||||
regData.code = ''
|
||||
regData.password = ''
|
||||
regData.repassword = ''
|
||||
}
|
||||
|
||||
function validatePasswordStartWith(value) {
|
||||
return !!regData.password && regData.password.startsWith(value) && regData.password.length >= value.length;
|
||||
}
|
||||
function validatePasswordSame(value) {
|
||||
return value === regData.password;
|
||||
}
|
||||
function validateUsername(value) {
|
||||
return /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/.test(value) || /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(value)
|
||||
|
||||
}
|
||||
function validateMail(value) {
|
||||
return /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/.test(value);
|
||||
}
|
||||
function validatePassword(value) {
|
||||
return /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$/.test(value);
|
||||
}
|
||||
//mark 周期、内置函数等
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
<style scoped lang="less">
|
||||
.page {
|
||||
background: transparent url("./img/05.jpeg") 100% 100%/100% 100% no-repeat;
|
||||
width: 100vm;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
151
src/views/login/resetPass.vue
Normal file
151
src/views/login/resetPass.vue
Normal file
@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<div>
|
||||
<t-steps class="px-8" readonly :current="currentStep" separator="arrow">
|
||||
<t-step-item :value="1" title="验证邮箱" />
|
||||
<t-step-item :value="2" title="重新设置密码" />
|
||||
</t-steps>
|
||||
|
||||
<t-form class="mt-5" :data="step1" colon labelAlign="top" :rules="rules1" showErrorMessage
|
||||
scroll-to-first-error="smooth" v-if="currentStep == 1" @submit="next">
|
||||
<t-form-item label="邮箱" name="username">
|
||||
<t-input v-model="step1.username" placeholder="请输入邮箱" />
|
||||
</t-form-item>
|
||||
<t-form-item label="验证码" name="code">
|
||||
<t-input v-model="step1.code" type="number" placeholder="请输验证码" />
|
||||
<t-button theme="primary" @click="getCode">获取验证码</t-button>
|
||||
</t-form-item>
|
||||
<t-form-item class="pt-4" name="btn">
|
||||
<div class="btns">
|
||||
<t-button theme="primary" ghost @click="back">返回登录</t-button>
|
||||
<t-button theme="primary" type="submit">下一步</t-button>
|
||||
</div>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
|
||||
<t-form class="mt-5" :data="step2" colon labelAlign="top" :rules="rules2" showErrorMessage
|
||||
scroll-to-first-error="smooth" v-if="currentStep == 2" @submit="submit">
|
||||
<t-form-item label="密码" name="password">
|
||||
<t-input v-model="step2.password" type="password" placeholder="请输入密码" />
|
||||
</t-form-item>
|
||||
<t-form-item label="重复密码" name="repassword">
|
||||
<t-input v-model="step2.repassword" type="password" placeholder="请再次输入密码" />
|
||||
</t-form-item>
|
||||
<t-form-item class="pt-4" name="btn">
|
||||
<div class="btns">
|
||||
<t-button theme="primary" ghost @click="currentStep--">上一步</t-button>
|
||||
<t-button theme="primary" type="submit">确定改密</t-button>
|
||||
</div>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
//mark import
|
||||
|
||||
//mark data
|
||||
const emit = defineEmits(["back"]);
|
||||
const currentStep = ref(1);
|
||||
|
||||
const step1 = reactive({
|
||||
username: "",
|
||||
code: ""
|
||||
});
|
||||
const step2 = reactive({
|
||||
username: "",
|
||||
password: "",
|
||||
repassword: "",
|
||||
});
|
||||
const rules1 = reactive({
|
||||
username: [
|
||||
{ required: true, message: '请输入邮箱', trigger: 'blur' },
|
||||
{ validator: validateMail, message: '请输入正确的邮箱', trigger: 'blur' },
|
||||
],
|
||||
code: [
|
||||
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
||||
{ len: 6, message: "验证码长度为6", trigger: "blur" },
|
||||
]
|
||||
})
|
||||
const rules2 = {
|
||||
password: [
|
||||
{ required: true, message: "密码不能为空", trigger: "blur" },
|
||||
{ validator: validatePassword, message: "必须是含有数字,字母的6-12位密码", trigger: "blur" },
|
||||
],
|
||||
repassword: [
|
||||
{ required: true, message: "密码不能为空", trigger: "blur" },
|
||||
{ validator: validatePassword, message: "必须是含有数字,字母的6-12位密码", trigger: "blur" },
|
||||
{ validator: validatePasswordSame, message: "两次密码输入不一致", trigger: ["blur", "password-input"] },
|
||||
],
|
||||
};
|
||||
|
||||
//mark method
|
||||
async function getCode() {
|
||||
if (!step1.username) {
|
||||
$msg.error("请输入邮箱");
|
||||
return;
|
||||
}
|
||||
const res = await $http.addr.sendMailinpass({ mail: step1.username });
|
||||
if (res.code == "1") $msg.success(res.msg);
|
||||
else if (res.code == "0") $msg.error(res.msg);
|
||||
}
|
||||
async function next() {
|
||||
if (validateResult === true) {
|
||||
currentStep.value++;
|
||||
step2.username = step1.username;
|
||||
// const res = await $http.user.rexpass(step1);
|
||||
// if (res.code == "1") {
|
||||
// $msg.success(res.msg);
|
||||
// currentStep.value++;
|
||||
// step2.username = step1.username;
|
||||
// } else if (res.code == "0") $msg.error(res.msg);
|
||||
return;
|
||||
}
|
||||
$msg.error(firstError);
|
||||
}
|
||||
|
||||
|
||||
async function submit() {
|
||||
if (validateResult === true) {
|
||||
const res = await $http.user.updatepass(step2)
|
||||
if (res.code == 1) {
|
||||
$msg.success(res.msg)
|
||||
emit("back")
|
||||
return
|
||||
}
|
||||
$msg.error(res.msg)
|
||||
|
||||
return
|
||||
}
|
||||
$msg.error(firstError)
|
||||
}
|
||||
|
||||
function back() {
|
||||
emit("back");
|
||||
}
|
||||
|
||||
function validatePasswordSame(value) {
|
||||
return value === step2.password;
|
||||
}
|
||||
function validateMail(value) {
|
||||
return /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/.test(value);
|
||||
}
|
||||
function validatePassword(value) {
|
||||
return /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$/.test(value);
|
||||
}
|
||||
//mark 周期、内置函数等
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.btns {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
:deep(.t-button) {
|
||||
width: 45%;
|
||||
}
|
||||
}
|
||||
</style>
|
83
tailwind.config.js
Normal file
83
tailwind.config.js
Normal file
@ -0,0 +1,83 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
// purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
|
||||
// purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
|
||||
content: [
|
||||
// Example content paths...
|
||||
"./public/**/*.html",
|
||||
"./src/**/*.{js,jsx,ts,tsx,vue}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
screens: {
|
||||
sm: { max: "767px" },
|
||||
md: { max: "1023px" },
|
||||
lg: { max: "1279px" },
|
||||
xl: { max: "1535px" },
|
||||
"2xl": { min: "1536px" },
|
||||
},
|
||||
colors: {
|
||||
pp: {
|
||||
100: "#eed1d5",
|
||||
200: "#dca4aa",
|
||||
300: "#cb7680",
|
||||
400: "#b94955",
|
||||
500: "#a81b2b",
|
||||
600: "#861622",
|
||||
700: "#65101a",
|
||||
800: "#430b11",
|
||||
900: "#220509"
|
||||
},
|
||||
purple: {
|
||||
100: "#BE8AEF",
|
||||
200: "#B172EC",
|
||||
300: "#A45BE9",
|
||||
400: "#9744E5",
|
||||
500: "#8A2BE2",
|
||||
600: "#7B1DD3",
|
||||
700: "#6C19B9",
|
||||
800: "#5C169F",
|
||||
900: "#4D1284",
|
||||
default: "#8A2BE2",
|
||||
},
|
||||
orange: {
|
||||
100: "#ffedcc",
|
||||
200: "#ffdb99",
|
||||
300: "#ffc966",
|
||||
400: "#ffb733",
|
||||
500: "#ffa500",
|
||||
600: "#cc8400",
|
||||
700: "#996300",
|
||||
800: "#664200",
|
||||
900: "#332100",
|
||||
default: "#ffa500"
|
||||
},
|
||||
suc: {
|
||||
100: "#dcf3d1",
|
||||
200: "#bae7a3",
|
||||
300: "#97dc76",
|
||||
400: "#75d048",
|
||||
500: "#52c41a",
|
||||
600: "#429d15",
|
||||
700: "#317610",
|
||||
800: "#214e0a",
|
||||
900: "#102705",
|
||||
default: "#52c41a"
|
||||
},
|
||||
blue:{
|
||||
default:'#0052D9',
|
||||
100: "#CCE0F7",
|
||||
200: "#99C1EF",
|
||||
300: "#66A3E8",
|
||||
400: "#337AE0",
|
||||
500: "#0052D9",
|
||||
600: "#003FAB",
|
||||
700: "#002B7D",
|
||||
800: "#00184F",
|
||||
900: "#000421",
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
important: true,
|
||||
};
|
@ -1,4 +1,3 @@
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
import { resolve } from "path";
|
||||
@ -13,13 +12,13 @@ import svgLoader from "vite-svg-loader";
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
tailwindcss(),
|
||||
svgLoader(),
|
||||
Components({
|
||||
resolvers: [TDesignResolver({library: 'vue-next'})],
|
||||
}),
|
||||
AutoImport({
|
||||
resolvers: [TDesignResolver({library: 'vue-next'})],
|
||||
imports: ['vue', 'vue-router', 'pinia'],
|
||||
resolvers: [TDesignResolver({library: 'vue-next'}),],
|
||||
}),
|
||||
],
|
||||
base: "/blog/",
|
||||
@ -37,7 +36,7 @@ export default defineConfig({
|
||||
less: {
|
||||
// additionalData: '@import "colorofchina/color.less";',
|
||||
modifyVars: {
|
||||
hack: `true; @import (reference) "${resolve("src/assets/base.less")}";`,
|
||||
hack: `true; @import (reference) "${resolve("src/assets/global.less")}";`,
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user