mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 00:10:25 +08:00 
			
		
		
		
	refactor: oauth2登录调整
This commit is contained in:
		@@ -1,24 +1,25 @@
 | 
				
			|||||||
window.globalConfig = {
 | 
					window.globalConfig = {
 | 
				
			||||||
    // 默认为空,以访问根目录为api请求地址。若前后端分离部署可单独配置该后端api请求地址
 | 
					    // 默认为空,以访问根目录为api请求地址。若前后端分离部署可单独配置该后端api请求地址
 | 
				
			||||||
    "BaseApiUrl": "",
 | 
					    BaseApiUrl: '',
 | 
				
			||||||
    "BaseWsUrl": ""
 | 
					    BaseWsUrl: '',
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// index.html添加百秒级时间戳,防止被浏览器缓存
 | 
					// index.html添加百秒级时间戳,防止被浏览器缓存
 | 
				
			||||||
!function () {
 | 
					// !(function () {
 | 
				
			||||||
    let t = "t=" + new Date().getTime().toString().substring(0, 8)
 | 
					//     let t = 't=' + new Date().getTime().toString().substring(0, 8);
 | 
				
			||||||
    let search = location.search;
 | 
					//     let search = location.search;
 | 
				
			||||||
    let m = search && search.match(/t=\d*/g)
 | 
					//     let m = search && search.match(/t=\d*/g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (m[0]) {
 | 
					//     console.log(location);
 | 
				
			||||||
        if (m[0] !== t) {
 | 
					//     if (m[0]) {
 | 
				
			||||||
            location.search = search.replace(m[0], t)
 | 
					//         if (m[0] !== t) {
 | 
				
			||||||
        }
 | 
					//             location.search = search.replace(m[0], t);
 | 
				
			||||||
    } else {
 | 
					//         }
 | 
				
			||||||
        if (search.indexOf('?') > -1) {
 | 
					//     } else {
 | 
				
			||||||
            location.search = search + '&' + t
 | 
					//         if (search.indexOf('?') > -1) {
 | 
				
			||||||
        } else {
 | 
					//             location.search = search + '&' + t;
 | 
				
			||||||
            location.search = t
 | 
					//         } else {
 | 
				
			||||||
        }
 | 
					//             location.search = t;
 | 
				
			||||||
    }
 | 
					//         }
 | 
				
			||||||
}()
 | 
					//     }
 | 
				
			||||||
 | 
					// })();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,4 +10,5 @@ export default {
 | 
				
			|||||||
    captcha: () => request.get('/sys/captcha'),
 | 
					    captcha: () => request.get('/sys/captcha'),
 | 
				
			||||||
    logout: () => request.post('/auth/accounts/logout'),
 | 
					    logout: () => request.post('/auth/accounts/logout'),
 | 
				
			||||||
    getPermissions: () => request.get('/sys/accounts/permissions'),
 | 
					    getPermissions: () => request.get('/sys/accounts/permissions'),
 | 
				
			||||||
 | 
					    oauth2Callback: (params: any) => request.get('/auth/oauth2/callback', params),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -257,7 +257,7 @@ router.beforeEach(async (to, from, next) => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const token = getSession('token');
 | 
					    const token = getSession('token');
 | 
				
			||||||
    if (to.path === '/login' && !token) {
 | 
					    if ((to.path === '/login' || to.path == '/oauth2/callback') && !token) {
 | 
				
			||||||
        next();
 | 
					        next();
 | 
				
			||||||
        NProgress.done();
 | 
					        NProgress.done();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,6 +143,14 @@ export const staticRoutes: Array<RouteRecordRaw> = [
 | 
				
			|||||||
            title: '没有权限',
 | 
					            title: '没有权限',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        path: '/oauth2/callback',
 | 
				
			||||||
 | 
					        name: 'oauth2Callback',
 | 
				
			||||||
 | 
					        component: () => import('@/views/oauth/Oauth2Callback.vue'),
 | 
				
			||||||
 | 
					        meta: {
 | 
				
			||||||
 | 
					            title: 'oauth2回调',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        path: '/machine/terminal',
 | 
					        path: '/machine/terminal',
 | 
				
			||||||
        name: 'machineTerminal',
 | 
					        name: 'machineTerminal',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -104,6 +104,24 @@
 | 
				
			|||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <el-dialog title="修改基本信息" v-model="baseInfoDialog.visible" :close-on-click-modal="false" width="450px" :destroy-on-close="true">
 | 
				
			||||||
 | 
					            <el-form :model="baseInfoDialog.form" :rules="baseInfoDialog.rules" ref="changePwdFormRef" label-width="auto">
 | 
				
			||||||
 | 
					                <el-form-item prop="username" label="用户名" required>
 | 
				
			||||||
 | 
					                    <el-input v-model.trim="baseInfoDialog.form.username"></el-input>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					                <el-form-item prop="name" label="姓名" required>
 | 
				
			||||||
 | 
					                    <el-input v-model.trim="baseInfoDialog.form.name"></el-input>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					            </el-form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <template #footer>
 | 
				
			||||||
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
 | 
					                    <!-- <el-button @click="cancelChangePwd">取 消</el-button> -->
 | 
				
			||||||
 | 
					                    <el-button @click="updateUserInfo()" type="primary" :loading="loading.updateUserConfirm">确 定</el-button>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					        </el-dialog>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -112,7 +130,7 @@ import { nextTick, onMounted, ref, toRefs, reactive, computed } from 'vue';
 | 
				
			|||||||
import { useRoute, useRouter } from 'vue-router';
 | 
					import { useRoute, useRouter } from 'vue-router';
 | 
				
			||||||
import { ElMessage } from 'element-plus';
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
import { initRouter } from '@/router/index';
 | 
					import { initRouter } from '@/router/index';
 | 
				
			||||||
import { setSession, setUserInfo2Session, setUseWatermark2Session } from '@/common/utils/storage';
 | 
					import { getSession, setSession, setUserInfo2Session, setUseWatermark2Session } from '@/common/utils/storage';
 | 
				
			||||||
import { formatAxis } from '@/common/utils/format';
 | 
					import { formatAxis } from '@/common/utils/format';
 | 
				
			||||||
import openApi from '@/common/openApi';
 | 
					import openApi from '@/common/openApi';
 | 
				
			||||||
import { RsaEncrypt } from '@/common/rsa';
 | 
					import { RsaEncrypt } from '@/common/rsa';
 | 
				
			||||||
@@ -120,6 +138,7 @@ import { getAccountLoginSecurity, useWartermark } from '@/common/sysconfig';
 | 
				
			|||||||
import { letterAvatar } from '@/common/utils/string';
 | 
					import { letterAvatar } from '@/common/utils/string';
 | 
				
			||||||
import { useUserInfo } from '@/store/userInfo';
 | 
					import { useUserInfo } from '@/store/userInfo';
 | 
				
			||||||
import QrcodeVue from 'qrcode.vue';
 | 
					import QrcodeVue from 'qrcode.vue';
 | 
				
			||||||
 | 
					import { personApi } from '@/views/personal/api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const rules = {
 | 
					const rules = {
 | 
				
			||||||
    username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
 | 
					    username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
 | 
				
			||||||
@@ -149,6 +168,7 @@ const state = reactive({
 | 
				
			|||||||
        captcha: '',
 | 
					        captcha: '',
 | 
				
			||||||
        cid: '',
 | 
					        cid: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    loginRes: {} as any,
 | 
				
			||||||
    changePwdDialog: {
 | 
					    changePwdDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
        form: {
 | 
					        form: {
 | 
				
			||||||
@@ -178,14 +198,26 @@ const state = reactive({
 | 
				
			|||||||
            code: [{ required: true, message: '请输入OTP授权码', trigger: 'blur' }],
 | 
					            code: [{ required: true, message: '请输入OTP授权码', trigger: 'blur' }],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    baseInfoDialog: {
 | 
				
			||||||
 | 
					        visible: false,
 | 
				
			||||||
 | 
					        form: {
 | 
				
			||||||
 | 
					            username: '',
 | 
				
			||||||
 | 
					            name: '',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        rules: {
 | 
				
			||||||
 | 
					            username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
 | 
				
			||||||
 | 
					            name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    loading: {
 | 
					    loading: {
 | 
				
			||||||
        signIn: false,
 | 
					        signIn: false,
 | 
				
			||||||
        changePwd: false,
 | 
					        changePwd: false,
 | 
				
			||||||
        otpConfirm: false,
 | 
					        otpConfirm: false,
 | 
				
			||||||
 | 
					        updateUserConfirm: false,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { accountLoginSecurity, showLoginFailTips, captchaImage, loginForm, changePwdDialog, otpDialog, loading } = toRefs(state);
 | 
					const { accountLoginSecurity, showLoginFailTips, captchaImage, loginForm, changePwdDialog, otpDialog, baseInfoDialog, loading } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    nextTick(async () => {
 | 
					    nextTick(async () => {
 | 
				
			||||||
@@ -268,7 +300,17 @@ const onSignIn = async () => {
 | 
				
			|||||||
    loginResDeal(loginRes);
 | 
					    loginResDeal(loginRes);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const updateUserInfo = async () => {
 | 
				
			||||||
 | 
					    const form = state.baseInfoDialog.form;
 | 
				
			||||||
 | 
					    await personApi.updateAccount.request(state.baseInfoDialog.form);
 | 
				
			||||||
 | 
					    state.baseInfoDialog.visible = false;
 | 
				
			||||||
 | 
					    useUserInfo().userInfo.username = form.username;
 | 
				
			||||||
 | 
					    useUserInfo().userInfo.name = form.name;
 | 
				
			||||||
 | 
					    await toIndex();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const loginResDeal = (loginRes: any) => {
 | 
					const loginResDeal = (loginRes: any) => {
 | 
				
			||||||
 | 
					    state.loginRes = loginRes;
 | 
				
			||||||
    // 用户信息
 | 
					    // 用户信息
 | 
				
			||||||
    const userInfos = {
 | 
					    const userInfos = {
 | 
				
			||||||
        name: loginRes.name,
 | 
					        name: loginRes.name,
 | 
				
			||||||
@@ -300,16 +342,26 @@ const loginResDeal = (loginRes: any) => {
 | 
				
			|||||||
    }, 400);
 | 
					    }, 400);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineExpose({
 | 
					 | 
				
			||||||
    loginResDeal,
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 登录成功后的跳转
 | 
					// 登录成功后的跳转
 | 
				
			||||||
const signInSuccess = async (accessToken: string = '') => {
 | 
					const signInSuccess = async (accessToken: string = '') => {
 | 
				
			||||||
 | 
					    if (!accessToken) {
 | 
				
			||||||
 | 
					        accessToken = getSession('token');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    // 存储 token 到浏览器缓存
 | 
					    // 存储 token 到浏览器缓存
 | 
				
			||||||
    setSession('token', accessToken);
 | 
					    setSession('token', accessToken);
 | 
				
			||||||
    // 初始化路由
 | 
					    // 初始化路由
 | 
				
			||||||
    await initRouter();
 | 
					    await initRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 判断是否为第一次oauth2登录,是的话需要用户填写姓名和用户名
 | 
				
			||||||
 | 
					    if (state.loginRes.isFirstOauth2Login) {
 | 
				
			||||||
 | 
					        state.baseInfoDialog.form.username = state.loginRes.username;
 | 
				
			||||||
 | 
					        state.baseInfoDialog.visible = true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        await toIndex();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const toIndex = async () => {
 | 
				
			||||||
    // 初始化登录成功时间问候语
 | 
					    // 初始化登录成功时间问候语
 | 
				
			||||||
    let currentTimeInfo = currentTime.value;
 | 
					    let currentTimeInfo = currentTime.value;
 | 
				
			||||||
    // 登录成功,跳到转首页
 | 
					    // 登录成功,跳到转首页
 | 
				
			||||||
@@ -356,6 +408,10 @@ const cancelChangePwd = () => {
 | 
				
			|||||||
    state.changePwdDialog.form.username = '';
 | 
					    state.changePwdDialog.form.username = '';
 | 
				
			||||||
    getCaptcha();
 | 
					    getCaptcha();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					defineExpose({
 | 
				
			||||||
 | 
					    loginResDeal,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped lang="scss">
 | 
					<style scoped lang="scss">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,19 +68,22 @@ onMounted(async () => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const oauth2Login = () => {
 | 
					const oauth2Login = () => {
 | 
				
			||||||
 | 
					    const width = 700;
 | 
				
			||||||
 | 
					    const height = 500;
 | 
				
			||||||
 | 
					    var iTop = (window.screen.height - 30 - height) / 2; //获得窗口的垂直位置;
 | 
				
			||||||
 | 
					    var iLeft = (window.screen.width - 10 - width) / 2; //获得窗口的水平位置;
 | 
				
			||||||
    // 小窗口打开oauth2鉴权
 | 
					    // 小窗口打开oauth2鉴权
 | 
				
			||||||
    let oauthWindoe = window.open(config.baseApiUrl + '/auth/oauth2/login', 'oauth2', 'width=600,height=600');
 | 
					    let oauthWindow = window.open(config.baseApiUrl + '/auth/oauth2/login', 'oauth2', `height=${height},width=${width},top=${iTop},left=${iLeft},location=no`);
 | 
				
			||||||
    if (oauthWindoe) {
 | 
					    if (oauthWindow) {
 | 
				
			||||||
        const handler = (e: any) => {
 | 
					        const handler = (e: any) => {
 | 
				
			||||||
            if (e.data.action === 'oauthLogin') {
 | 
					            if (e.data.action === 'oauthLogin') {
 | 
				
			||||||
                oauthWindoe!.close();
 | 
					 | 
				
			||||||
                window.removeEventListener('message', handler);
 | 
					                window.removeEventListener('message', handler);
 | 
				
			||||||
                loginForm.value!.loginResDeal(e.data);
 | 
					                loginForm.value!.loginResDeal(e.data);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        window.addEventListener('message', handler);
 | 
					        window.addEventListener('message', handler);
 | 
				
			||||||
        setInterval(() => {
 | 
					        setInterval(() => {
 | 
				
			||||||
            if (oauthWindoe!.closed) {
 | 
					            if (oauthWindow!.closed) {
 | 
				
			||||||
                window.removeEventListener('message', handler);
 | 
					                window.removeEventListener('message', handler);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }, 1000);
 | 
					        }, 1000);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								mayfly_go_web/src/views/oauth/Oauth2Callback.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								mayfly_go_web/src/views/oauth/Oauth2Callback.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <div></div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import { onMounted } from 'vue';
 | 
				
			||||||
 | 
					import { useRoute } from 'vue-router';
 | 
				
			||||||
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
 | 
					import openApi from '@/common/openApi';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const route = useRoute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onMounted(async () => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        const queryParam = route.query;
 | 
				
			||||||
 | 
					        // 使用hash路由,回调code可能会被设置到search
 | 
				
			||||||
 | 
					        // 如 localhost:8888/?code=xxxx/oauth2/callback,导致route.query获取不到值
 | 
				
			||||||
 | 
					        if (location.search) {
 | 
				
			||||||
 | 
					            const searchParams = location.search.split('?')[1];
 | 
				
			||||||
 | 
					            if (searchParams) {
 | 
				
			||||||
 | 
					                for (let searchParam of searchParams.split('&')) {
 | 
				
			||||||
 | 
					                    const searchParamSplit = searchParam.split('=');
 | 
				
			||||||
 | 
					                    queryParam[searchParamSplit[0]] = searchParamSplit[1];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const res: any = await openApi.oauth2Callback(queryParam);
 | 
				
			||||||
 | 
					        ElMessage.success('授权认证成功');
 | 
				
			||||||
 | 
					        top?.opener.postMessage(res);
 | 
				
			||||||
 | 
					        window.close();
 | 
				
			||||||
 | 
					    } catch (e: any) {
 | 
				
			||||||
 | 
					        setTimeout(() => {
 | 
				
			||||||
 | 
					            window.close();
 | 
				
			||||||
 | 
					        }, 1500);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<style lang="scss"></style>
 | 
				
			||||||
@@ -5,4 +5,5 @@ export const personApi = {
 | 
				
			|||||||
    updateAccount: Api.newPut('/sys/accounts/self'),
 | 
					    updateAccount: Api.newPut('/sys/accounts/self'),
 | 
				
			||||||
    authStatus: Api.newGet('/auth/oauth2/status'),
 | 
					    authStatus: Api.newGet('/auth/oauth2/status'),
 | 
				
			||||||
    getMsgs: Api.newGet('/msgs/self'),
 | 
					    getMsgs: Api.newGet('/msgs/self'),
 | 
				
			||||||
 | 
					    unbindOauth2: Api.newGet('/auth/oauth2/unbind'),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -136,7 +136,8 @@
 | 
				
			|||||||
                                    <div class="personal-edit-safe-item-left-value">当前状态:{{ authStatus.bind ? '已绑定' : '未绑定' }}</div>
 | 
					                                    <div class="personal-edit-safe-item-left-value">当前状态:{{ authStatus.bind ? '已绑定' : '未绑定' }}</div>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                                <div class="personal-edit-safe-item-right">
 | 
					                                <div class="personal-edit-safe-item-right">
 | 
				
			||||||
                                    <el-button link @click="bindOAuth2" :disabled="authStatus.bind" type="primary">立即绑定</el-button>
 | 
					                                    <el-button v-if="!authStatus.bind" link @click="bindOAuth2" type="primary">立即绑定</el-button>
 | 
				
			||||||
 | 
					                                    <el-button v-else link @click="unbindOAuth2()" type="warning">解绑</el-button>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
@@ -202,8 +203,8 @@ const state = reactive({
 | 
				
			|||||||
        password: '',
 | 
					        password: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    authStatus: {
 | 
					    authStatus: {
 | 
				
			||||||
        enable: { oauth2: false },
 | 
					        enable: false,
 | 
				
			||||||
        bind: { oauth2: false },
 | 
					        bind: false,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -241,12 +242,19 @@ const updateAccount = async () => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const bindOAuth2 = () => {
 | 
					const bindOAuth2 = () => {
 | 
				
			||||||
 | 
					    const width = 700;
 | 
				
			||||||
 | 
					    const height = 500;
 | 
				
			||||||
 | 
					    var iTop = (window.screen.height - 30 - height) / 2; //获得窗口的垂直位置;
 | 
				
			||||||
 | 
					    var iLeft = (window.screen.width - 10 - width) / 2; //获得窗口的水平位置;
 | 
				
			||||||
    // 小窗口打开oauth2鉴权
 | 
					    // 小窗口打开oauth2鉴权
 | 
				
			||||||
    let oauthWindow = window.open(config.baseApiUrl + '/auth/oauth2/bind?token=' + getSession('token'), 'oauth2', 'width=600,height=600');
 | 
					    let oauthWindow = window.open(
 | 
				
			||||||
 | 
					        config.baseApiUrl + '/auth/oauth2/bind?token=' + getSession('token'),
 | 
				
			||||||
 | 
					        'oauth2',
 | 
				
			||||||
 | 
					        `height=${height},width=${width},top=${iTop},left=${iLeft},location=no`
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
    if (oauthWindow) {
 | 
					    if (oauthWindow) {
 | 
				
			||||||
        const handler = (e: any) => {
 | 
					        const handler = (e: any) => {
 | 
				
			||||||
            if (e.data.action === 'oauthBind') {
 | 
					            if (e.data.action === 'oauthBind') {
 | 
				
			||||||
                oauthWindow!.close();
 | 
					 | 
				
			||||||
                window.removeEventListener('message', handler);
 | 
					                window.removeEventListener('message', handler);
 | 
				
			||||||
                // 处理登录token
 | 
					                // 处理登录token
 | 
				
			||||||
                ElMessage.success('绑定成功');
 | 
					                ElMessage.success('绑定成功');
 | 
				
			||||||
@@ -264,6 +272,12 @@ const bindOAuth2 = () => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const unbindOAuth2 = async () => {
 | 
				
			||||||
 | 
					    await personApi.unbindOauth2.request();
 | 
				
			||||||
 | 
					    ElMessage.success('解绑成功');
 | 
				
			||||||
 | 
					    state.authStatus = await personApi.authStatus.request();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getMsgs = async () => {
 | 
					const getMsgs = async () => {
 | 
				
			||||||
    const res = await personApi.getMsgs.request(state.msgDialog.query);
 | 
					    const res = await personApi.getMsgs.request(state.msgDialog.query);
 | 
				
			||||||
    state.msgDialog.msgs = res;
 | 
					    state.msgDialog.msgs = res;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,6 @@
 | 
				
			|||||||
package api
 | 
					package api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"mayfly-go/internal/auth/api/vo"
 | 
						"mayfly-go/internal/auth/api/vo"
 | 
				
			||||||
@@ -59,7 +58,7 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
 | 
				
			|||||||
	biz.NotEmpty(stateAction, "state已过期, 请重新登录")
 | 
						biz.NotEmpty(stateAction, "state已过期, 请重新登录")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	token, err := client.Exchange(rc.GinCtx, code)
 | 
						token, err := client.Exchange(rc.GinCtx, code)
 | 
				
			||||||
	biz.ErrIsNilAppendErr(err, "获取token失败: %s")
 | 
						biz.ErrIsNilAppendErr(err, "获取OAuth2 accessToken失败: %s")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 获取用户信息
 | 
						// 获取用户信息
 | 
				
			||||||
	httpCli := client.Client(rc.GinCtx.Request.Context(), token)
 | 
						httpCli := client.Client(rc.GinCtx.Request.Context(), token)
 | 
				
			||||||
@@ -104,7 +103,12 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
 | 
				
			|||||||
		err = a.Oauth2App.GetOAuthAccount(&entity.Oauth2Account{
 | 
							err = a.Oauth2App.GetOAuthAccount(&entity.Oauth2Account{
 | 
				
			||||||
			AccountId: accountId,
 | 
								AccountId: accountId,
 | 
				
			||||||
		}, "account_id", "identity")
 | 
							}, "account_id", "identity")
 | 
				
			||||||
		biz.IsTrue(err != nil, "该账号已被绑定")
 | 
							biz.IsTrue(err != nil, "该账号已被其他用户绑定")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = a.Oauth2App.GetOAuthAccount(&entity.Oauth2Account{
 | 
				
			||||||
 | 
								Identity: userId,
 | 
				
			||||||
 | 
							}, "account_id", "identity")
 | 
				
			||||||
 | 
							biz.IsTrue(err != nil, "您已绑定其他账号")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		now := time.Now()
 | 
							now := time.Now()
 | 
				
			||||||
		err = a.Oauth2App.BindOAuthAccount(&entity.Oauth2Account{
 | 
							err = a.Oauth2App.BindOAuthAccount(&entity.Oauth2Account{
 | 
				
			||||||
@@ -118,13 +122,7 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
 | 
				
			|||||||
			"action": "oauthBind",
 | 
								"action": "oauthBind",
 | 
				
			||||||
			"bind":   true,
 | 
								"bind":   true,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		b, err = json.Marshal(res)
 | 
							rc.ResData = res
 | 
				
			||||||
		biz.ErrIsNil(err, "数据序列化失败")
 | 
					 | 
				
			||||||
		rc.GinCtx.Header("Content-Type", "text/html; charset=utf-8")
 | 
					 | 
				
			||||||
		rc.GinCtx.Writer.WriteHeader(http.StatusOK)
 | 
					 | 
				
			||||||
		_, _ = rc.GinCtx.Writer.WriteString("<html>" +
 | 
					 | 
				
			||||||
			"<script>top.opener.postMessage(" + string(b) + ")</script>" +
 | 
					 | 
				
			||||||
			"</html>")
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		panic(biz.NewBizErr("state不合法"))
 | 
							panic(biz.NewBizErr("state不合法"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -132,14 +130,12 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 指定登录操作
 | 
					// 指定登录操作
 | 
				
			||||||
func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *sysentity.ConfigOauth2Login) {
 | 
					func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *sysentity.ConfigOauth2Login) {
 | 
				
			||||||
	clientIp := getIpAndRegion(rc)
 | 
					 | 
				
			||||||
	rc.ReqParam = fmt.Sprintf("oauth2 login username: %s | ip: %s", userId, clientIp)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 查询用户是否存在
 | 
						// 查询用户是否存在
 | 
				
			||||||
	oauthAccount := &entity.Oauth2Account{Identity: userId}
 | 
						oauthAccount := &entity.Oauth2Account{Identity: userId}
 | 
				
			||||||
	err := a.Oauth2App.GetOAuthAccount(oauthAccount, "account_id", "identity")
 | 
						err := a.Oauth2App.GetOAuthAccount(oauthAccount, "account_id", "identity")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var accountId uint64
 | 
						var accountId uint64
 | 
				
			||||||
 | 
						isFirst := false
 | 
				
			||||||
	// 不存在,进行注册
 | 
						// 不存在,进行注册
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		biz.IsTrue(oauth.AutoRegister, "系统未开启自动注册, 请先让管理员添加对应账号")
 | 
							biz.IsTrue(oauth.AutoRegister, "系统未开启自动注册, 请先让管理员添加对应账号")
 | 
				
			||||||
@@ -164,6 +160,7 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *sysentity
 | 
				
			|||||||
		})
 | 
							})
 | 
				
			||||||
		biz.ErrIsNilAppendErr(err, "绑定用户失败: %s")
 | 
							biz.ErrIsNilAppendErr(err, "绑定用户失败: %s")
 | 
				
			||||||
		accountId = account.Id
 | 
							accountId = account.Id
 | 
				
			||||||
 | 
							isFirst = true
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		accountId = oauthAccount.AccountId
 | 
							accountId = oauthAccount.AccountId
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -175,15 +172,13 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *sysentity
 | 
				
			|||||||
	err = a.AccountApp.GetAccount(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
 | 
						err = a.AccountApp.GetAccount(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
 | 
				
			||||||
	biz.ErrIsNilAppendErr(err, "获取用户信息失败: %s")
 | 
						biz.ErrIsNilAppendErr(err, "获取用户信息失败: %s")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clientIp := getIpAndRegion(rc)
 | 
				
			||||||
 | 
						rc.ReqParam = fmt.Sprintf("oauth2 login username: %s | ip: %s", account.Username, clientIp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res := LastLoginCheck(account, a.ConfigApp.GetConfig(sysentity.ConfigKeyAccountLoginSecurity).ToAccountLoginSecurity(), clientIp)
 | 
						res := LastLoginCheck(account, a.ConfigApp.GetConfig(sysentity.ConfigKeyAccountLoginSecurity).ToAccountLoginSecurity(), clientIp)
 | 
				
			||||||
	res["action"] = "oauthLogin"
 | 
						res["action"] = "oauthLogin"
 | 
				
			||||||
	b, err := json.Marshal(res)
 | 
						res["isFirstOauth2Login"] = isFirst
 | 
				
			||||||
	biz.ErrIsNil(err, "数据序列化失败")
 | 
						rc.ResData = res
 | 
				
			||||||
	rc.GinCtx.Header("Content-Type", "text/html; charset=utf-8")
 | 
					 | 
				
			||||||
	rc.GinCtx.Writer.WriteHeader(http.StatusOK)
 | 
					 | 
				
			||||||
	_, _ = rc.GinCtx.Writer.WriteString("<html>" +
 | 
					 | 
				
			||||||
		"<script>top.opener.postMessage(" + string(b) + ")</script>" +
 | 
					 | 
				
			||||||
		"</html>")
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *Oauth2Login) getOAuthClient() (*oauth2.Config, *sysentity.ConfigOauth2Login) {
 | 
					func (a *Oauth2Login) getOAuthClient() (*oauth2.Config, *sysentity.ConfigOauth2Login) {
 | 
				
			||||||
@@ -198,7 +193,7 @@ func (a *Oauth2Login) getOAuthClient() (*oauth2.Config, *sysentity.ConfigOauth2L
 | 
				
			|||||||
			AuthURL:  oath2LoginConfig.AuthorizationURL,
 | 
								AuthURL:  oath2LoginConfig.AuthorizationURL,
 | 
				
			||||||
			TokenURL: oath2LoginConfig.AccessTokenURL,
 | 
								TokenURL: oath2LoginConfig.AccessTokenURL,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		RedirectURL: oath2LoginConfig.RedirectURL + "/api/auth/oauth2/callback",
 | 
							RedirectURL: oath2LoginConfig.RedirectURL + "/#/oauth2/callback",
 | 
				
			||||||
		Scopes:      strings.Split(oath2LoginConfig.Scopes, ","),
 | 
							Scopes:      strings.Split(oath2LoginConfig.Scopes, ","),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return client, oath2LoginConfig
 | 
						return client, oath2LoginConfig
 | 
				
			||||||
@@ -217,3 +212,7 @@ func (a *Oauth2Login) Oauth2Status(ctx *req.Ctx) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ctx.ResData = res
 | 
						ctx.ResData = res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *Oauth2Login) Oauth2Unbind(rc *req.Ctx) {
 | 
				
			||||||
 | 
						a.Oauth2App.Unbind(rc.LoginAccount.Id)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,8 @@ type Oauth2 interface {
 | 
				
			|||||||
	GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error
 | 
						GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BindOAuthAccount(e *entity.Oauth2Account) error
 | 
						BindOAuthAccount(e *entity.Oauth2Account) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Unbind(accountId uint64)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newAuthApp(oauthAccountRepo repository.Oauth2Account) Oauth2 {
 | 
					func newAuthApp(oauthAccountRepo repository.Oauth2Account) Oauth2 {
 | 
				
			||||||
@@ -36,3 +38,7 @@ func (a *oauth2AppImpl) GetOAuthAccount(condition *entity.Oauth2Account, cols ..
 | 
				
			|||||||
func (a *oauth2AppImpl) BindOAuthAccount(e *entity.Oauth2Account) error {
 | 
					func (a *oauth2AppImpl) BindOAuthAccount(e *entity.Oauth2Account) error {
 | 
				
			||||||
	return a.oauthAccountRepo.SaveOAuthAccount(e)
 | 
						return a.oauthAccountRepo.SaveOAuthAccount(e)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *oauth2AppImpl) Unbind(accountId uint64) {
 | 
				
			||||||
 | 
						a.oauthAccountRepo.DeleteBy(&entity.Oauth2Account{AccountId: accountId})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,4 +7,6 @@ type Oauth2Account interface {
 | 
				
			|||||||
	GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error
 | 
						GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SaveOAuthAccount(e *entity.Oauth2Account) error
 | 
						SaveOAuthAccount(e *entity.Oauth2Account) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DeleteBy(e *entity.Oauth2Account)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,3 +22,7 @@ func (a *oauth2AccountRepoImpl) SaveOAuthAccount(e *entity.Oauth2Account) error
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return gormx.UpdateById(e)
 | 
						return gormx.UpdateById(e)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *oauth2AccountRepoImpl) DeleteBy(e *entity.Oauth2Account) {
 | 
				
			||||||
 | 
						gormx.DeleteByCondition(e)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,9 +45,11 @@ func Init(router *gin.RouterGroup) {
 | 
				
			|||||||
		req.NewGet("/oauth2/bind", oauth2Login.OAuth2Bind),
 | 
							req.NewGet("/oauth2/bind", oauth2Login.OAuth2Bind),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// oauth2回调地址
 | 
							// oauth2回调地址
 | 
				
			||||||
		req.NewGet("/oauth2/callback", oauth2Login.OAuth2Callback).Log(req.NewLogSave("oauth2回调")).NoRes().DontNeedToken(),
 | 
							req.NewGet("/oauth2/callback", oauth2Login.OAuth2Callback).Log(req.NewLogSave("oauth2回调")).DontNeedToken(),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewGet("/oauth2/status", oauth2Login.Oauth2Status),
 | 
							req.NewGet("/oauth2/status", oauth2Login.Oauth2Status),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req.NewGet("/oauth2/unbind", oauth2Login.Oauth2Unbind).Log(req.NewLogSave("oauth2解绑")),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req.BatchSetGroup(rg, reqs[:])
 | 
						req.BatchSetGroup(rg, reqs[:])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,6 +105,13 @@ func (a *Account) UpdateAccount(rc *req.Ctx) {
 | 
				
			|||||||
		biz.IsTrue(utils.CheckAccountPasswordLever(updateAccount.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
 | 
							biz.IsTrue(utils.CheckAccountPasswordLever(updateAccount.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
 | 
				
			||||||
		updateAccount.Password = cryptox.PwdHash(updateAccount.Password)
 | 
							updateAccount.Password = cryptox.PwdHash(updateAccount.Password)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oldAcc := a.AccountApp.GetById(updateAccount.Id)
 | 
				
			||||||
 | 
						// 账号创建十分钟内允许修改用户名(兼容oauth2首次登录修改用户名),否则不允许修改
 | 
				
			||||||
 | 
						if oldAcc.CreateTime.Add(10 * time.Minute).Before(time.Now()) {
 | 
				
			||||||
 | 
							// 禁止更新用户名,防止误传被更新
 | 
				
			||||||
 | 
							updateAccount.Username = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	a.AccountApp.Update(updateAccount)
 | 
						a.AccountApp.Update(updateAccount)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,6 +140,8 @@ func (a *Account) SaveAccount(rc *req.Ctx) {
 | 
				
			|||||||
			biz.IsTrue(utils.CheckAccountPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
 | 
								biz.IsTrue(utils.CheckAccountPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
 | 
				
			||||||
			account.Password = cryptox.PwdHash(account.Password)
 | 
								account.Password = cryptox.PwdHash(account.Password)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// 更新操作不允许修改用户名、防止误传更新
 | 
				
			||||||
 | 
							account.Username = ""
 | 
				
			||||||
		a.AccountApp.Update(account)
 | 
							a.AccountApp.Update(account)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,9 @@ type AccountCreateForm struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AccountUpdateForm struct {
 | 
					type AccountUpdateForm struct {
 | 
				
			||||||
	Password *string `json:"password" binding:"min=6,max=16"`
 | 
						Name     string  `json:"name" binding:"max=16"` // 姓名
 | 
				
			||||||
 | 
						Username string  `json:"username" binding:"max=20"`
 | 
				
			||||||
 | 
						Password *string `json:"password"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AccountChangePasswordForm struct {
 | 
					type AccountChangePasswordForm struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,8 @@ import (
 | 
				
			|||||||
type Account interface {
 | 
					type Account interface {
 | 
				
			||||||
	GetAccount(condition *entity.Account, cols ...string) error
 | 
						GetAccount(condition *entity.Account, cols ...string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetById(id uint64) *entity.Account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
						GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Create(account *entity.Account)
 | 
						Create(account *entity.Account)
 | 
				
			||||||
@@ -38,6 +40,10 @@ func (a *accountAppImpl) GetAccount(condition *entity.Account, cols ...string) e
 | 
				
			|||||||
	return a.accountRepo.GetAccount(condition, cols...)
 | 
						return a.accountRepo.GetAccount(condition, cols...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *accountAppImpl) GetById(id uint64) *entity.Account {
 | 
				
			||||||
 | 
						return a.accountRepo.GetById(id)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
					func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
				
			||||||
	return a.accountRepo.GetPageList(condition, pageParam, toEntity)
 | 
						return a.accountRepo.GetPageList(condition, pageParam, toEntity)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -51,8 +57,12 @@ func (a *accountAppImpl) Create(account *entity.Account) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *accountAppImpl) Update(account *entity.Account) {
 | 
					func (a *accountAppImpl) Update(account *entity.Account) {
 | 
				
			||||||
	// 禁止更新用户名,防止误传被更新
 | 
						if account.Username != "" {
 | 
				
			||||||
	account.Username = ""
 | 
							unAcc := &entity.Account{Username: account.Username}
 | 
				
			||||||
 | 
							err := a.GetAccount(unAcc)
 | 
				
			||||||
 | 
							biz.IsTrue(err != nil || unAcc.Id == account.Id, "该用户名已存在")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	a.accountRepo.Update(account)
 | 
						a.accountRepo.Update(account)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@ type Account interface {
 | 
				
			|||||||
	// 根据条件获取账号信息
 | 
						// 根据条件获取账号信息
 | 
				
			||||||
	GetAccount(condition *entity.Account, cols ...string) error
 | 
						GetAccount(condition *entity.Account, cols ...string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetById(id uint64) *entity.Account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
						GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Insert(account *entity.Account)
 | 
						Insert(account *entity.Account)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,14 @@ func (a *accountRepoImpl) GetAccount(condition *entity.Account, cols ...string)
 | 
				
			|||||||
	return gormx.GetBy(condition, cols...)
 | 
						return gormx.GetBy(condition, cols...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *accountRepoImpl) GetById(id uint64) *entity.Account {
 | 
				
			||||||
 | 
						ac := new(entity.Account)
 | 
				
			||||||
 | 
						if err := gormx.GetById(ac, id); err != nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ac
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *accountRepoImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
					func (m *accountRepoImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
				
			||||||
	qd := gormx.NewQuery(new(entity.Account)).
 | 
						qd := gormx.NewQuery(new(entity.Account)).
 | 
				
			||||||
		Like("name", condition.Name).
 | 
							Like("name", condition.Name).
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user