feat: R1 重构对称迁移 + 升级依赖 + 配置文件分离
- 命名重构:tenant → customer(对齐后端 R1 重构) - Tenant → Customer / tenant_id → customerId - tenantStore → customerStore / getTenant/setTenant → getCustomer/setCustomer - cookie key tenant → customer, HTTP header tenantId → customerId - 后端契约更新:AuthResponse 加 sub 字段 - 接口 URL 修复:/auth/oidc/callback → /api/v1/auth/oidc/callback - 依赖升级:vue 3.5 / element-plus 2.8 / vite 5 / typescript 5.6 / sass 1.79 - 删 node-sass / scss / sass-loader / moment / mock/index.ts - 配置文件拆分:.env.development / .env.production / .env.example - 删除冗余 view/auth/auth/callback.vue 副本 - .gitignore 增加 dist / .opencode / tmp - 新增 AGENT.md 与后端风格对齐
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<span class="headerAvatar">
|
||||
<template v-if="picType === 'avatar'">
|
||||
<el-avatar v-if="useTenantStore.tenant.headerImg" :size="30" :src="avatar" />
|
||||
<el-avatar v-if="useCustomerStore.customer.headerImg" :size="30" :src="avatar" />
|
||||
<el-avatar v-else :size="30" :src="noAvatar" />
|
||||
</template>
|
||||
<template v-if="picType === 'img'">
|
||||
<img v-if="useTenantStore.tenant.headerImg" :src="avatar" class="avatar">
|
||||
<img v-if="useCustomerStore.customer.headerImg" :src="avatar" class="avatar">
|
||||
<img v-else :src="noAvatar" class="avatar">
|
||||
</template>
|
||||
<template v-if="picType === 'file'">
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { tenantStore } from '@/store/modules/tenant'
|
||||
import { customerStore } from '@/store/modules/customer'
|
||||
import noAvatarPng from '@/assets/nobody.jpg'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -33,13 +33,13 @@ const props = defineProps({
|
||||
})
|
||||
const path = ref(import.meta.env.VITE_BASE_API + '/')
|
||||
const noAvatar = ref(noAvatarPng)
|
||||
const useTenantStore = tenantStore()
|
||||
const useCustomerStore = customerStore()
|
||||
const avatar = computed(() => {
|
||||
if (props.picSrc === '') {
|
||||
if (useTenantStore.tenant.headerImg !== '' && useTenantStore.tenant.headerImg.slice(0, 4) === 'http') {
|
||||
return useTenantStore.tenant.headerImg
|
||||
if (useCustomerStore.customer.headerImg !== '' && useCustomerStore.customer.headerImg.slice(0, 4) === 'http') {
|
||||
return useCustomerStore.customer.headerImg
|
||||
}
|
||||
return path.value + useTenantStore.tenant.headerImg
|
||||
return path.value + useCustomerStore.customer.headerImg
|
||||
} else {
|
||||
if (props.picSrc !== '' && props.picSrc.slice(0, 4) === 'http') {
|
||||
return props.picSrc
|
||||
@@ -61,7 +61,6 @@ const file = computed(() => {
|
||||
align-items: center;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.file {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<span class="header-avatar" style="cursor: pointer">
|
||||
<CustomPic />
|
||||
<span v-show="!useSettingsStore.isMobile" style="margin-left: 5px">{{
|
||||
useTenantStore.tenant.account
|
||||
useCustomerStore.customer.account
|
||||
}}</span>
|
||||
<el-icon>
|
||||
<arrow-down />
|
||||
@@ -67,10 +67,10 @@
|
||||
<el-dropdown-menu class="dropdown-group">
|
||||
<el-dropdown-item>
|
||||
<span style="font-weight: 600;">
|
||||
当前角色:{{ useTenantStore.tenant.account }}
|
||||
当前角色:{{ useCustomerStore.customer.account }}
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<template v-if="useTenantStore.tenant.account">
|
||||
<template v-if="useCustomerStore.customer.account">
|
||||
<!-- <el-dropdown-item v-for="item in userStore.userInfo.authorities.filter(i=>i.authorityId!==userStore.userInfo.authorityId)" :key="item.authorityId" @click="changeUserAuth(item.authorityId)">
|
||||
<span>
|
||||
切换为:{{ item.authorityName }}
|
||||
@@ -78,7 +78,7 @@
|
||||
</el-dropdown-item> -->
|
||||
</template>
|
||||
<el-dropdown-item icon="avatar" @click="toPerson">个人信息</el-dropdown-item>
|
||||
<el-dropdown-item icon="reading-lamp" @click="useTenantStore.logout">登 出</el-dropdown-item>
|
||||
<el-dropdown-item icon="reading-lamp" @click="useCustomerStore.logout">登 出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
@@ -89,13 +89,13 @@
|
||||
|
||||
<script setup lang='ts'>
|
||||
import CustomPic from "@/components/customPic/index.vue";
|
||||
import { tenantStore } from '@/store/modules/tenant'
|
||||
import { customerStore } from '@/store/modules/customer'
|
||||
import { settingsStore } from '@/store/modules/settings'
|
||||
import { Message } from "@element-plus/icons-vue"
|
||||
import { reactive, ref } from "vue";
|
||||
|
||||
// -- IMPORT --
|
||||
const useTenantStore = tenantStore()
|
||||
const useCustomerStore = customerStore()
|
||||
const useSettingsStore = settingsStore()
|
||||
|
||||
// -- REACTIVE OBJECT --
|
||||
@@ -131,7 +131,7 @@ const toPerson = () => {
|
||||
}
|
||||
|
||||
|
||||
useTenantStore.reflush()
|
||||
useCustomerStore.reflush()
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,17 +4,13 @@
|
||||
</div>
|
||||
<el-card class="box-card">
|
||||
|
||||
<el-form ref="ruleFormRef" :model="loginForm" :rules="loginRules" status-icon label-width="120px"
|
||||
class="demo-ruleForm">
|
||||
<el-form>
|
||||
<div class="title-container">
|
||||
<h3>秘密基地</h3>
|
||||
</div>
|
||||
<div>
|
||||
<el-avatar :size="28" :src="baiduCloudImage" @click="scan(qrcode)" />
|
||||
<el-button type="primary" size="large" @click="handleOidcLogin">统一登录</el-button>
|
||||
</div>
|
||||
<el-form-item>
|
||||
其他登录方式暂时还没有哦
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
------------------------------------------------------------
|
||||
<div>
|
||||
@@ -31,61 +27,25 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { tenantStore } from '../../store/modules/tenant'
|
||||
import router from '../../router'
|
||||
import baiduCloudImage from "../../assets/baiducloud.png"
|
||||
import { config, scan } from '../../const/config'
|
||||
import { reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const handleOidcLogin = () => {
|
||||
const issuer = import.meta.env.VITE_OIDC_ISSUER
|
||||
const clientId = import.meta.env.VITE_OIDC_CLIENT_ID
|
||||
const redirectUri = encodeURIComponent(import.meta.env.VITE_OIDC_REDIRECT_URI)
|
||||
const scope = encodeURIComponent('openid profile email')
|
||||
const state = Math.random().toString(36).substring(2)
|
||||
|
||||
let qrcode = config.BAIDU_CLOUD_URL + config.RESPONSE_TYPE + config.CLIENT_ID + config.REDIRECT_URI + config.SCOPE + config.DEVICE_ID + config.QR_CODE + config.DISPLAY
|
||||
|
||||
const useTenantStore = tenantStore()
|
||||
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const loginForm = reactive({
|
||||
user_id: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
const validateUserName = (rule: any, value: string, callback: Function) => {
|
||||
if (!value) {
|
||||
callback(new Error("请输入的用户名"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validatePassword = (rule: any, value: string, callback: Function) => {
|
||||
if (!value) {
|
||||
callback(new Error("请输入密码"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const loginRules = reactive({
|
||||
user_id: [{ validator: validateUserName, trigger: 'blur' }],
|
||||
password: [{ validator: validatePassword, trigger: 'blur' }]
|
||||
})
|
||||
|
||||
|
||||
const dologin = (form: any) => {
|
||||
|
||||
if (!form)
|
||||
if (!issuer || !clientId) {
|
||||
ElMessage.error('OIDC 未配置,请联系管理员')
|
||||
return
|
||||
// form.validate((valid: any) => {
|
||||
// if (valid) {
|
||||
// useTenantStore.login(loginForm.user_id, loginForm.password).then(res => {
|
||||
// console.log(1)
|
||||
// router.push({
|
||||
// path: '/home'
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
// } else {
|
||||
// return false
|
||||
// }
|
||||
// })
|
||||
sessionStorage.setItem('oidc_state', state)
|
||||
window.location.href =
|
||||
`${issuer}/application/o/authorize/?` +
|
||||
`client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}`
|
||||
}
|
||||
|
||||
const openSiteQuery = () => {
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
<el-input v-model="register_form.code" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="tenantId">
|
||||
<el-input v-model="register_form.tenant_id" :disabled="true" />
|
||||
<el-form-item label="customerId">
|
||||
<el-input v-model="register_form.customerId" :disabled="true" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="account">
|
||||
@@ -35,17 +35,17 @@ import { reactive } from 'vue'
|
||||
import { useRoute } from 'vue-router';
|
||||
import { register_user } from "./../../api/user";
|
||||
import router from '../../router/index'
|
||||
import { setTenant, setToken } from '../../utils/auth';
|
||||
import { setCustomer, setToken } from '../../utils/auth';
|
||||
|
||||
const route = useRoute()
|
||||
const params = route.query
|
||||
|
||||
|
||||
// use phone number to register user(tenant)
|
||||
// use phone number to register user(customer)
|
||||
const register_form = reactive({
|
||||
phone_number: '',
|
||||
code: '',
|
||||
tenant_id: params.tenantId as string,
|
||||
customerId: params.customerId as string,
|
||||
account: params.account as string,
|
||||
token: params.token as string
|
||||
})
|
||||
@@ -54,13 +54,13 @@ const onSubmit = () => {
|
||||
register_user(register_form).then((response) => {
|
||||
|
||||
if (response.status == 200) {
|
||||
const tenant = {
|
||||
id: params.tenantId,
|
||||
const customer = {
|
||||
id: params.customerId,
|
||||
account: params.account
|
||||
}
|
||||
|
||||
setToken(params.token as string)
|
||||
setTenant(tenant)
|
||||
setCustomer(customer)
|
||||
|
||||
const { href } = router.resolve({
|
||||
path: '/'
|
||||
@@ -74,4 +74,4 @@ const onSubmit = () => {
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
Reference in New Issue
Block a user