Files
tiantian-system/app/pages/developer/source.vue
2026-04-08 17:10:58 +08:00

369 lines
9.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="dev-page">
<div class="page-header">
<div>
<h2 class="page-title">💻 源码与仓库</h2>
<p class="page-desc">申请仓库访问权限获取完整源代码支持私有化部署与二次开发</p>
</div>
<a-button type="primary" @click="navigateTo('/developer/git')">
🐙 去绑定 Git 账号
</a-button>
</div>
<div class="page-body">
<!-- 权限获取流程 -->
<div class="panel mb-5">
<div class="panel-header">
<span class="panel-title">🚦 仓库访问权限流程</span>
</div>
<div class="flow-steps">
<div
v-for="(step, i) in steps"
:key="step.title"
class="flow-step"
:class="{ active: i <= currentStep, done: i < currentStep }"
>
<div class="flow-step-icon">
<span v-if="i < currentStep"></span>
<span v-else>{{ i + 1 }}</span>
</div>
<div class="flow-step-content">
<div class="flow-step-title">{{ step.title }}</div>
<div class="flow-step-desc">{{ step.desc }}</div>
<a-button
v-if="step.action"
size="small"
:type="i === currentStep ? 'primary' : 'default'"
class="mt-2"
@click="navigateTo(step.actionTo!)"
>
{{ step.action }}
</a-button>
</div>
<div v-if="i < steps.length - 1" class="flow-connector" />
</div>
</div>
</div>
<a-row :gutter="[16, 16]">
<!-- 仓库列表 -->
<a-col :xs="24" :lg="16">
<div class="panel">
<div class="panel-header">
<span class="panel-title">📁 我的仓库</span>
<a-button size="small" type="link" @click="navigateTo('/developer/requests')">查看申请记录</a-button>
</div>
<div class="empty-state">
<div class="empty-icon">💻</div>
<div class="empty-title">暂无可访问的仓库</div>
<div class="empty-desc">完成仓库权限申请后获批的仓库将在此处显示</div>
<a-space class="mt-4">
<a-button type="primary" @click="navigateTo('/developer/git')">绑定 Git 账号</a-button>
<a-button @click="navigateTo('/developer/requests')">申请记录</a-button>
</a-space>
</div>
</div>
</a-col>
<!-- 源码模块说明 -->
<a-col :xs="24" :lg="8">
<div class="panel">
<div class="panel-header">
<span class="panel-title">📦 源码包含模块</span>
</div>
<div class="module-list">
<div v-for="mod in modules" :key="mod.title" class="module-item">
<div class="module-icon" :class="mod.color">{{ mod.emoji }}</div>
<div class="module-info">
<div class="module-title">{{ mod.title }}</div>
<div class="module-desc">{{ mod.desc }}</div>
</div>
</div>
</div>
</div>
<div class="panel mt-4">
<div class="panel-header">
<span class="panel-title"> 源码权益说明</span>
</div>
<ul class="rights-list">
<li v-for="right in rights" :key="right" class="rights-item">
<span class="rights-check"></span>
<span>{{ right }}</span>
</li>
</ul>
</div>
</a-col>
</a-row>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({ layout: 'developer' })
useHead({ title: '源码与仓库 - 开发者中心' })
// 当前所在步骤0=未绑定Git1=已绑定待申请2=已申请待审核3=已获权限)
const currentStep = ref(0)
const steps = [
{
title: '绑定 Git 账号',
desc: '在 Git 账号绑定页面填写你的 Gitea 用户名,用于后续加组操作。',
action: '前往绑定',
actionTo: '/developer/git',
},
{
title: '提交加组申请',
desc: '填写申请表单,说明你需要访问的仓库和用途,等待运营审核。',
action: '提交申请',
actionTo: '/developer/requests',
},
{
title: '运营审核处理',
desc: '运营人员将在 1-3 个工作日内完成审核,并将你加入对应 Git 组。',
action: null,
actionTo: null,
},
{
title: '获得仓库访问权限',
desc: '审核通过后,你可以通过 Gitea 克隆仓库,开始二次开发。',
action: null,
actionTo: null,
},
]
const modules = [
{ emoji: '🗂️', title: 'Nuxt 4 前端', desc: 'Vue 3 + TypeScript完整 SSR 源码', color: 'blue' },
{ emoji: '⚙️', title: 'Java 后端', desc: 'Spring Boot 3多租户 SaaS 架构', color: 'purple' },
{ emoji: '🤖', title: 'AI 模块', desc: 'OpenClaw 集成RAG 知识库引擎', color: 'orange' },
{ emoji: '🚢', title: '部署脚本', desc: 'Docker Compose + CI/CD 流水线', color: 'green' },
]
const rights = [
'完整多租户 SaaS 源码',
'私有 Git 仓库,持续同步更新',
'无商用限制,可自由二次开发',
'支持私有化本地/云端部署',
'详细架构说明与部署文档',
]
</script>
<style scoped>
.dev-page { min-height: 100%; }
.page-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
padding: 24px 28px 16px;
border-bottom: 1px solid #f0f0f0;
gap: 16px;
}
.page-title {
font-size: 20px;
font-weight: 700;
color: rgba(0, 0, 0, 0.88);
margin: 0 0 4px;
}
.page-desc {
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
margin: 0;
}
.page-body {
padding: 20px 24px 28px;
}
.panel {
background: #fff;
border: 1px solid #f0f0f0;
border-radius: 12px;
overflow: hidden;
}
.panel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 18px;
border-bottom: 1px solid #f5f5f5;
}
.panel-title {
font-size: 14px;
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
}
/* 流程步骤 */
.flow-steps {
display: flex;
padding: 20px 24px;
gap: 0;
overflow-x: auto;
}
.flow-step {
flex: 1;
min-width: 150px;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: 0 16px;
}
.flow-step-icon {
width: 36px;
height: 36px;
border-radius: 50%;
background: #f0f0f0;
color: rgba(0, 0, 0, 0.35);
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 700;
flex-shrink: 0;
z-index: 1;
border: 2px solid #e8e8e8;
transition: all 0.2s;
margin-bottom: 10px;
}
.flow-step.active .flow-step-icon {
background: linear-gradient(135deg, #4f46e5, #7c3aed);
color: #fff;
border-color: transparent;
box-shadow: 0 4px 12px rgba(79, 70, 229, 0.35);
}
.flow-step.done .flow-step-icon {
background: #16a34a;
color: #fff;
border-color: transparent;
}
.flow-step-title {
font-size: 13px;
font-weight: 600;
color: rgba(0, 0, 0, 0.75);
margin-bottom: 4px;
}
.flow-step.active .flow-step-title {
color: #4f46e5;
}
.flow-step-desc {
font-size: 12px;
color: rgba(0, 0, 0, 0.4);
line-height: 1.5;
}
.flow-connector {
position: absolute;
top: 17px;
right: -50%;
width: 100%;
height: 2px;
background: #e8e8e8;
z-index: 0;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
padding: 48px 24px;
text-align: center;
}
.empty-icon { font-size: 48px; margin-bottom: 12px; }
.empty-title { font-size: 16px; font-weight: 600; color: rgba(0, 0, 0, 0.7); }
.empty-desc { font-size: 13px; color: rgba(0, 0, 0, 0.4); margin-top: 6px; }
/* 模块列表 */
.module-list {
padding: 12px 16px;
}
.module-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 0;
border-bottom: 1px solid #f9f9f9;
}
.module-item:last-child { border-bottom: none; }
.module-icon {
width: 36px;
height: 36px;
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.module-icon.blue { background: #eff6ff; }
.module-icon.purple { background: #f5f3ff; }
.module-icon.orange { background: #fff7ed; }
.module-icon.green { background: #f0fdf4; }
.module-title {
font-size: 13px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
.module-desc {
font-size: 12px;
color: rgba(0, 0, 0, 0.4);
margin-top: 2px;
}
/* 权益列表 */
.rights-list {
list-style: none;
margin: 0;
padding: 12px 18px;
}
.rights-item {
display: flex;
align-items: center;
gap: 8px;
padding: 7px 0;
font-size: 13px;
color: rgba(0, 0, 0, 0.72);
border-bottom: 1px solid #f9f9f9;
}
.rights-item:last-child { border-bottom: none; }
.rights-check {
width: 18px;
height: 18px;
flex-shrink: 0;
border-radius: 50%;
background: #dcfce7;
color: #16a34a;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 700;
}
</style>