From 197e3949af92e687e9e06bd2daf539b6b665d06d Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期五, 21 三月 2025 18:17:52 +0800 Subject: [PATCH] 微信绑定 --- src/layout/navBars/breadcrumb/user.vue | 4 src/api/login/UserMenuData.ts | 17 + src/hooks/useLogin.ts | 3 src/views/project/yw/systemManage/personalCenter/PersonalCenter.vue | 425 +++++++++++++++++++++++++++++++++++++++++++++++ src/utils/global.ts | 31 ++ customer_list/yw/static/config/route.js | 7 6 files changed, 477 insertions(+), 10 deletions(-) diff --git a/customer_list/yw/static/config/route.js b/customer_list/yw/static/config/route.js index 94d0bee..a4d411d 100644 --- a/customer_list/yw/static/config/route.js +++ b/customer_list/yw/static/config/route.js @@ -106,6 +106,13 @@ component: '/project/yw/systemManage/replaceWordMgr/ReplaceWordMgr.vue', }, { + name: 'PersonalCenter', + isKeepAlive: true, + isAffix: false, + path: '/personalCenter', + component: '/project/yw/systemManage/personalCenter/PersonalCenter.vue', + }, + { name: 'AmisEditor', isKeepAlive: true, isAffix: false, diff --git a/src/api/login/UserMenuData.ts b/src/api/login/UserMenuData.ts index 8bf6283..cb9d4ad 100644 --- a/src/api/login/UserMenuData.ts +++ b/src/api/login/UserMenuData.ts @@ -456,6 +456,23 @@ SortCode: 2, Description: '', }, + + { + Children: [], + ID: '1135', + ParentID: '3', + Type: 2, + Name: '涓汉涓績', + Path: '/personalCenter', + Permission: '', + Icon: 'ywifont ywicon-wode', + IsIframe: false, + OutLink: '', + IsHide: true, + Weight: 0, + SortCode: 2, + Description: '', + }, { Children: [], ID: '333-2', diff --git a/src/hooks/useLogin.ts b/src/hooks/useLogin.ts index d57cc72..6c8d6b2 100644 --- a/src/hooks/useLogin.ts +++ b/src/hooks/useLogin.ts @@ -69,8 +69,7 @@ const currentTime = formatAxis(new Date()); Local.set(accessSessionKey, res.hswatersession); await useUserInfo().setUserInfos({ - userName: res.name, - phoneNumber: res.phone, + ...(res ?? {}), photo: profileMan, }); //缂撳瓨鐢ㄦ埛淇℃伅 // state.loading.signIn = true; diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue index 9e8a684..59486cc 100644 --- a/src/layout/navBars/breadcrumb/user.vue +++ b/src/layout/navBars/breadcrumb/user.vue @@ -63,7 +63,7 @@ <el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick"> <span class="layout-navbars-breadcrumb-user-link"> <img :src="userInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" /> - {{ userInfos.userName === '' ? 'common' : userInfos.userName }} + {{ userInfos.name === '' ? 'common' : userInfos.name }} <el-icon class="el-icon--right"> <ele-ArrowDown /> </el-icon> @@ -75,7 +75,7 @@ <el-dropdown-item command="/404">{{ $t('message.user.dropdown3') }}</el-dropdown-item> <el-dropdown-item command="/401">{{ $t('message.user.dropdown4') }}</el-dropdown-item> --> - <!-- <el-dropdown-item command="/auth/personalCenter">{{ $t('message.user.dropdown2') }}</el-dropdown-item> --> + <el-dropdown-item command="/personalCenter">{{ $t('message.user.dropdown2') }}</el-dropdown-item> <el-dropdown-item divided command="logOut">{{ $t('message.user.dropdown5') }}</el-dropdown-item> </el-dropdown-menu> </template> diff --git a/src/utils/global.ts b/src/utils/global.ts index 25df7e1..2c15dff 100644 --- a/src/utils/global.ts +++ b/src/utils/global.ts @@ -56,7 +56,7 @@ value: res?.json_msg ?? '鐧诲綍澶辫触锛岃妫�鏌ユ槸鍚﹀凡缁戝畾寰俊', }); - window.location.href = SERVE_URL; + // window.location.href = SERVE_URL; } }; @@ -65,23 +65,42 @@ const res = await userBindingWechat({ weixin_code: wxcode, - user_name: userInfo.userName, + user_name: userInfo.name, }); + + const reloadPage = () => { + const url = window.location.href; + const [baseUrl, hash] = url.split('#/'); + const [path, search] = hash.split('?'); + + if (search) { + const searchParams = new URLSearchParams(search); + searchParams.delete('isWxLogin'); + searchParams.delete('wxcode'); + searchParams.delete('wxstate'); + + const newSearch = searchParams.toString(); + const newUrl = `${baseUrl}#/${path}${newSearch ? '?' + newSearch : ''}`; + window.history.replaceState({}, '', newUrl); + window.location.reload(); + } + }; if (res?.json_ok) { ElMessage.success('缁戝畾鎴愬姛'); const userInfo = Local.get(userInfoKey); Local.set(userInfoKey, { ...userInfo, - isBindWechat: true, - wechatNickname: res.json_url, + /** @description 闅忎究璁剧疆涓�涓�硷紝琛ㄧず宸茬粡缁戝畾浜� */ + weixin_openid: 'sdfdf', + weixin_nickname: res.json_url, }); setTimeout(() => { - window.location.href = SERVE_URL; + reloadPage(); }, 700); } else { ElMessage.error(res?.json_msg ?? '缁戝畾澶辫触'); setTimeout(() => { - window.location.href = SERVE_URL; + reloadPage(); }, 2000); } }; diff --git a/src/views/project/yw/systemManage/personalCenter/PersonalCenter.vue b/src/views/project/yw/systemManage/personalCenter/PersonalCenter.vue new file mode 100644 index 0000000..57c0b4c --- /dev/null +++ b/src/views/project/yw/systemManage/personalCenter/PersonalCenter.vue @@ -0,0 +1,425 @@ +<template> + <div class="sys-userCenter-container h100"> + <el-row :gutter="8" style="width: 100%" class="h100"> + <el-col :span="8" :xs="24" class="h100"> + <el-card shadow="hover" class="h100"> + <div class="account-center-avatarHolder"> + <el-avatar + :size="100" + :src="userInfos.photo" + @click="openCropperDialog" + v-loading="state.avatarLoading" + element-loading-spinner="el-icon-Upload" + element-loading-background="rgba(0, 0, 0, 0.2)" + @mouseenter="mouseEnterAvatar" + @mouseleave="mouseLeaveAvatar" + /> + <div class="username">{{ userInfos.realName }}</div> + </div> + <div class="account-center-org" style="display: flex; flex-direction: column; align-items: center"> + <div> + <p class="user-simple-info"> + <!-- 鐢ㄦ埛鍚� --> + <el-icon size="17" class="mr10"><ele-User /></el-icon> <span>{{ userInfos?.name ?? '---' }}</span> + </p> + <!-- 鍏徃鍚� --> + <!-- <p class="user-simple-info"> + <el-icon size="17"><ele-Briefcase /></el-icon> <span>{{ userInfos.SoftWare?.Project?.Corpration?.Name ?? '---' }}</span> + </p> --> + <p class="user-simple-info" v-if="userInfos?.weixin_nikename"> + <!-- 璐︽埛绫诲瀷鍚� --> + <span class="ywifont ywicon-weixin mr10"></span> + <span>{{ userInfos?.weixin_nikename ?? '---' }}</span> + </p> + </div> + </div> + </el-card> + </el-col> + + <el-col :span="16" :xs="24" class="h100" v-loading="state.loading"> + <el-card shadow="hover" class="h100"> + <el-tabs> + <el-tab-pane label="鍩虹淇℃伅"> + <el-form :model="state.ruleFormBase" ref="ruleFormBaseRef" label-width="80px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="鐢ㄦ埛ID"> + <el-input :model-value="userInfos?.name" placeholder="鐢ㄦ埛ID" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="濮撳悕"> + <el-input :model-value="userInfos?.real_name" placeholder="濮撳悕" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="鎬у埆"> + <el-input :model-value="userInfos?.sex" placeholder="鎬у埆" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="閮ㄩ棬"> + <el-input :model-value="userInfos?.part" placeholder="閮ㄩ棬" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="鐢佃瘽"> + <el-input :model-value="userInfos?.phone" placeholder="鐢佃瘽" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="閭"> + <el-input :model-value="userInfos?.email" placeholder="閭" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="寰俊鏄电О"> + <el-input :model-value="userInfos?.weixin_nikename" placeholder="寰俊鏄电О" /> + </el-form-item> + </el-col> + + + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="寰俊缁戝畾" prop="wechat"> + <div id="wechat-bind"> + <div v-if="bindingCodeShow" class="flex flex-col items-center justify-center"> + <iframe + ref="wechatQrRef" + sandbox="allow-top-navigation allow-scripts" + style="width: 200px; height: 170px; overflow: hidden" + frameborder="0" + ></iframe> + <span>浣跨敤寰俊鎵竴鎵粦瀹�</span> + </div> + <template v-else> + <div v-if="userInformationInfo.weixin_openid" class="flex items-center"> + <span>宸茬粦瀹�</span> + <el-button link type="primary" @click="openWechatLogin">閲嶆柊缁戝畾</el-button> + </div> + <div v-else class="flex items-center"> + <span>鏈粦瀹�</span> + <el-button link type="primary" @click="openWechatLogin">鐐瑰嚮缁戝畾</el-button> + </div> + </template> + </div> + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-tab-pane> + + <el-tab-pane label="淇敼瀵嗙爜"> + <el-form ref="ruleFormPasswordRef" :model="state.ruleFormPassword" label-width="80px"> + <el-form-item + label="鏂板瘑鐮�" + prop="passwordNew" + :rules="[{ required: true, message: '鏂板瘑鐮佷笉鑳戒负绌�', trigger: 'blur' }]" + > + <el-input + v-model="state.ruleFormPassword.passwordNew" + :type="state.showPasswdNew ? 'text' : 'password'" + autocomplete="off" + > + <template #suffix> + <i + class="iconfont el-input__icon login-content-password" + :class="state.showPasswdNew ? 'icon-yincangmima' : 'icon-xianshimima'" + @click="state.showPasswdNew = !state.showPasswdNew" + > + </i> + </template> + </el-input> + </el-form-item> + <el-form-item + label="纭瀵嗙爜" + prop="passwordNew2" + :rules="[{ validator: validatePassword, required: true, trigger: 'blur' }]" + > + <el-input :type="state.showPassWdNew2 ? 'text' : 'password'" v-model="state.passwordNew2" autocomplete="off"> + <template #suffix> + <i + class="iconfont el-input__icon login-content-password" + :class="state.showPassWdNew2 ? 'icon-yincangmima' : 'icon-xianshimima'" + @click="state.showPassWdNew2 = !state.showPassWdNew2" + > + </i> + </template> + </el-input> + </el-form-item> + <el-form-item> + <el-button icon="ele-Refresh" @click="resetPassword">閲� 缃�</el-button> + <el-button icon="ele-SuccessFilled" type="primary" @click="submitPassword">纭� 瀹�</el-button> + </el-form-item> + </el-form> + </el-tab-pane> + </el-tabs> + </el-card> + </el-col> + </el-row> + </div> +</template> + +<script lang="ts" setup name="sysUserCenter"> +import { onMounted, watch, reactive, ref, nextTick } from 'vue'; +import { storeToRefs } from 'pinia'; +import { ElForm, ElMessage, ElMessageBox, genFileId } from 'element-plus'; +import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'; +import { useUserInfo } from '/@/stores/userInfo'; +// import { base64ToFile } from '/@/utils/base64Conver'; +// import CropperDialog from '/@/components/cropper/index.vue'; +import { ADMIN_TYPE_MAP } from '/@/views/types'; +import { clearAccessTokens, userInfoKey } from '/@/utils/request'; +import { ResetSystemLoginPwd, UpdateSystemLoginPwd } from '/@/api/auth/userManage'; +import { SERVE_URL } from '/@/constants'; +import { Local } from '/@/utils/storage'; + +const stores = useUserInfo(); +const { userInfos } = storeToRefs(stores); +const uploadSignRef = ref<UploadInstance>(); +//const uploadAvatarRef = ref<UploadInstance>(); +const ruleFormBaseRef = ref<InstanceType<typeof ElForm>>(); +const ruleFormPasswordRef = ref<InstanceType<typeof ElForm>>(); +const state = reactive({ + loading: false, + avatarLoading: false, + signDialogVisible: false, + ruleFormBase: {}, + ruleFormPassword: {} as any, + showPasswdNew: false, + showPassWdNew2: false, + + signFileList: [] as any, + passwordNew2: '', + cropperTitle: '', +}); +const userInformationInfo = ref({}) as any; + +onMounted(async () => { + state.loading = true; + userInformationInfo.value = Local.get(userInfoKey); + + // var res = await getAPI(SysUserApi).apiSysUserBaseInfoGet(); + // state.ruleFormBase = res.data.result ?? { account: '' }; + state.loading = false; +}); + +// 涓婁紶澶村儚鍥剧墖 +const uploadCropperImg = async (e: any) => { + // var res = await getAPI(SysFileApi).apiSysFileUploadAvatarPostForm(e.img); + // userInfos.value.avatar = res.data.result?.filePath + '/' + res.data.result?.name; +}; + +// 鑾峰緱鐢靛瓙绛惧悕鏂囦欢鍒楄〃 +const handleChangeSignFile = (_file: any, fileList: []) => { + state.signFileList = fileList; +}; + +// 瀵嗙爜楠岃瘉 +const validatePassword = (_rule: any, value: any, callback: any) => { + if (!state.ruleFormPassword.passwordNew) { + callback('璇峰厛杈撳叆鏂板瘑鐮侊紒'); + } else if (state.passwordNew2 != state.ruleFormPassword.passwordNew) { + callback(new Error('涓ゆ瀵嗙爜涓嶄竴鑷达紒')); + } else { + callback(); + } +}; + +// 瀵嗙爜閲嶇疆 +const resetPassword = () => { + ElMessageBox.confirm('纭畾閲嶇疆褰撳墠鐢ㄦ埛瀵嗙爜锛�', '鎻愮ず', { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: 'warning', + }) + .then(async () => { + resetSystemLoginPwd(); + }) + .catch(() => {}); +}; + +const confirmReLogin = () => { + // 閫�鍑虹郴缁� + ElMessageBox.confirm('瀵嗙爜宸蹭慨鏀癸紝鏄惁閲嶆柊鐧诲綍绯荤粺锛�', '鎻愮ず', { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: 'warning', + }) + .then(async () => { + clearAccessTokens(); + }) + .catch(() => {}); +}; + +const resetSystemLoginPwd = async () => { + const res = await ResetSystemLoginPwd({ + ID: userInfos.value?.User?.LoginAccount?.ID, + }); + + if (res?.Code === 0) { + if (res.Data) { + confirmReLogin(); + } else { + ElMessage.error('閲嶇疆瀵嗙爜澶辫触'); + } + } else { + ElMessage.error('閲嶇疆瀵嗙爜澶辫触' + (res?.Message ? `锛�${JSON.stringify(res.Message)}` : '')); + } +}; + +// 瀵嗙爜鎻愪氦 +const submitPassword = () => { + ruleFormPasswordRef.value?.validate(async (valid: boolean) => { + if (!valid) return; + ElMessageBox.confirm('纭畾淇敼褰撳墠璐︽埛瀵嗙爜锛�', '鎻愮ず', { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: 'warning', + }) + .then(async () => { + const res = await UpdateSystemLoginPwd({ + ID: userInfos.value?.User?.LoginAccount?.ID, + LoginPwd: state.passwordNew2, + }); + + if (res?.Code === 0) { + if (res.Data) { + confirmReLogin(); + } else { + ElMessage.error('淇敼瀵嗙爜澶辫触'); + } + } else { + ElMessage.error('淇敼瀵嗙爜澶辫触' + (res?.Message ? `锛�${JSON.stringify(res.Message)}` : '')); + } + }) + .catch(() => {}); + }); +}; + + + + + +const bindingCodeShow = ref(false); +const wechatQrRef = ref<HTMLIFrameElement>(); + +const openWechatLogin = async () => { + bindingCodeShow.value = true; + await nextTick(); + if (!wechatQrRef.value) return; + const url = `${SERVE_URL}JJJHHH/home?isWxLogin=N`; + const appid = 'wx4ea2dca37170074c'; + const state = (new Date().getTime() / 1000).toString(); + const base64 = btoa(` + .impowerBox .title {display:none;} + + .impowerBox .status.status_browser p:nth-of-type(2){ + display: none; + } + + .impowerBox .qrcode { + width: 160px; + margin-top:0; + + } + + .info{ + display: none; + } + .impowerBox .status{ + } + #tpl_for_iframe{ + height:100%; + overflow: hidden; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + `); + const wechatAuthUrl = `https://open.weixin.qq.com/connect/qrconnect?appid=${appid}&redirect_uri=${encodeURIComponent( + `http://apiv3.xpump.net/User/wxUserLoginCB.html?from=wi&url=${url}` + )}&response_type=code&scope=snsapi_login&state=${state}&href=data:text/css;base64,${base64}#wechat_redirect`; + wechatQrRef.value.src = wechatAuthUrl; +}; + +// 鎵撳紑瑁佸壀寮圭獥 +const openCropperDialog = () => { + // state.cropperTitle = '鏇存崲澶村儚'; + // cropperDialogRef.value?.openDialog(userInfos.value.avatar); +}; + +// 榧犳爣杩涘叆鍜岀寮�澶村儚鏃� +const mouseEnterAvatar = () => { + state.avatarLoading = true; +}; + +const mouseLeaveAvatar = () => { + state.avatarLoading = false; +}; + +// 瀵煎嚭瀵硅薄 +defineExpose({ handleChangeSignFile }); +</script> + +<style lang="scss" scoped> +.login-content-password { + display: inline-block; + width: 20px; + cursor: pointer; + + &:hover { + color: #909399; + } +} +.user-simple-info { + display: flex; + align-items: flex-start; +} +.account-center-avatarHolder { + text-align: center; + margin-bottom: 24px; + + .username { + font-size: 20px; + line-height: 28px; + font-weight: 500; + margin-bottom: 4px; + } +} +.account-center-org { + margin-bottom: 8px; + position: relative; + p { + margin-top: 10px; + } + span { + // padding-left: 17px; + } +} +.avatar { + margin: 0 auto; + width: 104px; + height: 104px; + margin-bottom: 20px; + border-radius: 50%; + overflow: hidden; + img { + height: 100%; + width: 100%; + } +} + +.image-signature { + margin-top: 20px; + margin-bottom: 10px; + width: 100%; + height: 150px; + background-color: #fff; + text-align: center; + vertical-align: middle; + border: solid 1px var(--el-border-color); +} +</style> -- Gitblit v1.9.3