From d06a882e870f2aa26934ccd4b552d5292679320f Mon Sep 17 00:00:00 2001
From: zrj <646384940@qq.com>
Date: Wed, 05 Jun 2024 17:23:29 +0800
Subject: [PATCH] 登录调整(集成单点登录)

---
 src/store/modules/user.js    |   40 +++
 vue.config.js                |   18 +
 src/api/user.js              |   36 +++
 src/router/axios.js          |   11 
 src/api/oauth/oauth.js       |   38 +++
 src/page/login/userlogin.vue |  507 ++++++++++++++++++++++++++-------------------
 6 files changed, 430 insertions(+), 220 deletions(-)

diff --git a/src/api/oauth/oauth.js b/src/api/oauth/oauth.js
new file mode 100644
index 0000000..3804ac4
--- /dev/null
+++ b/src/api/oauth/oauth.js
@@ -0,0 +1,38 @@
+import request from '@/router/axios';
+
+export const authorize = ( params) => {
+  return request({
+    url: '/api/oauth/authorize',
+    method: 'get',
+    params: params
+  })
+}
+
+export const getPage = (current, size, params) => {
+  return request({
+    url: '/api/blade-convenienceHotline/convenienceHotline/page',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/blade-convenienceHotline/convenienceHotline/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/blade-convenienceHotline/convenienceHotline/submit',
+    method: 'post',
+    data: row
+  })
+}
+
diff --git a/src/api/user.js b/src/api/user.js
index 1969867..4f0398d 100644
--- a/src/api/user.js
+++ b/src/api/user.js
@@ -17,9 +17,7 @@
     password,
     grant_type:"password",
     scope: "all",
-    type,
-    // 查全部-暂定
-    loginType:1
+    type
   }
 });
 
@@ -70,6 +68,38 @@
   }
 });
 
+export const loginForm = (tenant_id, username, password,client_id,response_type,redirect_uri) => request({
+  url: '/api/oauth/form',
+  method: 'post',
+  headers:{
+    'Content-Type':"application/x-www-form-urlencoded",
+    'client_id':client_id,
+    'response_type':response_type,
+    'redirect_uri':redirect_uri
+  },
+  params: {
+    tenant_id,
+    username,
+    password
+  }
+});
+
+export const loginTo = (tenantId, username, password,client_id,response_type,redirect_uri) => request({
+  url: '/api/oauth/loginTo',
+  method: 'post',
+  headers:{
+    'Content-Type':"application/x-www-form-urlencoded",
+    'client_id':client_id,
+    'response_type':response_type,
+    'redirect_uri':redirect_uri
+  },
+  params: {
+    tenantId,
+    username,
+    password
+  }
+});
+
 export const registerGuest = (form, oauthId) => request({
   url: '/api/blade-system/user/register-guest',
   method: 'post',
diff --git a/src/page/login/userlogin.vue b/src/page/login/userlogin.vue
index eefba39..4196a00 100644
--- a/src/page/login/userlogin.vue
+++ b/src/page/login/userlogin.vue
@@ -1,6 +1,13 @@
 <template>
-    <el-form class="login-form" status-icon :rules="loginRules" ref="loginForm" :model="loginForm" label-width="0">
-        <!-- <el-form-item v-if="tenantMode" prop="tenantId">
+  <el-form
+    class="login-form"
+    status-icon
+    :rules="loginRules"
+    ref="loginForm"
+    :model="loginForm"
+    label-width="0"
+  >
+    <!-- <el-form-item v-if="tenantMode" prop="tenantId">
       <el-input size="small"
                 @keyup.enter.native="handleLogin"
                 v-model="loginForm.tenantId"
@@ -9,20 +16,35 @@
         <i slot="prefix" class="icon-quanxian"/>
       </el-input>
     </el-form-item> -->
-        <el-form-item prop="username">
-            <el-input size="small" @keyup.enter.native="handleLogin" v-model="loginForm.username" auto-complete="off"
-                :placeholder="$t('login.username')">
-                <i slot="prefix" class="icon-yonghu" />
-            </el-input>
-        </el-form-item>
-        <el-form-item prop="password">
-            <el-input size="small" @keyup.enter.native="handleLogin" :type="passwordType" v-model="loginForm.password"
-                auto-complete="off" :placeholder="$t('login.password')">
-                <i class="el-icon-view el-input__icon" slot="suffix" @click="showPassword" />
-                <i slot="prefix" class="icon-mima" />
-            </el-input>
-        </el-form-item>
-        <!-- <el-form-item v-if="this.website.captchaMode" prop="code">
+    <el-form-item prop="username">
+      <el-input
+        size="small"
+        @keyup.enter.native="handleLogin"
+        v-model="loginForm.username"
+        auto-complete="off"
+        :placeholder="$t('login.username')"
+      >
+        <i slot="prefix" class="icon-yonghu" />
+      </el-input>
+    </el-form-item>
+    <el-form-item prop="password">
+      <el-input
+        size="small"
+        @keyup.enter.native="handleLogin"
+        :type="passwordType"
+        v-model="loginForm.password"
+        auto-complete="off"
+        :placeholder="$t('login.password')"
+      >
+        <i
+          class="el-icon-view el-input__icon"
+          slot="suffix"
+          @click="showPassword"
+        />
+        <i slot="prefix" class="icon-mima" />
+      </el-input>
+    </el-form-item>
+    <!-- <el-form-item v-if="this.website.captchaMode" prop="code">
       <el-row :span="24">
         <el-col :span="16">
           <el-input size="small"
@@ -41,221 +63,276 @@
         </el-col>
       </el-row>
     </el-form-item> -->
-        <el-form-item>
-            <el-button type="primary" size="small" @click.native.prevent="handleLogin" class="login-submit">{{
-                $t('login.submit') }}
-            </el-button>
-        </el-form-item>
-        <el-dialog title="用户信息选择" append-to-body :visible.sync="userBox" width="350px">
-            <avue-form :option="userOption" v-model="userForm" @submit="submitLogin" />
-        </el-dialog>
-    </el-form>
+    <el-form-item>
+      <el-button
+        type="primary"
+        size="small"
+        @click.native.prevent="handleLogin"
+        class="login-submit"
+        >{{ $t("login.submit") }}
+      </el-button>
+    </el-form-item>
+    <el-dialog
+      title="用户信息选择"
+      append-to-body
+      :visible.sync="userBox"
+      width="350px"
+    >
+      <avue-form
+        :option="userOption"
+        v-model="userForm"
+        @submit="submitLogin"
+      />
+    </el-dialog>
+  </el-form>
 </template>
 
 <script>
-import Layout from "@/page/index/"
-import { mapGetters } from "vuex"
-import { info } from "@/api/system/tenant"
+import Layout from "@/page/index/";
+import { mapGetters } from "vuex";
+import { info } from "@/api/system/tenant";
+import { authorize } from "@/api/oauth/oauth";
 // import {getCaptcha} from "@/api/user";
-import { getTopUrl } from "@/util/util"
-
+import { getTopUrl } from "@/util/util";
+import axios from "axios";
 export default {
-    name: "userlogin",
-    data () {
-        return {
-            tenantMode: this.website.tenantMode,
-            loginForm: {
-                //租户ID
-                tenantId: "000000",
-                //部门ID
-                deptId: "",
-                //角色ID
-                roleId: "",
-                //用户名
-                username: "",
-                //密码
-                password: "",
-                //账号类型
-                type: "account",
-                //验证码的值
-                code: "",
-                //验证码的索引
-                key: "",
-                //预加载白色背景
-                image: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
+  name: "userlogin",
+  data() {
+    return {
+      params: {
+        // URL 上的 client_id、scope 等参数
+        response_type: undefined,
+        client_id: undefined,
+        redirect_uri: undefined,
+      },
+      tenantMode: this.website.tenantMode,
+      loginForm: {
+        //租户ID
+        tenantId: "000000",
+        //部门ID
+        deptId: "",
+        //角色ID
+        roleId: "",
+        //用户名
+        username: "",
+        //密码
+        password: "",
+        //账号类型
+        type: "account",
+        //验证码的值
+        code: "",
+        //验证码的索引
+        key: "",
+        //预加载白色背景
+        image:
+          "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
+      },
+      loginRules: {
+        // tenantId: [
+        //   {required: false, message: "请输入租户ID", trigger: "blur"}
+        // ],
+        username: [
+          { required: true, message: "请输入用户名", trigger: "blur" },
+        ],
+        password: [
+          { required: true, message: "请输入密码", trigger: "blur" },
+          { min: 1, message: "密码长度最少为6位", trigger: "blur" },
+        ],
+      },
+      passwordType: "password",
+      userBox: false,
+      userForm: {
+        deptId: "",
+        roleId: "",
+      },
+      userOption: {
+        labelWidth: 70,
+        submitBtn: true,
+        emptyBtn: false,
+        submitText: "登录",
+        column: [
+          {
+            label: "部门",
+            prop: "deptId",
+            type: "select",
+            props: {
+              label: "deptName",
+              value: "id",
             },
-            loginRules: {
-                // tenantId: [
-                //   {required: false, message: "请输入租户ID", trigger: "blur"}
-                // ],
-                username: [
-                    { required: true, message: "请输入用户名", trigger: "blur" }
-                ],
-                password: [
-                    { required: true, message: "请输入密码", trigger: "blur" },
-                    { min: 1, message: "密码长度最少为6位", trigger: "blur" }
-                ]
+            dicUrl: "/api/blade-system/dept/select",
+            span: 24,
+            display: false,
+            rules: [
+              {
+                required: true,
+                message: "请选择部门",
+                trigger: "blur",
+              },
+            ],
+          },
+          {
+            label: "角色",
+            prop: "roleId",
+            type: "select",
+            props: {
+              label: "roleName",
+              value: "id",
             },
-            passwordType: "password",
-            userBox: false,
-            userForm: {
-                deptId: '',
-                roleId: ''
-            },
-            userOption: {
-                labelWidth: 70,
-                submitBtn: true,
-                emptyBtn: false,
-                submitText: '登录',
-                column: [
-                    {
-                        label: '部门',
-                        prop: 'deptId',
-                        type: 'select',
-                        props: {
-                            label: 'deptName',
-                            value: 'id'
-                        },
-                        dicUrl: '/api/blade-system/dept/select',
-                        span: 24,
-                        display: false,
-                        rules: [{
-                            required: true,
-                            message: "请选择部门",
-                            trigger: "blur"
-                        }],
-                    },
-                    {
-                        label: '角色',
-                        prop: 'roleId',
-                        type: 'select',
-                        props: {
-                            label: 'roleName',
-                            value: 'id'
-                        },
-                        dicUrl: '/api/blade-system/role/select',
-                        span: 24,
-                        display: false,
-                        rules: [{
-                            required: true,
-                            message: "请选择角色",
-                            trigger: "blur"
-                        }],
-                    },
-                ]
-            }
-        }
+            dicUrl: "/api/blade-system/role/select",
+            span: 24,
+            display: false,
+            rules: [
+              {
+                required: true,
+                message: "请选择角色",
+                trigger: "blur",
+              },
+            ],
+          },
+        ],
+      },
+    };
+  },
+  created() {
+    this.getTenant();
+    //   this.refreshCode();
+    this.params.response_type = this.$route.query.response_type;
+    this.params.client_id = this.$route.query.client_id;
+    this.params.redirect_uri = this.$route.query.redirect_uri;
+    this.loginForm["response_type"] = this.$route.query.response_type;
+    this.loginForm["client_id"] = this.$route.query.client_id;
+    this.loginForm["redirect_uri"] = this.$route.query.redirect_uri;
+  },
+  mounted() {},
+  watch: {
+    "loginForm.deptId"() {
+      const column = this.findObject(this.userOption.column, "deptId");
+      if (this.loginForm.deptId.includes(",")) {
+        column.dicUrl = `/api/blade-system/dept/select?deptId=${this.loginForm.deptId}`;
+        column.display = true;
+      } else {
+        column.dicUrl = "";
+      }
     },
-    created () {
-        this.getTenant()
-        //   this.refreshCode();
+    "loginForm.roleId"() {
+      const column = this.findObject(this.userOption.column, "roleId");
+      if (this.loginForm.roleId.includes(",")) {
+        column.dicUrl = `/api/blade-system/role/select?roleId=${this.loginForm.roleId}`;
+        column.display = true;
+      } else {
+        column.dicUrl = "";
+      }
     },
-    mounted () {
+  },
+  computed: {
+    ...mapGetters(["tagWel", "userInfo"]),
+  },
+  props: [],
+  methods: {
+    async getAuthorize(params) {
+      const response = await axios.get(
+        "http://localhost:8100/oauth/authorize?client_id=sword&response_type=code&redirect_uri=https://www.baidu.com"
+      );
+      this.headers = response.headers;
     },
-    watch: {
-        'loginForm.deptId' () {
-            const column = this.findObject(this.userOption.column, "deptId")
-            if (this.loginForm.deptId.includes(",")) {
-                column.dicUrl = `/api/blade-system/dept/select?deptId=${this.loginForm.deptId}`
-                column.display = true
-            } else {
-                column.dicUrl = ''
-            }
-        },
-        'loginForm.roleId' () {
-            const column = this.findObject(this.userOption.column, "roleId")
-            if (this.loginForm.roleId.includes(",")) {
-                column.dicUrl = `/api/blade-system/role/select?roleId=${this.loginForm.roleId}`
-                column.display = true
-            } else {
-                column.dicUrl = ''
-            }
-        }
+    // refreshCode () {
+    //     if (this.website.captchaMode) {
+    //         getCaptcha().then(res => {
+    //             const data = res.data
+    //             this.loginForm.key = data.key
+    //             this.loginForm.image = data.image
+    //         })
+    //     }
+    // },
+    showPassword() {
+      this.passwordType === ""
+        ? (this.passwordType = "password")
+        : (this.passwordType = "");
     },
-    computed: {
-        ...mapGetters(["tagWel", "userInfo"])
+    submitLogin(form, done) {
+      if (form.deptId !== "") {
+        this.loginForm.deptId = form.deptId;
+      }
+      if (form.roleId !== "") {
+        this.loginForm.roleId = form.roleId;
+      }
+      this.handleLogin();
+      done();
     },
-    props: [],
-    methods: {
-        // refreshCode () {
-        //     if (this.website.captchaMode) {
-        //         getCaptcha().then(res => {
-        //             const data = res.data
-        //             this.loginForm.key = data.key
-        //             this.loginForm.image = data.image
-        //         })
-        //     }
-        // },
-        showPassword () {
-            this.passwordType === ""
-                ? (this.passwordType = "password")
-                : (this.passwordType = "")
-        },
-        submitLogin (form, done) {
-            if (form.deptId !== '') {
-                this.loginForm.deptId = form.deptId
-            }
-            if (form.roleId !== '') {
-                this.loginForm.roleId = form.roleId
-            }
-            this.handleLogin()
-            done()
-        },
-        handleLogin () {
-            this.$refs.loginForm.validate(valid => {
-                if (valid) {
-                    const loading = this.$loading({
-                        lock: true,
-                        text: '登录中,请稍后。。。',
-                        spinner: "el-icon-loading"
-                    })
-                    this.$store.dispatch("LoginByUsername", this.loginForm).then((res) => {
-                        if (res.error) {
-                            loading.close()
-                            return
-                        }
-
-                        if (this.website.switchMode) {
-                            const deptId = this.userInfo.dept_id
-                            const roleId = this.userInfo.role_id
-                            if (deptId.includes(",") || roleId.includes(",")) {
-                                this.loginForm.deptId = deptId
-                                this.loginForm.roleId = roleId
-                                this.userBox = true
-                                this.$store.dispatch("LogOut").then(() => {
-                                    loading.close()
-                                })
-                                return false
-                            }
-                        }
-
-                        this.$router.$avueRouter.formatRoutes(res.menuData, true)
-                        this.$router.push({ path: res.fistMenu.path })
-
-                        loading.close()
-                    }).catch(() => {
-                        loading.close()
-                        // this.refreshCode()
-                    })
+    handleLogin() {
+      this.$refs.loginForm.validate((valid) => {
+        if (valid) {
+          const loading = this.$loading({
+            lock: true,
+            text: "登录中,请稍后。。。",
+            spinner: "el-icon-loading",
+          });
+          if (
+            this.$route.query.response_type &&
+            this.$route.query.client_id &&
+            this.$route.query.redirect_uri
+          ) {
+            this.$store
+              .dispatch("loginForm", this.loginForm)
+              .then((res) => {
+                loading.close();
+              })
+              .catch(() => {
+                loading.close();
+                // this.refreshCode()
+              });
+          } else {
+            this.$store
+              .dispatch("LoginByUsername", this.loginForm)
+              .then((res) => {
+                if (res.error) {
+                  loading.close();
+                  return;
                 }
-            })
-        },
 
-        getTenant () {
-            let domain = getTopUrl()
-            // 临时指定域名,方便测试
-            //domain = "https://bladex.cn";
-            info(domain).then(res => {
-                const data = res.data
-                if (data.success && data.data.tenantId) {
-                    this.tenantMode = false
-                    this.loginForm.tenantId = data.data.tenantId
-                    this.$parent.$refs.login.style.backgroundImage = `url(${data.data.backgroundUrl})`
+                if (this.website.switchMode) {
+                  const deptId = this.userInfo.dept_id;
+                  const roleId = this.userInfo.role_id;
+                  if (deptId.includes(",") || roleId.includes(",")) {
+                    this.loginForm.deptId = deptId;
+                    this.loginForm.roleId = roleId;
+                    this.userBox = true;
+                    this.$store.dispatch("LogOut").then(() => {
+                      loading.close();
+                    });
+                    return false;
+                  }
                 }
-            })
+
+                this.$router.$avueRouter.formatRoutes(res.menuData, true);
+                this.$router.push({ path: "/404" });
+
+                loading.close();
+              })
+              .catch(() => {
+                loading.close();
+                // this.refreshCode()
+              });
+          }
         }
-    }
-}
+      });
+    },
+
+    getTenant() {
+      let domain = getTopUrl();
+      // 临时指定域名,方便测试
+      //domain = "https://bladex.cn";
+      info(domain).then((res) => {
+        const data = res.data;
+        if (data.success && data.data.tenantId) {
+          this.tenantMode = false;
+          this.loginForm.tenantId = data.data.tenantId;
+          this.$parent.$refs.login.style.backgroundImage = `url(${data.data.backgroundUrl})`;
+        }
+      });
+    },
+  },
+};
 </script>
 
 <style></style>
diff --git a/src/router/axios.js b/src/router/axios.js
index 75c85e3..28eea84 100644
--- a/src/router/axios.js
+++ b/src/router/axios.js
@@ -69,23 +69,32 @@
 });
 //http response 拦截
 axios.interceptors.response.use(res => {
+  // console.log(res,33)
   //关闭 progress bar
   NProgress.done();
   //获取状态码
   const status = res.data.code || res.status;
   const statusWhiteList = website.statusWhiteList || [];
   const message = res.data.msg || res.data.error_description || '未知错误';
+  if(res.config.url=='/api/oauth/form' && res.status == 200){
+    window.open(res.request.responseURL,'_self')
+    return
+  }
   //如果在白名单里则自行catch逻辑处理
   if (statusWhiteList.includes(status)) return Promise.reject(res);
   //如果是401则跳转到登录页面
   if (status === 401) store.dispatch('FedLogOut').then(() => router.push({path: '/login'}));
   // 如果请求为非200否者默认统一处理
   if (status !== 200) {
+    // console.log(message,888)
     Message({
       message: message,
       type: 'error'
     });
-    return Promise.reject(new Error(message))
+    // NProgress.done();
+    if(res.config.url=='/api/oauth/token'){
+      return Promise.reject(new Error(message))
+    }
   }
   return res;
 }, error => {
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index 9400031..a73f3e2 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -10,6 +10,8 @@
 import { deepClone } from "@/util/util";
 import website from "@/config/website";
 import {
+  loginTo,
+  loginForm,
   loginByUsername,
   loginBySocial,
   loginBySso,
@@ -71,6 +73,44 @@
     homeFirstTagPage: getStore({ name: "firstTagPage" }) || {},
   },
   actions: {
+    //自定义表单登录
+    loginTo({ dispatch, commit }, userInfo) {
+      return new Promise((resolve) => {
+        loginTo(
+          userInfo.tenantId,
+          userInfo.username,
+          md5(userInfo.password),
+          userInfo.client_id,
+          userInfo.response_type,
+          userInfo.redirect_uri
+        ).then((res) => {
+          // const data = res.data.data;
+          // commit("SET_TOKEN", data);
+          // commit("DEL_ALL_TAG");
+          // commit("CLEAR_LOCK");
+          resolve();
+        });
+      });
+    },
+    //表单登录
+    loginForm({ dispatch, commit }, userInfo) {
+      return new Promise((resolve) => {
+        loginForm(
+          userInfo.tenantId,
+          userInfo.username,
+          md5(userInfo.password),
+          userInfo.client_id,
+          userInfo.response_type,
+          userInfo.redirect_uri
+        ).then((res) => {
+          // const data = res.data.data;
+          // commit("SET_TOKEN", data);
+          // commit("DEL_ALL_TAG");
+          // commit("CLEAR_LOCK");
+          resolve();
+        });
+      });
+    },
     //根据用户名登录
     LoginByUsername({ dispatch, commit }, userInfo) {
       return new Promise((resolve, reject) => {
diff --git a/vue.config.js b/vue.config.js
index ba231d1..2464558 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -38,7 +38,7 @@
         proxy: {
             "/api": {
                 //本地服务接口地址
-                target:"http://192.168.1.50:8110/",
+                target:"http://192.168.1.50:8100",
                 // target: "https://srgdjczzxtpt.com:2080/api",
                 // target: "https://kt39592615.goho.co",
                 // target: "http://z4042833u6.wicp.vip",
@@ -52,6 +52,22 @@
                     "^/api": "/",
                 },
             },
+            "/www.baidu.com": {
+                //本地服务接口地址
+                target:"https://www.baidu.com",
+                // target: "https://srgdjczzxtpt.com:2080/api",
+                // target: "https://kt39592615.goho.co",
+                // target: "http://z4042833u6.wicp.vip",
+                // target: "http://localhost:9528",
+                // target: "http://192.168.2.109:9528",
+                //远程演示服务地址,可用于直接启动项目
+                //target: 'https://saber.bladex.cn/api',
+                changeOrigin: true,
+                ws: true,
+                // pathRewrite: {
+                //     "^/api": "/",
+                // },
+            },
         },
     },
 }

--
Gitblit v1.9.3