yangg пре 1 година
родитељ
комит
4e7d60115c
6 измењених фајлова са 236 додато и 207 уклоњено
  1. 1 1
      .env
  2. 36 15
      src/components/layout/Header.vue
  3. 2 1
      src/locales/zh.json
  4. 6 1
      src/permission.js
  5. 2 2
      src/router/index.ts
  6. 189 187
      src/views/auth/boxed-signin.vue

+ 1 - 1
.env

@@ -1 +1 @@
-VITE_API_URL=http://192.168.8.101:8080
+VITE_API_URL=http://192.168.8.101:9999

+ 36 - 15
src/components/layout/Header.vue

@@ -102,9 +102,9 @@
                                                 <span class="badge bg-primary/80"
                                                     v-text="notifications.length + 'New'"></span>
                                             </template>
-                                        </div>
-                                    </li>
-                                    <template v-for="notification in notifications" :key="notification.id">
+</div>
+</li>
+<template v-for="notification in notifications" :key="notification.id">
                                         <li class="dark:text-white-light/90">
                                             <div class="group flex items-center px-4 py-2">
                                                 <div class="grid place-content-center rounded">
@@ -130,7 +130,7 @@
                                             </div>
                                         </li>
                                     </template>
-                                    <template v-if="notifications.length">
+<template v-if="notifications.length">
                                         <li>
                                             <div class="p-4">
                                                 <button class="btn btn-primary block w-full btn-small"
@@ -138,7 +138,7 @@
                                             </div>
                                         </li>
                                     </template>
-                                    <template v-if="!notifications.length">
+<template v-if="!notifications.length">
                                         <li>
                                             <div
                                                 class="!grid place-content-center hover:!bg-transparent text-lg min-h-[200px]">
@@ -150,10 +150,10 @@
                                             </div>
                                         </li>
                                     </template>
-                                </ul>
-                            </template>
-                        </Popper>
-                    </div> -->
+</ul>
+</template>
+</Popper>
+</div> -->
 
                     <div class="dropdown shrink-0">
                         <Popper :placement="store.state.rtlClass === 'rtl' ? 'bottom-end' : 'bottom-start'"
@@ -191,11 +191,10 @@
 
 
                                     <li class="border-t border-white-light dark:border-white-light/10">
-                                        <router-link to="/login" class="text-danger !py-3" @click="close()">
+                                        <div class="text-danger !py-3" @click="handleLogoutClick">
                                             <icon-logout class="w-4.5 h-4.5 ltr:mr-2 rtl:ml-2 rotate-90 shrink-0" />
-
                                             退出
-                                        </router-link>
+                                        </div>
                                     </li>
                                 </ul>
                             </template>
@@ -215,7 +214,7 @@ import { useI18n } from 'vue-i18n';
 
 import appSetting from '@/app-setting';
 
-import { useRoute } from 'vue-router';
+import { useRouter, useRoute } from 'vue-router';
 import { useStore } from 'vuex';
 
 import IconMenu from '@/components/icon/icon-menu.vue';
@@ -244,9 +243,11 @@ import IconMenuDatatables from '@/components/icon/menu/icon-menu-datatables.vue'
 import IconMenuForms from '@/components/icon/menu/icon-menu-forms.vue';
 import IconMenuPages from '@/components/icon/menu/icon-menu-pages.vue';
 import IconMenuMore from '@/components/icon/menu/icon-menu-more.vue';
-
+import { ElMessageBox } from 'element-plus'
+//ElMessageBox
 const store = useStore();
 const route = useRoute();
+const router = useRouter()
 const search = ref(false);
 
 // multi language
@@ -354,5 +355,25 @@ const toggleSidebars = () => {
 const toggleTheme = (theme) => {
     store.dispatch('toggleTheme', theme);
 };
-
+const close = () => {
+    console.log("001");
+}
+const handleLogoutClick = () => {
+    ElMessageBox.confirm(
+        '确定退出吗?',
+        '提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+        }
+    )
+        .then(() => {
+            store.dispatch('logoutAction').then(() => {
+                const route = router.resolve('/login');
+                location.replace(route.href); // 为了重新实例化vue-router对象 避免bug
+            });
+        })
+        .catch(() => { /* Handle cancel action if needed */ });
+};
 </script>

+ 2 - 1
src/locales/zh.json

@@ -132,5 +132,6 @@
     "val_username": "请输入管理员名称",
     "val_password": "请输入管理员密码",
     "val_validcode": "请输入图片验证码",
-    "val_form": "表单填写有误,请检查!"
+    "val_form": "表单填写有误,请检查!",
+    "company_name":"请输入公司名称"
 }

+ 6 - 1
src/permission.js

@@ -28,9 +28,14 @@ let toFirstRoute = function getTopRoutePath(router, next) {
     router.replace(path)
   }
 }
-console.log(router);
 router.beforeEach(async (to, from, next) => {
   const store = useStore()
+  if (to?.meta?.layout == 'auth') {
+    store.dispatch("setMainLayout", 'auth');
+  } else {
+    store.dispatch("setMainLayout", 'app');
+  }
+  next(true);
   const refreshToken = Storage.getItem('admin_refresh_token')
   if (refreshToken) {
     if ((to.path === '/login' || to.path === '/franchise/login') && store.getters.addRouters.length) {

+ 2 - 2
src/router/index.ts

@@ -24,7 +24,7 @@ const asyncRouterMap: RouteRecordRaw[] = [
 asyncRouterMap.forEach(route => {
     router.addRoute(route);
 });
-router.beforeEach((to, from, next) => {
+/* router.beforeEach((to, from, next) => {
     const store = useStore();
     //判断当前页面是否带有侧边栏及顶部
     if (to?.meta?.layout == 'auth') {
@@ -33,7 +33,7 @@ router.beforeEach((to, from, next) => {
         store.dispatch("setMainLayout",'app');
     }
     next(true);
-});
+}); */
 
 export { constantRouterMap, asyncRouterMap };
 export default router;

+ 189 - 187
src/views/auth/boxed-signin.vue

@@ -1,32 +1,25 @@
 <template>
-    <div>
-        <div class="absolute inset-0">
-            <img src="/assets/images/auth/bg-gradient.png" alt="image" class="h-full w-full object-cover" />
-        </div>
-
-        <div
-            class="relative flex items-center justify-center bg-[url(/assets/images/auth/map.png)] bg-cover bg-center bg-no-repeat dark:bg-[#060818] sm:px-16">
-
-
-            <img src="/assets/images/auth/coming-soon-object3.png" alt="image"
-                class="absolute right-0 top-0 h-[300px]" />
+  <div>
+    <div class="absolute inset-0">
+      <img src="/assets/images/auth/bg-gradient.png" alt="image" class="h-full w-full object-cover" />
+    </div>
 
-            <div
-                class="relative w-full max-w-[870px] rounded-md bg-[linear-gradient(45deg,#fff9f9_0%,rgba(255,255,255,0)_25%,rgba(255,255,255,0)_75%,_#fff9f9_100%)] p-2 dark:bg-[linear-gradient(52.22deg,#0E1726_0%,rgba(14,23,38,0)_18.66%,rgba(14,23,38,0)_51.04%,rgba(14,23,38,0)_80.07%,#0E1726_100%)]">
-                <div
-                    class="relative flex flex-col justify-center rounded-md bg-white/60 backdrop-blur-lg dark:bg-black/50 px-6 lg:min-h-[758px] py-20">
-                    <div class="absolute top-6 end-6">
-                        <div class="dropdown">
+    <div class="relative flex items-center justify-center bg-[url(/assets/images/auth/map.png)] bg-cover bg-center bg-no-repeat dark:bg-[#060818] sm:px-16">
+      <img src="/assets/images/auth/coming-soon-object3.png" alt="image" class="absolute right-0 top-0 h-[300px]" />
 
-                        </div>
-                    </div>
-                    <div class="mx-auto w-full max-w-[440px]">
-                        <div class="mb-10">
-                            <h1 class="text-3xl font-extrabold uppercase !leading-snug text-primary md:text-4xl">Sign in
-                            </h1>
-                            <p class="text-base font-bold leading-normal text-white-dark">欢迎登录V3StudioApp</p>
-                        </div>
-                        <!--  <form class="space-y-5 dark:text-white" @submit.prevent="router.push('/')">
+      <div
+        class="relative w-full max-w-[870px] rounded-md bg-[linear-gradient(45deg,#fff9f9_0%,rgba(255,255,255,0)_25%,rgba(255,255,255,0)_75%,_#fff9f9_100%)] p-2 dark:bg-[linear-gradient(52.22deg,#0E1726_0%,rgba(14,23,38,0)_18.66%,rgba(14,23,38,0)_51.04%,rgba(14,23,38,0)_80.07%,#0E1726_100%)]"
+      >
+        <div class="relative flex flex-col justify-center rounded-md bg-white/60 backdrop-blur-lg dark:bg-black/50 px-6 lg:min-h-[758px] py-20">
+          <div class="absolute top-6 end-6">
+            <div class="dropdown"></div>
+          </div>
+          <div class="mx-auto w-full max-w-[440px]">
+            <div class="mb-10">
+              <h1 class="text-3xl font-extrabold uppercase !leading-snug text-primary md:text-4xl">Sign in</h1>
+              <p class="text-base font-bold leading-normal text-white-dark">欢迎登录V3StudioApp</p>
+            </div>
+            <!--  <form class="space-y-5 dark:text-white" @submit.prevent="router.push('/')">
                             <div>
                                 <label for="Email">请输入账号</label>
                                 <div class="relative text-white-dark">
@@ -58,61 +51,68 @@
                                 登录
                             </button>
                         </form> -->
-                        <!-- <el-button @click="goHome">测试</el-button> -->
-                        <el-form :model="loginForm" :rules="loginRules" ref="loginFormRef" class="login-input">
-                            <el-form-item prop="username">
-                                <el-input v-model="loginForm.username" :placeholder="$t('username')" autofocus
-                                    clearable>
-                                    <template v-slot:prefix>
-                                        <svg-icon class="el-input__icon" icon-class="user" />
-                                    </template>
-                                </el-input>
-                            </el-form-item>
-                            <el-form-item prop="password">
-                                <el-input v-model="loginForm.password" type="password" autocomplete="off"
-                                    :placeholder="$t('password')" :minlength="6" :maxlength="20" clearable>
-                                    <template v-slot:prefix>
-                                        <svg-icon class="el-input__icon" icon-class="password" />
-                                    </template>
-                                </el-input>
-                            </el-form-item>
-                            <el-form-item prop="validcode" v-if="validateInFO.validator_type === 'IMAGE'">
-                                <el-input v-model="loginForm.validcode" :placeholder="$t('validcode')" :maxlength="4"
-                                    clearable>
-                                    <template v-slot:append>
-                                        <img class="login-validcode-img" :src="validcodeImg" @click="changeValidcode">
-                                    </template>
-                                </el-input>
-                            </el-form-item>
-                            <div v-else-if="validateInFO.validator_type === 'ALIYUN'" style="margin-bottom: 20px">
-                                <div id="pc-valid" class="nc-container"></div>
-                            </div>
-                            <el-form-item>
-                                <el-button type="primary" :loading="loading" :disabled="!accountAfsSuccess" class="btn"
-                                    @click="submitLogin(loginFormRef)">
-                                    {{ $t('logIn') }}
-                                </el-button>
-                            </el-form-item>
-                        </el-form>
-                        <!-- 新用户注册账号--暂不开放 -->
-                        <!-- <div class="relative my-7 text-center md:mb-9">
+            <!-- <el-button @click="goHome">测试</el-button> -->
+            <el-form :model="loginForm" :rules="loginRules" ref="loginFormRef" class="login-input">
+              <el-form-item prop="company_name">
+                <el-select v-model="loginForm.company_name" filterable :placeholder="$t('company_name')" style="width: 240px">
+                  <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </el-form-item>
+              <el-form-item prop="username">
+                <el-input v-model="loginForm.username" :placeholder="$t('username')" autofocus clearable>
+                  <template v-slot:prefix>
+                    <svg-icon class="el-input__icon" icon-class="user" />
+                  </template>
+                </el-input>
+              </el-form-item>
+              <el-form-item prop="password">
+                <el-input
+                  v-model="loginForm.password"
+                  type="password"
+                  autocomplete="off"
+                  :placeholder="$t('password')"
+                  :minlength="6"
+                  :maxlength="20"
+                  clearable
+                >
+                  <template v-slot:prefix>
+                    <svg-icon class="el-input__icon" icon-class="password" />
+                  </template>
+                </el-input>
+              </el-form-item>
+              <el-form-item prop="validcode" v-if="validateInFO.validator_type === 'IMAGE'">
+                <el-input v-model="loginForm.validcode" :placeholder="$t('validcode')" :maxlength="4" clearable>
+                  <template v-slot:append>
+                    <img class="login-validcode-img h-8 w-full p-0" :src="validcodeImg" @click="changeValidcode" />
+                  </template>
+                </el-input>
+              </el-form-item>
+              <div v-else-if="validateInFO.validator_type === 'ALIYUN'" style="margin-bottom: 20px">
+                <div id="pc-valid" class="nc-container"></div>
+              </div>
+              <el-form-item>
+                <el-button type="primary" :loading="loading" :disabled="!accountAfsSuccess" class="btn" @click="submitLogin(loginFormRef)">
+                  {{ $t('logIn') }}
+                </el-button>
+              </el-form-item>
+            </el-form>
+            <!-- 新用户注册账号--暂不开放 -->
+            <!-- <div class="relative my-7 text-center md:mb-9">
                             <span class="absolute inset-x-0 top-1/2 h-px w-full -translate-y-1/2 bg-white-light dark:bg-white-dark"></span>
                             <span class="relative bg-white px-2 font-bold uppercase text-white-dark dark:bg-dark dark:text-white-light">or</span>
                         </div> -->
 
-
-
-                        <!-- <div class="text-center dark:text-white">
+            <!-- <div class="text-center dark:text-white">
                            新用户请注册 ?
                             <router-link to="/auth/boxed-signup" class="uppercase text-primary underline transition hover:text-black dark:hover:text-white">
                                 注册
                             </router-link>
                         </div> -->
-                    </div>
-                </div>
-            </div>
+          </div>
         </div>
+      </div>
     </div>
+  </div>
 </template>
 <script lang="ts" setup>
 import { computed, onMounted, reactive, ref } from 'vue';
@@ -122,166 +122,168 @@ import appSetting from '@/app-setting';
 import { useStore } from 'vuex';
 import { useRouter, useRoute } from 'vue-router';
 import { useMeta } from '@/composables/use-meta';
-import Storage from '@/utils/storage'
-import * as API_common from '@/api/common'
-import { v4 as uuidv4 } from "uuid";
-import AliyunAfs from '@/composables/AliyunAfs'
-import { ElMessage, FormInstance } from 'element-plus'
+import Storage from '@/utils/storage';
+import * as API_common from '@/api/common';
+import { v4 as uuidv4 } from 'uuid';
+import AliyunAfs from '@/composables/AliyunAfs';
+import { ElMessage, FormInstance } from 'element-plus';
 import app from '@/stores/modules/app';
 
+const loading: any = ref(false);
+
+const options:any=ref([])
 
-const loading: any = ref(false)
 const loginForm = reactive({
-    username: '',
-    password: '',
-    scene: 'LOGIN',
-    validcode: '',
-    company_name: 'aslkf'
+  username: '',
+  password: '',
+  scene: 'LOGIN',
+  validcode: '',
+  company_name: 'aslkf',
 });
 const { t } = useI18n();
 const loginRules = reactive({
-    username: [
-        { required: true, message: t('val_username'), trigger: 'blur' }
-    ],
-    password: [
-        { required: true, message: t('val_password'), trigger: 'blur' }
-    ],
-    validcode: [
-        { required: true, message: t('val_validcode'), trigger: 'blur' }
-    ]
+  username: [{ required: true, message: t('val_username'), trigger: 'blur' }],
+  password: [{ required: true, message: t('val_password'), trigger: 'blur' }],
+  validcode: [{ required: true, message: t('val_validcode'), trigger: 'blur' }],
 });
 // 验证信息
-const validateInFO: any = ref({})
-let validcodeImg: any = ref('')
-let uuid: any = ref(Storage.getItem('admin_uuid'))
+const validateInFO: any = ref({});
+let validcodeImg: any = ref('');
+let uuid: any = ref(Storage.getItem('admin_uuid'));
 // 阿里云验证条实例
-let afs: any = ref(null)
+let afs: any = ref(null);
 // 当滑动验证成功之后返回的参数
 const afsParam: any = ref({
-    c_sessionid: '',
-    sig: '',
-    nc_token: ''
-})
+  c_sessionid: '',
+  sig: '',
+  nc_token: '',
+});
 // 阿里云滑动验证是否通过 && 如果不是 阿里云验证则直接设置为 true
-const accountAfsSuccess: any = ref(false)
+const accountAfsSuccess: any = ref(false);
 // 是否为加盟商登录
-const is_franchise: any = ref(false)
-const loginFormRef = ref<FormInstance>()
-
+const is_franchise: any = ref(false);
+const loginFormRef = ref<FormInstance>();
 
 useMeta({ title: 'Login Boxed' });
 const router = useRouter();
-const route = useRoute()
+const route = useRoute();
 const store = useStore();
 // multi language
 const i18n = reactive(useI18n());
 console.log(i18n);
 const changeLanguage = (item: any) => {
-    i18n.locale = item.code;
-    appSetting.toggleLanguage(item);
+  i18n.locale = item.code;
+  appSetting.toggleLanguage(item);
 };
 const currentFlag = computed(() => {
-    return `/assets/images/flags/${i18n.locale.toUpperCase()}.svg`;
+  return `/assets/images/flags/${i18n.locale.toUpperCase()}.svg`;
 });
 
 onMounted(() => {
-    const uuids = Storage.getItem('admin_uuid')
-    if (uuids) {
-        uuid = uuids
+  const uuids = Storage.getItem('admin_uuid');
+  if (uuids) {
+    uuid = uuids;
+  } else {
+    const _uuid = uuidv4();
+    uuid = _uuid;
+    Storage.setItem('admin_uuid', _uuid, { expires: 30 });
+  }
+  changeValidcode();
+  API_common.getValidator().then((res) => {
+    validateInFO.value = res;
+    const { validator_type, aliyun_afs } = res;
+    if (validator_type === 'ALIYUN') {
+      //afs = new AliyunAfs('#pc-valid', aliyun_afs.scene, aliyun_afs.app_key, initCaptcha)
+      afs.init();
     } else {
-        const _uuid = uuidv4()
-        uuid = _uuid
-        Storage.setItem('admin_uuid', _uuid, { expires: 30 })
+      accountAfsSuccess.value = true;
     }
-    changeValidcode();
-    API_common.getValidator().then(res => {
-        validateInFO.value = res
-        const { validator_type, aliyun_afs } = res
-        if (validator_type === 'ALIYUN') {
-            //afs = new AliyunAfs('#pc-valid', aliyun_afs.scene, aliyun_afs.app_key, initCaptcha)
-            afs.init()
-        } else {
-            accountAfsSuccess.value = true
-        }
-    })
+  });
 });
 
 /** 阿里云滑动验证 通过后的回调函数 **/
 const initCaptcha = (data) => {
-    afsParam.c_sessionid = data.csessionid
-    afsParam.sig = data.sig
-    afsParam.nc_token = data.nc_token
-    accountAfsSuccess.value = true
-}
+  afsParam.c_sessionid = data.csessionid;
+  afsParam.sig = data.sig;
+  afsParam.nc_token = data.nc_token;
+  accountAfsSuccess.value = true;
+};
 
 /** 更换图片验证码 */
 const changeValidcode = () => {
-    validcodeImg = API_common.getValidateCodeUrl('LOGIN', uuid)
-    console.log(validcodeImg);
-}
+  validcodeImg.value = API_common.getValidateCodeUrl('LOGIN', uuid);
+  console.log(validcodeImg);
+};
 const MixinClone = (obj) => {
-    return JSON.parse(JSON.stringify(obj))
-}
+  return JSON.parse(JSON.stringify(obj));
+};
 
 /** 登录处理 */
 const dispatchLoginAction = (params) => {
-    loading.value = true;
-    return new Promise((resolve, reject) => {
-        store.dispatch('loginAction', params).then((res: any) => {
-            loading.value = false;
-            if (res) {
-                try {
-                    const WS = new WebSocket(res.access_token);
-                    // 使用 provide/inject 或其他方式在 Vue 3 中共享 WebSocket 实例
-                    app.provide('websocket', WS);
-                } catch (error) {
-                    console.log('websocket 实例化失败:', error);
-                }
-            }
-            const forward = route.query.forward;
-            let query = JSON.parse(JSON.stringify(route.query));
-            delete query.forward
-             router.push({ path: 'dashboard', query }).catch(() => { }); //forward ||
-        }).catch(() => {
-            loading.value = false;
-            reject();
-        });
-    });
-}
+  loading.value = true;
+  return new Promise((resolve, reject) => {
+    store
+      .dispatch('loginAction', params)
+      .then((res: any) => {
+        loading.value = false;
+        if (res) {
+          try {
+            const WS = new WebSocket(res.access_token);
+            // 使用 provide/inject 或其他方式在 Vue 3 中共享 WebSocket 实例
+            app.provide('websocket', WS);
+          } catch (error) {
+            console.log('websocket 实例化失败:', error);
+          }
+        }
+        const forward = route.query.forward;
+        let query = JSON.parse(JSON.stringify(route.query));
+        delete query.forward;
+        router.push({ path: '/', query }).catch(() => {}); //forward ||
+      })
+      .catch(() => {
+        loading.value = false;
+        reject();
+      });
+  });
+};
 
 const submitLogin = (formEl: FormInstance | undefined) => {
-    if (!accountAfsSuccess) return
-    console.log(!afs);
-    if (!afs) {
-        const params = MixinClone(loginForm)
-        params.c_sessionid = afsParam.c_sessionid
-        params.sig = afsParam.sig
-        params.nc_token = afsParam.nc_token
-        delete params.validcode
-        delete params.scene
+  if (!accountAfsSuccess) return;
+  console.log(!afs);
+  if (!afs) {
+    const params = MixinClone(loginForm);
+    params.c_sessionid = afsParam.c_sessionid;
+    params.sig = afsParam.sig;
+    params.nc_token = afsParam.nc_token;
+    delete params.validcode;
+    delete params.scene;
+    dispatchLoginAction(params).catch(() => {
+      accountAfsSuccess.value = false;
+    });
+  } else {
+    formEl?.validate((valid: boolean) => {
+      if (valid) {
+        const params = MixinClone(loginForm);
+        params.uuid = uuid;
+        params.captcha = params.validcode;
+        delete params.validcode;
         dispatchLoginAction(params).catch(() => {
-            accountAfsSuccess.value = false
-        })
-    } else {
-        formEl?.validate((valid: boolean) => {
-            if (valid) {
-                const params = MixinClone(loginForm);
-                params.uuid = uuid;
-                params.captcha = params.validcode;
-                delete params.validcode;
-                dispatchLoginAction(params).catch(() => {
-                    changeValidcode();
-                });
-            } else {
-                // 使用 Element Plus 的消息提示
-                ElMessage.error(t('val_form'));
-                return false;
-            }
+          changeValidcode();
         });
-    }
-}
+      } else {
+        // 使用 Element Plus 的消息提示
+        ElMessage.error(t('val_form'));
+        return false;
+      }
+    });
+  }
+};
 const goHome = () => {
-    router.push({ path: 'dashboard' }).catch(() => { })
-}
-
+  router.push({ path: 'dashboard' }).catch(() => {});
+};
 </script>
+<style>
+.el-input-group__append {
+  padding: 0;
+}
+</style>