ljc 7 месяцев назад
Родитель
Сommit
d487f9473c

+ 1 - 0
package.json

@@ -80,6 +80,7 @@
     "lint-staged": "^12.3.4",
     "lint-staged": "^12.3.4",
     "mrm": "^3.0.10",
     "mrm": "^3.0.10",
     "prettier": "^2.7.1",
     "prettier": "^2.7.1",
+    "sass-loader": "^10.5.2",
     "typescript": "^4.6.4",
     "typescript": "^4.6.4",
     "unplugin-auto-import": "^0.10.3",
     "unplugin-auto-import": "^0.10.3",
     "unplugin-vue-components": "^0.21.2",
     "unplugin-vue-components": "^0.21.2",

+ 9 - 14
src/App.vue

@@ -25,21 +25,16 @@
 
 
 <style lang="scss">
 <style lang="scss">
   #app {
   #app {
-    position: relative;
-    width: 100%;
-    height: 100%;
-    font-family: Avenir, sans-serif;
+    font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei',
+      '微软雅黑', Arial, sans-serif;
     -webkit-font-smoothing: antialiased;
     -webkit-font-smoothing: antialiased;
     -moz-osx-font-smoothing: grayscale;
     -moz-osx-font-smoothing: grayscale;
-    color: #2c3e50;
-  }
-  .el-pager li:focus {
-    border: none;
-  }
-  .el-dropdown:focus {
-    border: none;
-  }
-  .svg-icon:focus {
-    border: none;
+    text-align: center;
+    width: 100%;
+    height: 100%;
+    min-width: 1080px;
+    overflow: hidden;
+    overflow-x: auto;
+    font-size: 12px;
   }
   }
 </style>
 </style>

BIN
src/assets/image/login/CN.jpg


BIN
src/assets/image/login/EN.jpg


BIN
src/assets/image/login/admin_LOGO12.png


+ 17 - 3
src/routers/index.ts

@@ -47,10 +47,24 @@ export const constantRoutes: Array<RouteRecordRaw & extendRoute> = [
   },
   },
   {
   {
     path: '/login',
     path: '/login',
-    name: 'Login',
-    component: () => import('@/views/login/index.vue'),
+    name: 'login',
+    component: () => import('@/views/login/User.vue'),
     hidden: true,
     hidden: true,
-    meta: { title: '登录' },
+    redirect: '/signin',
+    children: [
+      {
+        path: '/signin',
+        name: 'SignIn',
+        component: () => import('@/views/login/index.vue'),
+        hidden: true,
+      },
+      {
+        path: '/forget',
+        name: 'Forget',
+        component: () => import('@/views/login/Forget.vue'),
+        hidden: true,
+      },
+    ],
   },
   },
   {
   {
     path: '/',
     path: '/',

+ 8 - 8
src/styles/index.scss

@@ -1,8 +1,8 @@
-@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 *;
+@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';

+ 1 - 13
src/styles/variables.scss

@@ -9,7 +9,7 @@ $yellow: #fec171;
 $panGreen: #30b08f;
 $panGreen: #30b08f;
 
 
 /* 全局 css 变量 */
 /* 全局 css 变量 */
-$primaryColor: var(--el-color-primary);
+$primaryColor: #409eff;
 
 
 // sidebar
 // sidebar
 $menuText: #bfcbd9;
 $menuText: #bfcbd9;
@@ -23,15 +23,3 @@ $subMenuBg: #1f2d3d;
 $subMenuHover: #001528;
 $subMenuHover: #001528;
 
 
 $sideBarWidth: 210px;
 $sideBarWidth: 210px;
-
-:export {
-  menuText: $menuText;
-  menuActiveText: $menuActiveText;
-  subMenuActiveText: $subMenuActiveText;
-  menuBg: $menuBg;
-  menuHover: $menuHover;
-  subMenuBg: $subMenuBg;
-  subMenuHover: $subMenuHover;
-  sideBarWidth: $sideBarWidth;
-  primaryColor: $primaryColor;
-}

+ 151 - 0
src/views/login/Forget.vue

@@ -0,0 +1,151 @@
+<template>
+  <div id="signin" v-loading="loading">
+    <div class="title">
+      <i class="el-icon-lock"></i>
+      <span v-t="'forget.title'"></span>
+    </div>
+    <el-form :model="params" :rules="rules" ref="params" label-width="0" class="form">
+      <el-form-item prop="email">
+        <el-input
+          class="m-input"
+          prefix-icon="iconfont iconyouxiang1"
+          v-model.trim="params.email"
+          :placeholder="$t('forget.form')"
+        ></el-input>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="danger" class="s-btn" @click="send" v-t="'forget.forget'"></el-button>
+      </el-form-item>
+      <el-form-item>
+        <el-button class="s-btn" @click="cancel" v-t="'forget.cancel'"></el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+  import Service from '@/service/login'
+  import Config from '@/config'
+
+  let { Code } = Config
+  export default {
+    data() {
+      return {
+        loading: false,
+        params: {
+          email: '',
+        },
+        // 验证规则
+        rules: {
+          email: [
+            {
+              validator: (rule, value, callback) => {
+                if (this.Config.Pattern.Email.test(value)) {
+                  callback()
+                } else {
+                  callback(new Error(this.$i18n.t('vaildate.email.format')))
+                }
+              },
+              trigger: 'blur',
+            },
+          ],
+        },
+      }
+    },
+    methods: {
+      // 发送
+      send: async function () {
+        this.$refs['params'].validate(async (valid) => {
+          if (valid) {
+            let res = await Service.forgetPwd(this.params)
+            if (res.code == Code.StatusOK) {
+              this.loading = true
+              this.$pigeon.MessageOK(res.msg)
+              setTimeout(() => {
+                this.loading = false
+                this.$router.push({ path: '/signin' }).catch((arr) => arr)
+              }, 1000)
+            } else {
+              this.$pigeon.MessageError(res.msg)
+            }
+          } else {
+            return false
+          }
+        })
+      },
+      cancel() {
+        this.$router.push({ path: '/signin' }).catch((arr) => arr)
+      },
+    },
+    mounted() {},
+  }
+</script>
+
+<style lang="scss" scoped>
+  #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;
+      }
+    }
+    .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();
+        }
+      }
+      .words {
+        // margin-top: 20px;
+        text-align: left;
+        line-height: 24px;
+        a {
+          margin-left: 1em;
+          @include font_main();
+        }
+      }
+      .s-btn {
+        width: 100%;
+      }
+    }
+  }
+</style>
+
+<style lang="scss">
+  #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>

+ 183 - 0
src/views/login/User.vue

@@ -0,0 +1,183 @@
+<template>
+  <el-row id="user">
+    <div style="height: auto">
+      <div class="section-common section-top">
+        <div class="bar">
+          <div>
+            <img :src="logo" alt="" />
+          </div>
+          <div class="menu-logo chooseLang crm-cursor">
+            <img
+              v-if="langList[language] == 'ENGLISH'"
+              style="width: 15px; height: 10px; margin: 0 4px"
+              :src="icon_en"
+              alt
+            />
+            <img
+              v-if="langList[language] == '中文简体'"
+              style="width: 15px; height: 10px; margin: 0 4px"
+              :src="icon_cn"
+              alt
+            />
+            <el-dropdown trigger="click" @command="chooseLang">
+              <span class="menu">
+                {{ langList[language] }}
+                <i class="el-icon-arrow-down el-icon--right"></i>
+              </span>
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item command="en">English</el-dropdown-item>
+                  <el-dropdown-item command="cn">中文简体</el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </div>
+        </div>
+      </div>
+      <el-col class="section-common section-bottom">
+        <router-view v-slot="{ Component, route }">
+          <component :is="Component" :key="route.path" />
+        </router-view>
+      </el-col>
+    </div>
+  </el-row>
+</template>
+
+<script lang="ts" setup>
+  import { ref, onMounted, inject } from 'vue'
+  import { useStore } from 'vuex'
+  import { useI18n } from 'vue-i18n'
+  import axios from 'axios'
+  // import Service from '@/service/login'
+  // 引入图片
+  import logo from '@/assets/image/login/admin_LOGO12.png'
+  import icon_cn from '@/assets/image/login/CN.jpg'
+  import icon_en from '@/assets/image/login/EN.jpg'
+  import { log } from 'echarts/types/src/util/log'
+  // 注入 reload 方法
+  const reload = inject('reload')
+  const store = useStore()
+  const { locale } = useI18n()
+
+  // 响应式数据
+  const langList = ref({
+    en: 'ENGLISH',
+    cn: '中文简体',
+  })
+  const language = ref('')
+
+  // 方法
+  const getClientIP = async () => {
+    try {
+      const res = await axios.get('https://ipinfo.io/json', {})
+      if (res.data.ip) {
+        sessionStorage.setItem('CLIENT', res.data.ip)
+        if (sessionStorage.getItem('CLIENT')) {
+          axios.defaults.headers.common['CLIENT'] = sessionStorage.getItem('CLIENT')
+        }
+      }
+    } catch (err) {
+      console.error('获取IP失败:', err)
+    }
+  }
+
+  const init = async (abc) => {
+    console.log(abc)
+  }
+
+  const initLanguage = () => {
+    const savedLang = sessionStorage.getItem('lang')
+    if (savedLang) {
+      setLanguage(savedLang)
+    } else {
+      // 根据浏览器语言自动检测
+      const browserLang = (navigator.language || navigator.browserLanguage).toLowerCase()
+      const detectedLang = browserLang.indexOf('zh') >= 0 ? 'cn' : 'en'
+      chooseLang(detectedLang)
+    }
+  }
+
+  const setLanguage = (lang) => {
+    locale.value = language.value = lang
+    axios.defaults.headers.common['Language'] = lang
+  }
+
+  const chooseLang = async (key) => {
+    setLanguage(key)
+    sessionStorage.setItem('lang', key)
+
+    // 调用后端语言切换
+    await switchLanguage(key)
+
+    // 延迟重载页面
+    setTimeout(() => {
+      reload?.()
+    }, 500)
+  }
+
+  const switchLanguage = async (lang) => {
+    try {
+      // await Service.switchLanguage({ lang })
+    } catch (error) {
+      console.error('切换语言失败:', error)
+    }
+  }
+
+  const toHome = () => {
+    store.commit('isActiveTab', '99')
+  }
+
+  // 生命周期
+  onMounted(async () => {
+    console.log('asdasda')
+    await getClientIP()
+    initLanguage()
+  })
+</script>
+
+<style lang="scss" scoped>
+  #user {
+    height: 100%;
+    border-top: 1px solid #000000;
+    box-sizing: border-box;
+    overflow-y: auto;
+    @include bg_gray_7();
+    .section-common {
+      height: auto;
+      padding: 25px 0;
+      margin: auto;
+    }
+    .section-top {
+      width: 100%;
+      display: flex;
+      justify-content: center;
+      .bar {
+        width: 540px;
+        padding: 0 40px;
+        display: flex;
+        align-items: center;
+        align-content: center;
+        justify-content: space-between;
+        .chooseLang {
+          display: flex;
+          align-items: center;
+          border: 1px solid transparent;
+          @include bg_white();
+          border-radius: 50px;
+          padding: 5px 8px;
+        }
+        .el-dropdown {
+          i {
+            font-size: 16px;
+            font-weight: bold;
+          }
+        }
+      }
+    }
+    .section-right {
+      height: auto;
+      width: 640px;
+      padding-top: 48px;
+    }
+  }
+</style>

+ 1 - 22
src/views/login/index.vue

@@ -9,7 +9,6 @@
         <el-input
         <el-input
           v-model.trim="params.loginName"
           v-model.trim="params.loginName"
           class="m-input"
           class="m-input"
-          prefix-icon="iconfont iconyouxiang1"
           :placeholder="$t('signin.form.email')"
           :placeholder="$t('signin.form.email')"
           @keyup.enter="login"
           @keyup.enter="login"
         ></el-input>
         ></el-input>
@@ -21,30 +20,10 @@
           type="password"
           type="password"
           autocomplete="off"
           autocomplete="off"
           show-password
           show-password
-          prefix-icon="iconfont iconmima"
           :placeholder="$t('signin.form.password')"
           :placeholder="$t('signin.form.password')"
           @keyup.enter="login"
           @keyup.enter="login"
         ></el-input>
         ></el-input>
       </el-form-item>
       </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">
       <el-form-item class="forget">
         <div><a v-t="'signin.forget'" href="#/forget"></a></div>
         <div><a v-t="'signin.forget'" href="#/forget"></a></div>
       </el-form-item>
       </el-form-item>
@@ -336,7 +315,7 @@
   })
   })
 </script>
 </script>
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  @import './index';
+  @import './index.scss';
   #signin {
   #signin {
     .el-input__inner {
     .el-input__inner {
       border: none;
       border: none;

+ 2 - 0
vite.config.ts

@@ -48,6 +48,8 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
     css: {
     css: {
       preprocessorOptions: {
       preprocessorOptions: {
         scss: {
         scss: {
+          javascriptEnabled: true,
+          api: 'modern-compiler',
           additionalData: `@use "@/styles/index.scss" as *;`,
           additionalData: `@use "@/styles/index.scss" as *;`,
         },
         },
       },
       },