feat: 合并代码
This commit is contained in:
1
src/renderer/auto-imports.d.ts
vendored
1
src/renderer/auto-imports.d.ts
vendored
@@ -192,6 +192,7 @@ declare global {
|
||||
const useFullscreen: typeof import('@vueuse/core').useFullscreen
|
||||
const useGamepad: typeof import('@vueuse/core').useGamepad
|
||||
const useGeolocation: typeof import('@vueuse/core').useGeolocation
|
||||
const useI18n: typeof import('vue-i18n').useI18n
|
||||
const useId: typeof import('vue').useId
|
||||
const useIdle: typeof import('@vueuse/core').useIdle
|
||||
const useImage: typeof import('@vueuse/core').useImage
|
||||
|
||||
76
src/renderer/components/HeaderBar/index.vue
Normal file
76
src/renderer/components/HeaderBar/index.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<header class="title-bar flex items-start justify-between h-[40px]">
|
||||
<div class="title-bar-main flex-auto">
|
||||
<slot>{{ title ?? '' }}</slot>
|
||||
</div>
|
||||
|
||||
<div class="title-bar-controls w-[168px] flex items-center justify-end text-tx-secondary">
|
||||
<native-tooltip :content="t('window.minimize')">
|
||||
<button v-show="isMinimizable" class="flex items-center justify-center cursor-pointer w-[40px] h-[40px]"
|
||||
@click="minimizeWindow">
|
||||
<iconify-icon icon="material-symbols:check-indeterminate-small" color="#ffffff" :width="btnSize"
|
||||
:height="btnSize" />
|
||||
</button>
|
||||
</native-tooltip>
|
||||
<native-tooltip :content="isMaximized ? t('window.restore') : t('window.maximize')">
|
||||
<button v-show="isMaximizable" class="flex items-center justify-center cursor-pointer w-[40px] h-[40px]"
|
||||
@click="maximizeWindow">
|
||||
<iconify-icon icon="material-symbols:chrome-maximize-outline-sharp" color="#ffffff" :width="btnSize"
|
||||
:height="btnSize" v-show="!isMaximized" />
|
||||
<iconify-icon icon="material-symbols:chrome-restore-outline-sharp" color="#ffffff" :width="btnSize"
|
||||
:height="btnSize" v-show="isMaximized" />
|
||||
</button>
|
||||
</native-tooltip>
|
||||
<native-tooltip :content="t('window.close')">
|
||||
<button v-show="isClosable" class="flex items-center justify-center cursor-pointer w-[40px] h-[40px]"
|
||||
@click="handleClose">
|
||||
<iconify-icon icon="material-symbols:close" color="#ffffff" :width="btnSize" :height="btnSize" />
|
||||
</button>
|
||||
</native-tooltip>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Icon as IconifyIcon } from '@iconify/vue'
|
||||
import { useWinManager } from '@hooks/useWinManager'
|
||||
|
||||
import NativeTooltip from '@components/NativeTooltip/index.vue'
|
||||
|
||||
interface HeaderBarProps {
|
||||
title?: string;
|
||||
isMaximizable?: boolean;
|
||||
isMinimizable?: boolean;
|
||||
isClosable?: boolean;
|
||||
}
|
||||
|
||||
defineOptions({ name: 'HeaderBar' })
|
||||
|
||||
withDefaults(defineProps<HeaderBarProps>(), {
|
||||
isMaximizable: true,
|
||||
isMinimizable: true,
|
||||
isClosable: true,
|
||||
})
|
||||
const emit = defineEmits(['close']);
|
||||
const { t } = useI18n();
|
||||
|
||||
const btnSize = 16;
|
||||
|
||||
const {
|
||||
isMaximized,
|
||||
closeWindow,
|
||||
minimizeWindow,
|
||||
maximizeWindow
|
||||
} = useWinManager();
|
||||
|
||||
function handleClose() {
|
||||
emit('close');
|
||||
closeWindow();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title-bar {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
</style>
|
||||
43
src/renderer/components/NativeTooltip/index.vue
Normal file
43
src/renderer/components/NativeTooltip/index.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<template v-if="slots.default()[0].el">
|
||||
<slot></slot>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span :title="content">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { logger } from '@utils/logger'
|
||||
|
||||
interface Props {
|
||||
content: string;
|
||||
}
|
||||
|
||||
defineOptions({ name: 'NativeTooltip' });
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const slots = defineSlots()
|
||||
|
||||
if (slots?.default?.().length > 1) {
|
||||
logger.warn('NativeTooltip only support one slot.')
|
||||
}
|
||||
|
||||
const updateTooltipContent = (content: string) => {
|
||||
const defaultSlot = slots?.default?.();
|
||||
|
||||
if (defaultSlot) {
|
||||
const slotElement = defaultSlot[0]?.el
|
||||
|
||||
if (slotElement && slotElement instanceof HTMLElement) {
|
||||
slotElement.title = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => updateTooltipContent(props.content))
|
||||
|
||||
watch(() => props.content, (val: string) => updateTooltipContent(val));
|
||||
</script>
|
||||
@@ -0,0 +1,31 @@
|
||||
export function useWinManager() {
|
||||
const isMaximized = ref(false)
|
||||
|
||||
function closeWindow() {
|
||||
window.api.closeWindow();
|
||||
}
|
||||
|
||||
function minimizeWindow() {
|
||||
window.api.minimizeWindow();
|
||||
}
|
||||
|
||||
function maximizeWindow() {
|
||||
window.api.maximizeWindow();
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
window.api.viewIsReady();
|
||||
isMaximized.value = await window.api.isWindowMaximized();
|
||||
window.api.onWindowMaximized((_isMaximized: boolean) => isMaximized.value = _isMaximized);
|
||||
})
|
||||
|
||||
return {
|
||||
isMaximized,
|
||||
closeWindow,
|
||||
minimizeWindow,
|
||||
maximizeWindow
|
||||
}
|
||||
};
|
||||
|
||||
export default useWinManager;
|
||||
|
||||
44
src/renderer/i18n.ts
Normal file
44
src/renderer/i18n.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { createI18n, I18n, type I18nOptions } from 'vue-i18n';
|
||||
|
||||
const languages = ['zh', 'en'] as const;
|
||||
type LanguageType = (typeof languages)[number];
|
||||
|
||||
async function createI18nInstance() {
|
||||
const options: I18nOptions = {
|
||||
legacy: false,
|
||||
locale: 'zh',
|
||||
fallbackLocale: 'zh',
|
||||
messages: {
|
||||
zh: await import('@locales/zh.json').then(m => m.default),
|
||||
en: await import('@locales/en.json').then(m => m.default),
|
||||
}
|
||||
}
|
||||
|
||||
const i18n = createI18n(options);
|
||||
|
||||
return i18n
|
||||
}
|
||||
|
||||
|
||||
export const i18n = await createI18nInstance();
|
||||
|
||||
export async function setLanguage(lang:LanguageType,_i18n?:I18n){
|
||||
const __i18n = _i18n ?? i18n;
|
||||
|
||||
if(__i18n.mode === 'legacy'){
|
||||
__i18n.global.locale = lang;
|
||||
return;
|
||||
}
|
||||
|
||||
(__i18n.global.locale as unknown as Ref<LanguageType>).value = lang;
|
||||
}
|
||||
|
||||
export function getLanguage(){
|
||||
if(i18n.mode === 'legacy'){
|
||||
return i18n.global.locale;
|
||||
}
|
||||
|
||||
return (i18n.global.locale as unknown as Ref<LanguageType>).value;
|
||||
}
|
||||
|
||||
export default i18n;
|
||||
@@ -1,25 +1,35 @@
|
||||
import { createApp } from "vue";
|
||||
import { createApp, type Plugin } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
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'
|
||||
// import './permission'
|
||||
|
||||
// 样式文件隔离
|
||||
import "./styles/index.css";
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
// 引入全局组件
|
||||
import HeaderBar from '@components/HeaderBar/index.vue'
|
||||
import DragRegion from '@components/DragRegion/index.vue'
|
||||
|
||||
const components: Plugin = (app) => {
|
||||
app.component('HeaderBar', HeaderBar);
|
||||
app.component('DragRegion', DragRegion);
|
||||
}
|
||||
|
||||
// 创建 Vue 应用实例
|
||||
const app = createApp(App);
|
||||
const pinia = createPinia();
|
||||
|
||||
// 使用 Pinia 状态管理
|
||||
app.use(createPinia());
|
||||
|
||||
|
||||
// 使用 Vue Router
|
||||
app.use(pinia);
|
||||
app.use(router);
|
||||
app.use(ElementPlus, { locale })
|
||||
app.use(components)
|
||||
app.use(i18n)
|
||||
|
||||
// 挂载应用到 DOM
|
||||
app.mount("#app");
|
||||
|
||||
@@ -1,77 +1,18 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import Layout from '@renderer/layout/index.vue'
|
||||
import { createRouter, createMemoryHistory } from "vue-router";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: "/login",
|
||||
name: "Login",
|
||||
component: () => import("@renderer/views/login/index.vue"),
|
||||
},
|
||||
{
|
||||
path: "/browser",
|
||||
name: "Browser",
|
||||
component: () => import("@renderer/browser/BrowserLayout.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
component: Layout,
|
||||
children: [
|
||||
{
|
||||
path: "home",
|
||||
component: () => import("@renderer/views/home/index.vue"),
|
||||
name: "Home",
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "stock",
|
||||
name: "Stock",
|
||||
component: () => import("@renderer/views/stock/index.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "rate",
|
||||
name: "Rate",
|
||||
component: () => import("@renderer/views/rate/index.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "order",
|
||||
name: "Order",
|
||||
component: () => import("@renderer/views/order/index.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "more",
|
||||
name: "More",
|
||||
component: () => import("@renderer/views/more/index.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "setting",
|
||||
name: "Setting",
|
||||
component: () => import("@renderer/views/setting/index.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: "/dashboard",
|
||||
name: "Dashboard",
|
||||
component: () => import("@renderer/views/dashboard/index.vue"),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/about",
|
||||
name: "About",
|
||||
component: () => import("@renderer/views/about/index.vue"),
|
||||
},
|
||||
component: () => import("@renderer/views/login/index.vue"),
|
||||
name: "Login",
|
||||
meta: { requiresAuth: false },
|
||||
}
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
history: createMemoryHistory(),
|
||||
routes,
|
||||
scrollBehavior(to: any, from: any, savedPosition: any) {
|
||||
scrollBehavior(_to: any, _from: any, savedPosition: any) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
}
|
||||
@@ -80,24 +21,24 @@ const router = createRouter({
|
||||
},
|
||||
});
|
||||
|
||||
router.beforeEach((to: any, from: any, next: any) => {
|
||||
const token = localStorage.getItem("token");
|
||||
if (to.meta && (to.meta as any).requiresAuth && !token) {
|
||||
next({ path: "/login" });
|
||||
return;
|
||||
}
|
||||
// router.beforeEach((to: any, from: any, next: any) => {
|
||||
// const token = localStorage.getItem("token");
|
||||
// if (to.meta && (to.meta as any).requiresAuth && !token) {
|
||||
// next({ path: "/login" });
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (token && to.path === "/login") {
|
||||
next({ path: "/home" });
|
||||
return;
|
||||
}
|
||||
// if (token && to.path === "/login") {
|
||||
// next({ path: "/home" });
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (token && to.path === "/") {
|
||||
next({ path: "/home" });
|
||||
return;
|
||||
}
|
||||
// if (token && to.path === "/") {
|
||||
// next({ path: "/home" });
|
||||
// return;
|
||||
// }
|
||||
|
||||
next();
|
||||
});
|
||||
// next();
|
||||
// });
|
||||
|
||||
export default router;
|
||||
|
||||
18
src/renderer/utils/errorHandler.ts
Normal file
18
src/renderer/utils/errorHandler.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { Plugin } from 'vue'
|
||||
import logger from './logger'
|
||||
|
||||
export const errorHandler: Plugin = (app) => {
|
||||
app.config.errorHandler = (err, instance, info) => {
|
||||
logger.error('Vue error:', err, instance, info);
|
||||
};
|
||||
|
||||
window.onerror = (message, source, lineno, colno, error) => {
|
||||
logger.error('Window error:', message, source, lineno, colno, error);
|
||||
};
|
||||
|
||||
window.onunhandledrejection = (event) => {
|
||||
logger.error('Unhandled Promise Rejection:', event);
|
||||
};
|
||||
};
|
||||
|
||||
export default errorHandler;
|
||||
12
src/renderer/utils/logger.ts
Normal file
12
src/renderer/utils/logger.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export const logger = window.api.logger ?? console;
|
||||
|
||||
if (window.api.logger) {
|
||||
console.debug = logger.debug;
|
||||
console.log = logger.info;
|
||||
console.info = logger.info;
|
||||
console.warn = logger.warn;
|
||||
console.error = logger.error;
|
||||
}
|
||||
|
||||
export default logger;
|
||||
15
src/renderer/views/dialog/index.ts
Normal file
15
src/renderer/views/dialog/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import '@renderer/styles/index.css'
|
||||
|
||||
import errorHandler from '@utils/errorHandler'
|
||||
import i18n from '@renderer/i18n'
|
||||
import HeaderBar from '@renderer/components/HeaderBar/index.vue'
|
||||
import DragRegion from '@renderer/components/DragRegion/index.vue'
|
||||
|
||||
import Dialog from './index.vue'
|
||||
|
||||
createApp(Dialog)
|
||||
.use(i18n)
|
||||
.use(errorHandler)
|
||||
.component('HeaderBar', HeaderBar)
|
||||
.component('DragRegion', DragRegion)
|
||||
.mount('#app')
|
||||
5
src/renderer/views/dialog/index.vue
Normal file
5
src/renderer/views/dialog/index.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template></template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
16
src/renderer/views/login/index.ts
Normal file
16
src/renderer/views/login/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import '@renderer/styles/index.css'
|
||||
|
||||
import errorHandler from '@utils/errorHandler'
|
||||
import i18n from '@renderer/i18n'
|
||||
import HeaderBar from '@renderer/components/HeaderBar/index.vue'
|
||||
import DragRegion from '@renderer/components/DragRegion/index.vue'
|
||||
|
||||
import Login from './index.vue'
|
||||
|
||||
createApp(Login)
|
||||
.use(i18n)
|
||||
.use(createPinia())
|
||||
.use(errorHandler)
|
||||
.component('HeaderBar', HeaderBar)
|
||||
.component('DragRegion', DragRegion)
|
||||
.mount('#app')
|
||||
@@ -1,86 +1,90 @@
|
||||
<template>
|
||||
<div class="h-screen box-border p-[8px] login-bg flex items-center justify-center">
|
||||
<div class="w-[836px] h-full bg-white rounded-2xl p-[32px] flex flex-col">
|
||||
<div class="flex items-center">
|
||||
<img class="w-[48px] h-[48px]" src="@assets/images/login/blue_logo.png" />
|
||||
<div class="h-screen login-bg flex flex-col">
|
||||
<header-bar>
|
||||
<drag-region class="w-full" />
|
||||
</header-bar>
|
||||
|
||||
<span class="ml-auto text-[14px] text-gray-600">没有账号?</span>
|
||||
<button
|
||||
class="bg-sky-50 rounded-[8px] text-[14px] text-sky-600 px-[12px] py-[6px] focus-visible:outline-none">注册</button>
|
||||
</div>
|
||||
<main class="box-border p-[8px] flex-auto flex ">
|
||||
<div class="w-[836px] box-border bg-white rounded-2xl p-[32px] flex flex-col">
|
||||
<div class="flex items-center">
|
||||
<img class="w-[48px] h-[48px]" src="@assets/images/login/blue_logo.png" />
|
||||
|
||||
<div class="flex flex-col items-center justify-center mb-[24px] box-border pt-[108px]">
|
||||
<img class="w-[80px] h-[80px] mb-[12px]" src="@assets/images/login/user_icon.png" />
|
||||
<div class="text-[24px] font-500 text-gray-800 line-height-[32px] mb-[4px]">登录</div>
|
||||
<div class="text-[16px] text-gray-500 line-height-[24px]">24小时在岗,从不打烊的数字员工</div>
|
||||
</div>
|
||||
<!-- <span class="ml-auto text-[14px] text-gray-600">没有账号?</span>
|
||||
<button
|
||||
class="bg-sky-50 rounded-[8px] text-[14px] text-sky-600 px-[12px] py-[6px] focus-visible:outline-none cursor-pointer">注册</button> -->
|
||||
</div>
|
||||
|
||||
<el-form class="w-[392px] ml-auto mr-auto" ref="formRef" :rules="rules" :model="form" label-position="top"
|
||||
@keyup.enter="onSubmit">
|
||||
<el-form-item prop="username">
|
||||
<div class="text-[14px] text-gray-600">账号</div>
|
||||
<el-input v-model.trim="form.username" placeholder="请输入账号" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<RiUser3Fill size="20px" color="#99A0AE" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<div class="text-[14px] text-gray-600">密码</div>
|
||||
<el-input v-model.trim="form.password" placeholder="请输入密码" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<RiKey2Fill size="20px" color="#99A0AE" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<div class="flex flex-col items-center justify-center mb-[24px] box-border pt-[108px]">
|
||||
<img class="w-[80px] h-[80px] mb-[12px]" src="@assets/images/login/user_icon.png" />
|
||||
<div class="text-[24px] font-500 text-gray-800 line-height-[32px] mb-[4px]">登录</div>
|
||||
<div class="text-[16px] text-gray-500 line-height-[24px]">24小时在岗,从不打烊的数字员工</div>
|
||||
</div>
|
||||
|
||||
<el-form-item prop="code">
|
||||
<span class="text-[14px] text-gray-600">验证码</span>
|
||||
<el-input v-model.trim="form.code" placeholder="请输入验证码" clearable autocomplete="off">
|
||||
<template #suffix>
|
||||
<img class="w-[80px] h-[38px] cursor-pointer" :src="imgSrc" @click="getVerifyCode" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form class="w-[392px] ml-auto mr-auto" ref="formRef" :rules="rules" :model="form" label-position="top"
|
||||
@keyup.enter="onSubmit">
|
||||
<el-form-item prop="username">
|
||||
<div class="text-[14px] text-gray-600">账号</div>
|
||||
<el-input class="h-[40px]" v-model.trim="form.username" placeholder="请输入账号" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<RiUser3Fill size="20px" color="#99A0AE" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<div class="text-[14px] text-gray-600">密码</div>
|
||||
<el-input class="h-[40px]" v-model.trim="form.password" placeholder="请输入密码" clearable autocomplete="off">
|
||||
<template #prefix>
|
||||
<RiKey2Fill size="20px" color="#99A0AE" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 记住密码|忘记密码 -->
|
||||
<div class="flex items-center justify-between mb-[24px] mt-[24px]">
|
||||
<div class="flex items-center gap-2 cursor-pointer">
|
||||
<input type="checkbox" v-model="showPwd" class="w-[14px] h-[14px] rounded-[4px]" />
|
||||
<span class="text-[14px] text-gray-600">记住密码</span>
|
||||
<el-form-item prop="code">
|
||||
<span class="text-[14px] text-gray-600">验证码</span>
|
||||
<el-input v-model.trim="form.code" placeholder="请输入验证码" autocomplete="off">
|
||||
<template #suffix>
|
||||
<img class="w-[80px] h-[38px] cursor-pointer" :src="imgSrc" @click="getVerifyCode" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 记住密码|忘记密码 -->
|
||||
<div class="flex items-center justify-between mb-[24px] mt-[24px]">
|
||||
<div class="flex items-center gap-2 cursor-pointer">
|
||||
<input type="checkbox" v-model="showPwd" class="w-[14px] h-[14px] rounded-[4px]" />
|
||||
<span class="text-[14px] text-gray-600">记住密码</span>
|
||||
</div>
|
||||
<!-- <span class="text-[14px] text-sky-600 cursor-pointer">忘记密码?</span> -->
|
||||
</div>
|
||||
<span class="text-[14px] text-sky-600">忘记密码?</span>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<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>
|
||||
|
||||
<!-- 同意协议 -->
|
||||
<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>
|
||||
</el-form>
|
||||
|
||||
<!-- Copy Right -->
|
||||
<div class="text-[14px] text-gray-500 text-center mt-auto">
|
||||
© 2025 贵州智念科技服务有限公司 版权所有
|
||||
</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>
|
||||
|
||||
<!-- 同意协议 -->
|
||||
<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">《使用协议》</span>
|
||||
<span class="text-[14px] text-gray-600">和</span>
|
||||
<span class="text-[14px] text-sky-600">《隐私协议》</span>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<!-- Copy Right -->
|
||||
<div class="text-[14px] text-gray-500 text-center mt-auto">
|
||||
© 2025 贵州智念科技服务有限公司 版权所有
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img class="w-[570px]" src="@assets/images/login/logo.png" />
|
||||
<img class="w-[540px]" src="@assets/images/login/logo.png" />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { authOauth2TokenUsingPost } from "@renderer/api";
|
||||
import { RiUser3Fill, RiKey2Fill } from '@remixicon/vue'
|
||||
import { generateUUID } from "@utils/generateUUID";
|
||||
@@ -145,4 +149,12 @@ const onSubmit = async () => {
|
||||
background-position: 0 0;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__error) {
|
||||
padding-top: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
15
src/renderer/views/setting/index.ts
Normal file
15
src/renderer/views/setting/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import '@renderer/styles/index.css'
|
||||
|
||||
import errorHandler from '@renderer/utils/errorHandler'
|
||||
import i18n from '@renderer/i18n'
|
||||
import HeaderBar from '@renderer/components/HeaderBar/index.vue'
|
||||
import DragRegion from '@renderer/components/DragRegion/index.vue'
|
||||
|
||||
import Setting from './index.vue'
|
||||
|
||||
createApp(Setting)
|
||||
.use(i18n)
|
||||
.use(errorHandler)
|
||||
.component('HeaderBar', HeaderBar)
|
||||
.component('DragRegion', DragRegion)
|
||||
.mount('#app')
|
||||
Reference in New Issue
Block a user