Compare commits
4 Commits
f944dd680c
...
cddbba0e0f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cddbba0e0f | ||
|
|
781a3137a6 | ||
|
|
d977da5c38 | ||
|
|
e06bd84f29 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -89,6 +89,7 @@ typings/
|
||||
|
||||
# Vite
|
||||
.vite/
|
||||
*.timestamp-*.mjs
|
||||
|
||||
# Electron-Forge
|
||||
out/
|
||||
|
||||
@@ -105,6 +105,7 @@ const menus = ref([
|
||||
{ name: '知识空间', index: '/knowledge', icon: 'book' },
|
||||
{ name: 'opencode对话', index: '/chat', icon: 'bot' },
|
||||
{ name: '发现设备', index: '/bonjour', icon: 'server' },
|
||||
{ name: '测试页', index: '/test', icon: 'flask-conical' },
|
||||
]);
|
||||
|
||||
// 处理菜单点击
|
||||
|
||||
125
src/renderer/components/LoginDialog.vue
Normal file
125
src/renderer/components/LoginDialog.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" :show-close="false" width="680px" border-radius="16px" :close-on-click-modal="true" class="login-dialog">
|
||||
<div class="flex h-[420px] rounded-2xl overflow-hidden">
|
||||
<!-- 左侧表单区 -->
|
||||
<div class="flex flex-col items-center justify-center w-1/2 px-10 py-8 bg-white">
|
||||
<!-- Logo 占位,后续替换为真实图片 -->
|
||||
<div class="mb-4">
|
||||
<div class="w-14 h-14 rounded-full bg-green-100 flex items-center justify-center text-2xl">🤖</div>
|
||||
</div>
|
||||
|
||||
<p class="text-base font-semibold text-gray-700 mb-6">登录后体验更多功能</p>
|
||||
|
||||
<el-form :model="form" :rules="rules" ref="formRef" class="w-full" @submit.prevent="handleLogin">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="form.username" placeholder="请输入账号" :prefix-icon="User" size="large" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="form.password" type="password" placeholder="请输入密码" show-password size="large" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="w-full flex justify-end mb-4">
|
||||
<span class="text-xs text-gray-400 cursor-pointer hover:text-green-500">忘记密码?</span>
|
||||
</div>
|
||||
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
class="w-full !bg-black !border-black !rounded-full !text-white font-semibold"
|
||||
:loading="loading"
|
||||
@click="handleLogin"
|
||||
>
|
||||
登录
|
||||
</el-button>
|
||||
|
||||
<div class="mt-4 flex items-center gap-2 text-xs text-gray-400">
|
||||
<el-checkbox v-model="agreed" size="small" />
|
||||
<span>请先阅读<a href="#" class="text-green-500">用户协议与隐私政策</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧品牌区 -->
|
||||
<div class="flex flex-col items-center justify-between w-1/2 bg-[#5DC98A] px-8 py-8 rounded-r-2xl">
|
||||
<div class="self-end text-white text-2xl font-bold tracking-widest">玄鉴</div>
|
||||
<div class="flex flex-col items-center gap-3 text-white text-center">
|
||||
<p class="text-xl font-semibold">我是AI工作助手</p>
|
||||
<p class="text-sm opacity-80">能独立思考、自主执行的工作伙伴</p>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { User } from '@element-plus/icons-vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'login-success']);
|
||||
|
||||
const visible = ref(props.modelValue);
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => (visible.value = val)
|
||||
);
|
||||
watch(visible, (val) => emit('update:modelValue', val));
|
||||
|
||||
const formRef = ref(null);
|
||||
const loading = ref(false);
|
||||
const agreed = ref(false);
|
||||
|
||||
const form = ref({
|
||||
username: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
const rules = {
|
||||
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
||||
};
|
||||
|
||||
async function handleLogin() {
|
||||
if (!agreed.value) {
|
||||
ElMessage.warning('请先阅读并同意用户协议与隐私政策');
|
||||
return;
|
||||
}
|
||||
await formRef.value?.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
loading.value = true;
|
||||
try {
|
||||
// TODO: 替换为真实登录接口
|
||||
await new Promise((r) => setTimeout(r, 800));
|
||||
ElMessage.success('登录成功');
|
||||
emit('login-success', { username: form.value.username });
|
||||
visible.value = false;
|
||||
} catch (err) {
|
||||
ElMessage.error('登录失败,请重试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.el-dialog) {
|
||||
border-radius: 16px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
:deep(.el-dialog__header) {
|
||||
display: none;
|
||||
}
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -19,6 +19,12 @@ const routes = [
|
||||
component: () => import('@/views/bonjour/BonjourView.vue'),
|
||||
meta: { title: '发现设备' },
|
||||
},
|
||||
{
|
||||
path: '/test',
|
||||
name: 'Test',
|
||||
component: () => import('@/views/test/TestView.vue'),
|
||||
meta: { title: '测试页' },
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
17
src/renderer/views/test/TestView.vue
Normal file
17
src/renderer/views/test/TestView.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center h-full">
|
||||
<el-button type="primary" size="large" @click="showLogin = true">打开登录弹窗</el-button>
|
||||
<LoginDialog v-model="showLogin" @login-success="onLoginSuccess" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import LoginDialog from '@/components/LoginDialog.vue';
|
||||
|
||||
const showLogin = ref(false);
|
||||
|
||||
function onLoginSuccess(user) {
|
||||
console.log('登录成功:', user);
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user