Compare commits

..

4 Commits

Author SHA1 Message Date
houakang
cddbba0e0f Merge branch 'fix-error' of https://gitea.cirry.cn/cirry/electron-opencode into fix-error 2026-04-12 10:55:39 +08:00
houakang
781a3137a6 feat: 添加登录对话框组件和测试路由
添加新的登录对话框组件 LoginDialog.vue,包含表单验证和登录逻辑
在路由配置中添加测试页路由 '/test' 用于后续开发
2026-04-12 10:55:28 +08:00
houakang
d977da5c38 feat: 添加测试页面及路由配置
新增测试页面视图组件并在主菜单中添加测试页入口,用于开发阶段的测试验证
2026-04-12 10:55:16 +08:00
houakang
e06bd84f29 chore: 在.gitignore中添加Vite生成的timestamp文件
添加*.timestamp-*.mjs到.gitignore以忽略Vite生成的时间戳文件
2026-04-12 10:55:01 +08:00
5 changed files with 150 additions and 0 deletions

1
.gitignore vendored
View File

@@ -89,6 +89,7 @@ typings/
# Vite
.vite/
*.timestamp-*.mjs
# Electron-Forge
out/

View File

@@ -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' },
]);
// 处理菜单点击

View 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>

View File

@@ -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({

View 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>