Browse Source

feature: 添加scss

ljc 7 months ago
parent
commit
d79654fe13

+ 0 - 1
src/layout/components/Header/components/Language.vue

@@ -33,7 +33,6 @@
 
   // 切换显示语言
   const SwitchLanguage = (lang) => {
-    console.log(v3This, 'this')
     if (lang != v3This.ctx.Session.Get('lang')) {
       switchLang(lang)
     }

+ 8 - 8
src/styles/index.scss

@@ -1,8 +1,8 @@
-@import './variables.scss';
-@import './color.scss';
-@import './sidebar.scss';
-@import './transition.scss';
-@import './common.scss';
-@import './cwg_common.scss';
-@import './default.scss';
-@import './element.scss';
+@use './variables.scss' as *;
+@use './color.scss' as *;
+@use './sidebar.scss' as *;
+@use './transition.scss' as *;
+@use './common.scss' as *;
+@use './cwg_common.scss' as *;
+@use './default.scss' as *;
+@use './element.scss' as *;

+ 55 - 131
src/views/login/index.scss

@@ -1,143 +1,67 @@
-$dark_gray: #889aa4;
-.login-box {
-  position: relative;
-  width: 100%;
-  height: 100%;
-  background: white;
-  border-radius: 8px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  .login-left {
-    width: 50%;
-    img {
-      width: 100%;
-      max-width: 900px;
+#signin {
+  width: 540px;
+  height: auto;
+  margin: auto;
+  border-top: 2px solid;
+  @include border_red_1();
+  @include bg_white();
+  .title {
+    padding: 32px 0;
+    margin-bottom: 30px;
+    font-size: 24px;
+    font-weight: bolder;
+    i {
+      margin-right: 10px;
     }
   }
-  .login-form {
-    max-width: 480px;
-    width: 50%;
-    padding: 40px;
-    border-radius: 10px;
-    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
-    box-sizing: border-box;
-    position: relative;
-
-    .info-qrcode {
-      width: 150px;
-      height: 40px;
-      border-radius: 8px;
-      box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
-      position: absolute;
-      top: -60px;
-      right: 0;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      color: #1492ff;
-      font-size: 16px;
-      &::after {
-        content: '';
-        -webkit-box-sizing: border-box;
-        box-sizing: border-box;
-        width: 10px;
-        height: 26px;
-        border-top: 13px solid #fff;
-        border-left: 5px solid transparent;
-        border-right: 5px solid transparent;
-        border-bottom: 13px solid transparent;
-        position: absolute;
-        top: 40px;
-        right: 16px;
+  .form {
+    padding: 20px 80px;
+    .forget {
+      text-align: center;
+      text-decoration: underline;
+      margin: 100px 0;
+      @include font_red_1();
+      font-weight: bold;
+      a {
+        @include font_red_1();
       }
     }
-  }
-  .login-title {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    margin-bottom: 30px;
-    .title {
-      margin: 0;
-      font-size: 30px;
-      white-space: nowrap;
+    .words {
+      // margin-top: 20px;
+      text-align: left;
+      line-height: 24px;
+      a {
+        margin-left: 1em;
+        @include font_main();
+      }
     }
-    .icon {
-      width: 60px;
+    .s-btn {
+      width: 100%;
     }
-  }
-  ::v-deep(.el-input__inner) {
-    height: 40px;
-  }
-}
-.login-btn {
-  margin-top: 20px;
-  width: 100%;
-  height: 47px;
-}
-.show-pwd {
-  position: absolute;
-  right: 10px;
-  top: 7px;
-  font-size: 16px;
-  color: $dark_gray;
-  cursor: pointer;
-  user-select: none;
-  ::v-deep(.svg-icon) {
-    vertical-align: 0;
-  }
-}
-.login-container {
-  background-color: #f0f2f5;
-  height: 100%;
-  width: 100%;
-  overflow: hidden;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  padding: 25px 25px;
-  box-sizing: border-box;
-}
-.login-dark {
-  position: absolute;
-  right: 20px;
-  top: 20px;
-}
 
-.qrcode {
-  position: absolute;
-  right: 0;
-  top: 0;
-  cursor: pointer;
-  width: 30px;
-}
-.login-qrcode {
-  width: 100%;
-  display: flex;
-  justify-content: center;
-  flex-direction: column;
-  align-items: center;
-  img {
-    width: 60%;
   }
-  .title {
-  }
-}
-
-@media (max-width: 850px) {
-  .login-container {
-    padding: 10px;
-  }
-  .login-box {
-    .login-form {
-      width: 88%;
-      .title {
-        font-size: 20px;
-      }
+  .getCode {
+    margin-top: 15px;
+    padding: 6px 20px;
+    border: 1px solid;
+    border-radius: 4px;
+    cursor: pointer;
+    user-select: none;
+    white-space: nowrap;
+    &:hover {
+      // @include font_main();
+      color: #9d9d9d;
     }
   }
-  .login-left {
-    display: none;
+  .dia-content{
+    .dialogCheck_form{
+      min-height: 100px;
+    }
+    .getCode{
+      margin-top: 0;
+    }
+    .el-form-item{
+      margin-top: 50px;
+    }
   }
 }

+ 347 - 20
src/views/login/index.vue

@@ -1,34 +1,361 @@
 <template>
-  <div class="login-container">
-    <div class="login-box">
-      <SwitchDark class="login-dark" />
-      <div class="login-left">
-        <img src="@/assets/image/login/side-logo.png" />
-      </div>
-      <div class="login-form">
-        <div class="info-qrcode">{{ accountLogin ? '扫码登录' : '账号登录' }}</div>
-        <img src="@/assets/image/login/qrcode-icon.png" class="qrcode" @click="handleClick" />
+  <div id="signin" v-loading="loading">
+    <div class="title">
+      <i class="el-icon-unlock"></i>
+      <span v-t="'signin.title'"></span>
+    </div>
+    <el-form ref="params" :model="params" :rules="rules" label-width="0" class="form">
+      <el-form-item prop="loginName">
+        <el-input
+          v-model.trim="params.loginName"
+          class="m-input"
+          prefix-icon="iconfont iconyouxiang1"
+          :placeholder="$t('signin.form.email')"
+          @keyup.enter="login"
+        ></el-input>
+      </el-form-item>
+      <el-form-item prop="password">
+        <el-input
+          v-model.trim="params.password"
+          class="m-input"
+          type="password"
+          autocomplete="off"
+          show-password
+          prefix-icon="iconfont iconmima"
+          :placeholder="$t('signin.form.password')"
+          @keyup.enter="login"
+        ></el-input>
+      </el-form-item>
+      <!-- <el-form-item prop="code">
+        <el-row>
+          <el-col :span="14">
+            <el-input
+              class="code"
+              v-model.trim="params.emailCode"
+              prefix-icon="iconfont iconyanzhengma"
+              :placeholder="$t('signup.form.code')"
+            ></el-input>
+          </el-col>
+          <el-col :span="9" :push="1" style="margin-top: 10px">
+            <span
+              @click="getCode(1)"
+              class="getCode"
+              v-text="getCodeString"
+            ></span>
+          </el-col>
+        </el-row>
+      </el-form-item> -->
+      <el-form-item class="forget">
+        <div><a v-t="'signin.forget'" href="#/forget"></a></div>
+      </el-form-item>
+      <el-form-item>
+        <el-button v-t="'signin.login'" type="danger" class="s-btn" @click="loginValid"></el-button>
+      </el-form-item>
+    </el-form>
 
-        <LoginForm v-if="accountLogin" />
-        <LoginQrcode v-else />
+    <!--验证码-->
+    <el-dialog
+      :title="$t('getCode.item1')"
+      center
+      :close-on-click-modal="false"
+      custom-class="dialog_header_w"
+    >
+      <div class="dia-content">
+        <el-form
+          ref="dialogCheck_form"
+          :model="dialogCheck_form"
+          :rules="rules"
+          label-width="0"
+          class="dialogCheck_form"
+        >
+          <el-form-item v-if="dialogCheck_type == 0" prop="emailCode">
+            <el-row>
+              <el-col :span="14">
+                <el-input
+                  v-model.trim="dialogCheck_form.emailCode"
+                  class="code"
+                  prefix-icon="iconfont iconyanzhengma"
+                  :placeholder="$t('getCode.item2')"
+                  @blur="selectChange"
+                ></el-input>
+              </el-col>
+              <el-col :span="9" :push="1" style="display: flex; justify-content: center">
+                <span class="getCode" @click="getCode(1)" v-text="getCodeString"></span>
+              </el-col>
+            </el-row>
+          </el-form-item>
+          <el-form-item v-if="dialogCheck_type == 1" prop="gaCode">
+            <el-row>
+              <el-col :span="24">
+                <el-input
+                  v-model.trim="dialogCheck_form.gaCode"
+                  class="code"
+                  prefix-icon="iconfont iconyanzhengma"
+                  :placeholder="$t('getCode.item3')"
+                  @blur="selectChange"
+                ></el-input>
+              </el-col>
+            </el-row>
+          </el-form-item>
+        </el-form>
+        <!--        <div slot="footer" class="dialog-footer">-->
+        <!--          <el-button v-t="'Btn.Cancel'" @click="dialogCheck = false"></el-button>-->
+        <!--          <el-button v-t="'Btn.Confirm'" type="danger" @click="login()"></el-button>-->
+        <!--        </div>-->
       </div>
-    </div>
+    </el-dialog>
   </div>
 </template>
 
 <script lang="ts" setup>
-  import { ref } from 'vue'
-  import LoginForm from './components/LoginForm.vue'
-  import SwitchDark from '@/components/SwitchDark/index.vue'
-  import LoginQrcode from './components/LoginQrcode.vue'
+  import { ref, reactive, onMounted } from 'vue'
+  import { useRouter } from 'vue-router'
+  import { useStore } from 'vuex'
+  // import Service from '@/service/login'
+  import Config from '@/config/index'
+  import axios from 'axios'
+  import type { FormInstance, FormRules } from 'element-plus'
+
+  const { Code } = Config
+  const router = useRouter()
+  const store = useStore()
+
+  // 类型定义
+  interface LoginParams {
+    loginName: string
+    password: string
+    emailCode: string
+  }
+
+  interface DialogCheckForm {
+    emailCode: string
+    gaCode: string
+  }
+
+  // 响应式数据
+  const loading = ref(false)
+  const params = reactive<LoginParams>({
+    loginName: '',
+    password: '',
+    emailCode: '',
+  })
+
+  const timer = ref(59)
+  const interval = ref<NodeJS.Timeout | null>(null)
+  const getCodeString = ref('')
+
+  const dialogCheck = ref(false)
+  const dialogCheck_form = reactive<DialogCheckForm>({
+    emailCode: '',
+    gaCode: '',
+  })
+  const dialogCheck_type = ref(0)
+
+  // 表单引用
+  const paramsFormRef = ref<FormInstance>()
+  const dialogCheckFormRef = ref<FormInstance>()
+
+  // 验证规则
+  const rules = reactive<FormRules>({
+    loginName: [{ required: true, message: '请输入登录名', trigger: 'blur' }],
+    password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+    emailCode: [{ required: true, message: '请输入邮箱验证码', trigger: 'blur' }],
+    gaCode: [{ required: true, message: '请输入谷歌验证码', trigger: 'blur' }],
+  })
+
+  // 方法
+  const selectChange = () => {
+    // 如果需要强制更新
+  }
+
+  // 登录验证方式
+  const loginValid = async () => {
+    if (!paramsFormRef.value) return
+
+    const valid = await paramsFormRef.value.validate()
+    if (!valid) return
+
+    loading.value = true
+    try {
+      const data = {
+        loginName: params.loginName,
+        password: params.password,
+      }
+      // const res = await Service.loginValid(data)
+      //
+      // if (res.code === Code.StatusOK) {
+      //   const validFlag = res.data
+      //   dialogCheck.value = true
+      //   dialogCheck_type.value = validFlag === 1 ? 1 : 0
+      //
+      //   if (validFlag !== 1) {
+      //     await getCode(1)
+      //   }
+      // } else {
+      //   // 使用你的消息提示组件
+      //   console.error(res.msg)
+      // }
+    } catch (error) {
+      console.error('登录验证失败:', error)
+    } finally {
+      loading.value = false
+    }
+  }
+
+  // 登录
+  const login = async () => {
+    if (!dialogCheckFormRef.value) return
 
-  const accountLogin = ref<boolean>(true)
+    const valid = await dialogCheckFormRef.value.validate()
+    if (!valid) return
 
-  const handleClick = () => {
-    console.log('===', accountLogin)
-    accountLogin.value = !accountLogin.value
+    loading.value = true
+    try {
+      const data =
+        dialogCheck_type.value === 1
+          ? {
+              loginName: params.loginName,
+              password: params.password,
+              gaCode: dialogCheck_form.gaCode,
+            }
+          : {
+              loginName: params.loginName,
+              password: params.password,
+              emailCode: dialogCheck_form.emailCode,
+            }
+
+      // const res = await Service.Login(data)
+      // if (res.code === Code.StatusOK) {
+      //   dialogCheck.value = false
+      //   sessionStorage.setItem('access_token', res.data)
+      //   axios.defaults.headers.common['Access-Token'] = res.data
+      //   await getLoginInfo()
+      // } else {
+      //   console.error(res.msg)
+      // }
+    } catch (error) {
+      console.error('登录失败:', error)
+    } finally {
+      loading.value = false
+    }
+  }
+
+  // 获取登录信息
+  const getLoginInfo = async () => {
+    try {
+      // const res = await Service.CustomLoginInfo()
+      // if (res.code === Code.StatusOK) {
+      //   store.commit('InitInfo', res.data)
+      //   store.commit('InfoExpire', false)
+      //   sessionStorage.setItem('info', JSON.stringify(res.data))
+      //   console.log('登录成功')
+      //
+      //   setTimeout(() => {
+      //     router.push({ path: '/' }).catch((err) => console.log(err))
+      //   }, 1000)
+      // } else {
+      //   store.commit('InfoExpire', false)
+      //   console.error('系统错误')
+      // }
+    } catch (error) {
+      console.error('获取登录信息失败:', error)
+      loading.value = false
+    }
+  }
+
+  // 修改语言
+  const switchLanguage = async () => {
+    const la = 'cn' // 这里应该从 i18n 获取当前语言
+    // await Service.switchLanguage({ lang: la })
+  }
+
+  // 获取验证码
+  const getCode = async (val: number) => {
+    if (val && !params.loginName) {
+      console.warn('请输入邮箱')
+      return
+    }
+
+    if (interval.value) return // 防止重复点击
+
+    getCodeString.value = `验证码已发送,${timer.value}秒后重新获取`
+
+    await getCode1(val)
+
+    interval.value = setInterval(() => {
+      timer.value--
+      sessionStorage.setItem('timer', timer.value.toString())
+
+      if (timer.value > 0) {
+        getCodeString.value = `验证码已发送,${timer.value}秒后重新获取`
+      } else {
+        getCodeString.value = '获取验证码'
+        clearInterval(interval.value!)
+        interval.value = null
+        timer.value = 59
+        sessionStorage.setItem('timer', timer.value.toString())
+      }
+    }, 1000)
+  }
+
+  // 发送验证码请求
+  const getCode1 = async (val: number) => {
+    if (!val) return
+
+    try {
+      // const res = await Service.sendCode({
+      //   loginName: params.loginName,
+      //   lang: sessionStorage.getItem('lang') || 'en',
+      // })
+      //
+      // if (res.code === Code.StatusOK) {
+      //   console.log('验证码发送成功')
+      // } else {
+      //   console.error(res.msg)
+      // }
+    } catch (error) {
+      console.error('发送验证码失败:', error)
+    }
   }
+
+  // 初始化定时器
+  const initTimer = () => {
+    const storedTimer = sessionStorage.getItem('timer')
+    const t = storedTimer ? parseInt(storedTimer) : 59
+
+    if (t === 59) {
+      getCodeString.value = '获取验证码'
+    } else {
+      timer.value = t
+      getCode(0)
+    }
+  }
+
+  onMounted(() => {
+    initTimer()
+  })
 </script>
 <style lang="scss" scoped>
   @import './index';
+  #signin {
+    .el-input__inner {
+      border: none;
+      border-bottom: 1px solid;
+      border-radius: 0;
+      @include border_gray_1();
+    }
+    .el-form-item {
+      margin-bottom: 40px;
+    }
+    .el-form-item__content {
+      line-height: initial !important;
+    }
+    .el-input__prefix,
+    .el-input__suffix {
+      @include font_gray_content_1();
+    }
+    .s-btn.el-button--danger {
+      @include bg_red_1();
+    }
+  }
 </style>

+ 2 - 2
vite.config.ts

@@ -48,14 +48,14 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
     css: {
       preprocessorOptions: {
         scss: {
-          additionalData: `@use "./src/styles/index.scss" as *;`,
+          additionalData: `@use "@/styles/index.scss" as *;`,
         },
       },
     },
     // 配置别名
     resolve: {
       alias: {
-        '@': resolve('src'),
+        '@': path.resolve(__dirname, './src'),
         static: resolve('public/static'),
       },
       // 忽略后缀名的配置选项, 添加 .vue 选项时要记得原本默认忽略的选项也要手动写入