feat: 登录接口对接
This commit is contained in:
10
global.d.ts
vendored
10
global.d.ts
vendored
@@ -88,6 +88,16 @@ declare global {
|
||||
|
||||
type ThemeMode = 'dark' | 'light' | 'system';
|
||||
|
||||
// form 表单数据类型声明
|
||||
interface LoginForm {
|
||||
username: string;
|
||||
password: string;
|
||||
randomStr: string;
|
||||
code: string;
|
||||
grant_type: string;
|
||||
scope: string;
|
||||
}
|
||||
|
||||
// 弹窗类型定义
|
||||
interface CreateDialogProps {
|
||||
winId?: string;
|
||||
|
||||
@@ -12,7 +12,7 @@ const api: WindowApi = {
|
||||
minimizeWindow: () => ipcRenderer.send(IPC_EVENTS.WINDOW_MINIMIZE),
|
||||
maximizeWindow: () => ipcRenderer.send(IPC_EVENTS.WINDOW_MAXIMIZE),
|
||||
onWindowMaximized: (callback: (isMaximized: boolean) => void) => ipcRenderer.on(IPC_EVENTS.WINDOW_MAXIMIZE + 'back', (_, isMaximized) => callback(isMaximized)),
|
||||
isWindowMaximized: () => ipcRenderer.invoke(IPC_EVENTS.WINDOW_MAXIMIZE),
|
||||
isWindowMaximized: () => ipcRenderer.invoke(IPC_EVENTS.IS_WINDOW_MAXIMIZED),
|
||||
viewIsReady: () => ipcRenderer.send(IPC_EVENTS.RENDERER_IS_READY),
|
||||
|
||||
app: {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { createApp, type Plugin } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import router from "./router";
|
||||
import App from "./App.vue";
|
||||
import { createApp, type Plugin } from "vue"
|
||||
import { createPinia } from "pinia"
|
||||
import errorHandler from "@utils/errorHandler"
|
||||
import router from "./router"
|
||||
import App from "./App.vue"
|
||||
import ElementPlus from 'element-plus'
|
||||
import locale from 'element-plus/es/locale/lang/zh-cn'
|
||||
import i18n from './i18n'
|
||||
@@ -30,6 +31,7 @@ app.use(router);
|
||||
app.use(ElementPlus, { locale })
|
||||
app.use(components)
|
||||
app.use(i18n)
|
||||
app.use(errorHandler)
|
||||
|
||||
// 挂载应用到 DOM
|
||||
app.mount("#app");
|
||||
|
||||
@@ -15,7 +15,7 @@ router.beforeEach((to: any, _from: any, next: any) => {
|
||||
} else if (isWhiteList(to.path)) {
|
||||
next()
|
||||
} else {
|
||||
|
||||
next()
|
||||
}
|
||||
} else {
|
||||
// no token
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
export const useCounterStore = defineStore('counter', () => {
|
||||
const count = ref(0)
|
||||
|
||||
const doubleCount = computed(() => count.value * 2)
|
||||
|
||||
function increment() {
|
||||
count.value++
|
||||
}
|
||||
|
||||
function decrement() {
|
||||
count.value--
|
||||
}
|
||||
|
||||
function reset() {
|
||||
count.value = 0
|
||||
}
|
||||
|
||||
return { count, doubleCount, increment, decrement, reset }
|
||||
})
|
||||
50
src/renderer/store/userinfo.ts
Normal file
50
src/renderer/store/userinfo.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { authOauth2TokenUsingPost } from "@renderer/api"
|
||||
import { getToken, setToken, removeToken } from '@utils/auth'
|
||||
|
||||
export const useUserStore = defineStore('userInfo', {
|
||||
state: () => ({
|
||||
token: getToken(),
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* 登录方法
|
||||
* @function login
|
||||
* @async
|
||||
* @param {Object} data - 登录数据
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async login(data: LoginForm) {
|
||||
data.grant_type = 'password';
|
||||
data.scope = 'server';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
authOauth2TokenUsingPost({body: {...data, clientId: ''}})
|
||||
.then((res: any) => {
|
||||
// 存储token 信息
|
||||
setToken(res.access_token)
|
||||
resolve(res)
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 退出系统
|
||||
logOut() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// logout(this.token).then(() => {
|
||||
// this.token = ''
|
||||
// this.roles = []
|
||||
// this.permissions = []
|
||||
// removeToken()
|
||||
// resolve()
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { Plugin } from 'vue'
|
||||
import logger from './logger'
|
||||
|
||||
export const errorHandler: Plugin = (app) => {
|
||||
export const errorHandler: Plugin = (app) => {
|
||||
app.config.errorHandler = (err, instance, info) => {
|
||||
logger.error('Vue error:', err, instance, info);
|
||||
// 过滤掉无法序列化的 Vue 实例对象
|
||||
logger.error('Vue error:', err, info);
|
||||
};
|
||||
|
||||
window.onerror = (message, source, lineno, colno, error) => {
|
||||
|
||||
@@ -1,5 +1,67 @@
|
||||
const safeStringify = (arg: any) => {
|
||||
try {
|
||||
// 处理 Error 对象
|
||||
if (arg instanceof Error) {
|
||||
return {
|
||||
message: arg.message,
|
||||
stack: arg.stack,
|
||||
name: arg.name
|
||||
}
|
||||
}
|
||||
// 简单值直接返回
|
||||
if (typeof arg !== 'object' || arg === null) {
|
||||
return arg
|
||||
}
|
||||
// 处理 Vue 响应式对象(Proxy)
|
||||
if (arg?.__v_isRef || arg?.__v_isReactive || arg?.__v_isReadonly) {
|
||||
// 尝试解包 Proxy/Ref
|
||||
try {
|
||||
const raw = JSON.parse(JSON.stringify(arg))
|
||||
return raw
|
||||
} catch (e) {
|
||||
return '[Vue Reactive Object]'
|
||||
}
|
||||
}
|
||||
// 尝试深拷贝,如果失败则说明包含不可序列化对象
|
||||
const raw = JSON.parse(JSON.stringify(arg))
|
||||
return raw
|
||||
} catch (e) {
|
||||
// 序列化失败,返回字符串描述
|
||||
return String(arg)
|
||||
}
|
||||
}
|
||||
|
||||
export const logger = window.api.logger ?? console;
|
||||
// 缓存原始 console 方法,防止递归调用和保持控制台输出
|
||||
const originalConsole = {
|
||||
debug: console.debug.bind(console),
|
||||
log: console.log.bind(console),
|
||||
info: console.info.bind(console),
|
||||
warn: console.warn.bind(console),
|
||||
error: console.error.bind(console),
|
||||
}
|
||||
|
||||
const createSafeLogger = (originalLogger: any) => {
|
||||
return {
|
||||
debug: (message: string, ...meta: any[]) => {
|
||||
originalConsole.debug(message, ...meta)
|
||||
originalLogger.debug(String(message), ...meta.map(safeStringify))
|
||||
},
|
||||
info: (message: string, ...meta: any[]) => {
|
||||
originalConsole.info(message, ...meta)
|
||||
originalLogger.info(String(message), ...meta.map(safeStringify))
|
||||
},
|
||||
warn: (message: string, ...meta: any[]) => {
|
||||
originalConsole.warn(message, ...meta)
|
||||
originalLogger.warn(String(message), ...meta.map(safeStringify))
|
||||
},
|
||||
error: (message: string, ...meta: any[]) => {
|
||||
originalConsole.error(message, ...meta)
|
||||
originalLogger.error(String(message), ...meta.map(safeStringify))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const logger = window.api.logger ? createSafeLogger(window.api.logger) : console
|
||||
|
||||
if (window.api.logger) {
|
||||
console.debug = logger.debug;
|
||||
|
||||
@@ -58,19 +58,20 @@
|
||||
</div>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<button class="w-full py-2 bg-blue-600 text-white rounded-[8px] hover:bg-blue-700 disabled:bg-blue-300"
|
||||
@click="onSubmit">
|
||||
{{ loading ? '登录中…' : '登录' }}
|
||||
<button type="button"
|
||||
class="w-full py-2 bg-blue-600 cursor-pointer text-white rounded-[8px] hover:bg-blue-700 disabled:bg-blue-300"
|
||||
:loading="loading" @click="onSubmit">
|
||||
登 录
|
||||
</button>
|
||||
|
||||
<!-- 同意协议 -->
|
||||
<div class="flex items-center justify-center gap-2 mt-[24px]">
|
||||
<!-- <div class="flex items-center justify-center gap-2 mt-[24px]">
|
||||
<input type="checkbox" v-model="isAgree" class="w-[14px] h-[14px] rounded-[4px]" />
|
||||
<span class="text-[14px] text-gray-600">我已同意</span>
|
||||
<span class="text-[14px] text-sky-600 cursor-pointer">《使用协议》</span>
|
||||
<span class="text-[14px] text-gray-600">和</span>
|
||||
<span class="text-[14px] text-sky-600 cursor-pointer">《隐私协议》</span>
|
||||
</div>
|
||||
</div> -->
|
||||
</el-form>
|
||||
|
||||
<!-- Copy Right -->
|
||||
@@ -81,27 +82,17 @@
|
||||
|
||||
<img class="w-[540px]" src="@assets/images/login/logo.png" />
|
||||
</main>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { authOauth2TokenUsingPost } from "@renderer/api";
|
||||
import { useUserStore } from "@renderer/store/userinfo"
|
||||
import { RiUser3Fill, RiKey2Fill } from '@remixicon/vue'
|
||||
import { generateUUID } from "@utils/generateUUID";
|
||||
import { generateUUID } from "@utils/generateUUID"
|
||||
import { rule } from '@utils/validate'
|
||||
|
||||
|
||||
// form 表单数据类型声明
|
||||
interface LoginForm {
|
||||
username: string;
|
||||
password: string;
|
||||
randomStr: string;
|
||||
code: string;
|
||||
}
|
||||
|
||||
const router = useRouter();
|
||||
const form = reactive<LoginForm>({ username: "", password: "", randomStr: '', code: "" });
|
||||
const userStore = useUserStore()
|
||||
const form = reactive<LoginForm>({ username: "", password: "", randomStr: '', code: "", grant_type: '', scope: '' });
|
||||
const loading = ref(false);
|
||||
const showPwd = ref(false);
|
||||
const isAgree = ref(false);
|
||||
@@ -130,13 +121,10 @@ const onSubmit = async () => {
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
// localStorage.setItem("token", "dev-token");
|
||||
// const res: any = await authOauth2TokenUsingPost({ body: form });
|
||||
// const token = res && (res.token || res.data?.token || res.access_token);
|
||||
// if (!token) throw new Error("登录失败");
|
||||
// localStorage.setItem("token", token);
|
||||
// await (window as any).api.app.setFrameless('/home')
|
||||
router.push('/home');
|
||||
userStore.login(form).then(() => {
|
||||
// window.location.href = 'index.html'
|
||||
console.log(form)
|
||||
})
|
||||
} finally {
|
||||
getVerifyCode()
|
||||
loading.value = false; // 登录结束
|
||||
|
||||
Reference in New Issue
Block a user