+
-
{{ project.description }}
-
+
+
{{ project.description || 'NO_DESCRIPTION_AVAILABLE' }}
+
+
-
-
+
+
@@ -51,142 +65,201 @@ const handleEdit = () => {
};
const handleDelete = async () => {
- if (!confirm('确定要删除这个项目吗?')) {
+ if (!confirm('CONFIRM DELETION PROTOCOL?')) {
return;
}
try {
await projectApi.delete(props.project.id);
- // 触发父组件刷新列表
emit('deleted', props.project.id);
} catch (error: any) {
- alert(error.response?.data?.error?.message || '删除失败');
+ alert(error.response?.data?.error?.message || 'DELETION FAILED');
}
};
const formatDate = (dateString: string) => {
const date = new Date(dateString);
- return date.toLocaleDateString('zh-CN');
+ return date.toLocaleDateString('zh-CN', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit'
+ }).replace(/\//g, '.');
};
+.edit-btn:hover {
+ background: var(--primary);
+ color: black;
+ box-shadow: 0 0 10px var(--primary);
+}
+
+.delete-btn {
+ color: var(--accent);
+ border-color: var(--accent);
+}
+
+.delete-btn:hover {
+ background: var(--accent);
+ color: white;
+ box-shadow: 0 0 10px var(--accent);
+}
+
\ No newline at end of file
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
index e9cd9f9..85b2c42 100644
--- a/frontend/src/main.ts
+++ b/frontend/src/main.ts
@@ -2,6 +2,7 @@ import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
+import './styles/variables.css';
const app = createApp(App);
diff --git a/frontend/src/styles/variables.css b/frontend/src/styles/variables.css
new file mode 100644
index 0000000..f20eaac
--- /dev/null
+++ b/frontend/src/styles/variables.css
@@ -0,0 +1,157 @@
+:root {
+ /* --- ACID / NEON PALETTE --- */
+ /* Base Colors - RGB for opacity manipulation */
+ --color-primary-rgb: 204, 255, 0; /* Acid Lime: #CCFF00 */
+ --color-secondary-rgb: 138, 43, 226; /* Electric Violet: #8A2BE2 */
+ --color-accent-rgb: 255, 0, 85; /* Cyber Pink: #FF0055 */
+ --color-info-rgb: 0, 240, 255; /* Cyan: #00F0FF */
+
+ --color-bg-rgb: 5, 5, 5; /* Void Black */
+ --color-surface-rgb: 18, 18, 20; /* Dark Gunmetal */
+ --color-surface-light-rgb: 30, 30, 35;
+
+ --color-text-main: #ffffff;
+ --color-text-muted: #888888;
+
+ /* Actual Color Variables */
+ --primary: rgb(var(--color-primary-rgb));
+ --secondary: rgb(var(--color-secondary-rgb));
+ --accent: rgb(var(--color-accent-rgb));
+ --info: rgb(var(--color-info-rgb));
+
+ --bg-body: rgb(var(--color-bg-rgb));
+ --bg-surface: rgb(var(--color-surface-rgb));
+ --bg-surface-light: rgb(var(--color-surface-light-rgb));
+
+ /* --- BORDERS & GLOWS --- */
+ --border-color: rgba(255, 255, 255, 0.1);
+ --border-color-hover: var(--primary);
+
+ --glow-primary: 0 0 20px rgba(var(--color-primary-rgb), 0.4);
+ --glow-accent: 0 0 20px rgba(var(--color-accent-rgb), 0.4);
+ --glow-text: 0 0 10px rgba(var(--color-primary-rgb), 0.6);
+
+ /* --- TYPOGRAPHY --- */
+ --font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ --font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
+
+ /* --- ANIMATIONS & MICRO-INTERACTIONS --- */
+ --transition-fast: 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ --transition-normal: 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
+ --transition-bounce: 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+
+ --radius-sm: 4px;
+ --radius-md: 12px;
+ --radius-lg: 24px;
+}
+
+/* --- GLOBAL RESET & UTILITIES --- */
+body {
+ background-color: var(--bg-body);
+ color: var(--color-text-main);
+ font-family: var(--font-family-base);
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ overflow-x: hidden;
+}
+
+/* Custom Scrollbar */
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+::-webkit-scrollbar-track {
+ background: var(--bg-body);
+}
+::-webkit-scrollbar-thumb {
+ background: #333;
+ border-radius: 4px;
+}
+::-webkit-scrollbar-thumb:hover {
+ background: var(--primary);
+}
+
+/* Utility Classes */
+.container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0 20px;
+}
+
+.btn {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 12px 24px;
+ font-weight: 700;
+ font-size: 1rem;
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ transition: all var(--transition-normal);
+ border: none;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ position: relative;
+ overflow: hidden;
+}
+
+.btn:active {
+ transform: scale(0.96);
+}
+
+/* Primary Button - Acid Style */
+.btn-primary {
+ background-color: var(--primary);
+ color: #000;
+ box-shadow: 0 4px 0 rgba(255, 255, 255, 0.2) inset, 0 -4px 0 rgba(0,0,0,0.1) inset;
+}
+.btn-primary:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 0 25px rgba(var(--color-primary-rgb), 0.6);
+}
+
+/* Secondary/Ghost Button */
+.btn-ghost {
+ background: transparent;
+ border: 1px solid var(--border-color);
+ color: var(--color-text-main);
+}
+.btn-ghost:hover {
+ border-color: var(--color-text-main);
+ background: rgba(255,255,255,0.05);
+}
+
+/* Input Styles */
+.input-field {
+ width: 100%;
+ padding: 12px 16px;
+ background: var(--bg-surface);
+ border: 1px solid var(--border-color);
+ border-radius: var(--radius-md);
+ color: white;
+ font-size: 1rem;
+ transition: var(--transition-normal);
+ outline: none;
+}
+
+.input-field:focus {
+ border-color: var(--primary);
+ box-shadow: 0 0 0 4px rgba(var(--color-primary-rgb), 0.1);
+ background: var(--bg-surface-light);
+}
+
+/* Card Style */
+.acid-card {
+ background: var(--bg-surface);
+ border: 1px solid var(--border-color);
+ border-radius: var(--radius-md);
+ padding: 20px;
+ transition: var(--transition-normal);
+ position: relative;
+}
+.acid-card:hover {
+ border-color: var(--primary);
+ transform: translateY(-4px);
+ box-shadow: var(--glow-primary);
+ z-index: 1;
+}
diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue
index 945f5db..e8fcfa2 100644
--- a/frontend/src/views/Home.vue
+++ b/frontend/src/views/Home.vue
@@ -2,33 +2,42 @@
-
+
+
+
EXPLORE PROJECTS
+
DEPLOY // SHARE // DOMINATE
+
+
+
-
+
-
+
-
-
-
+
-
+
-
加载中...
+
LOADING_DATA...
-
-
暂无项目
+
+
📦
+
NO PROJECTS FOUND
+
INITIATE FIRST DEPLOYMENT
+
@@ -46,17 +55,17 @@
:disabled="currentPage === 1"
class="page-btn"
>
- 上一页
+ < PREV
- 第 {{ currentPage }} 页 / 共 {{ Math.ceil(total / limit) }} 页
+ PAGE {{ currentPage }} / {{ Math.ceil(total / limit) }}
@@ -169,7 +178,10 @@ onMounted(() => {
+
\ No newline at end of file
diff --git a/frontend/src/views/Login.vue b/frontend/src/views/Login.vue
index 2629dd7..4e88f57 100644
--- a/frontend/src/views/Login.vue
+++ b/frontend/src/views/Login.vue
@@ -1,35 +1,51 @@
-
-
登录
+
+
+
+
🚀
+
欢迎回来
+
SYSTEM ACCESS // GRANTED
+
+
@@ -62,7 +78,7 @@ const handleLogin = async () => {
userStore.setUser(response.user);
router.push('/');
} catch (err: any) {
- error.value = err.response?.data?.error?.message || '登录失败,请重试';
+ error.value = err.response?.data?.error?.message || 'Access Denied';
} finally {
loading.value = false;
}
@@ -75,96 +91,131 @@ const handleLogin = async () => {
display: flex;
align-items: center;
justify-content: center;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- padding: 2rem;
+ background-color: var(--bg-body);
+ position: relative;
+ overflow: hidden;
+}
+
+.glow-bg {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 60vw;
+ height: 60vw;
+ background: radial-gradient(circle, rgba(var(--color-primary-rgb), 0.15) 0%, rgba(0,0,0,0) 70%);
+ filter: blur(80px);
+ z-index: 0;
+ animation: breathe 8s infinite ease-in-out;
+}
+
+@keyframes breathe {
+ 0%, 100% { opacity: 0.5; transform: translate(-50%, -50%) scale(1); }
+ 50% { opacity: 0.8; transform: translate(-50%, -50%) scale(1.1); }
}
.login-container {
- background: white;
- border-radius: 16px;
- padding: 3rem;
width: 100%;
max-width: 400px;
- box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
+ z-index: 1;
+ backdrop-filter: blur(20px);
+ background: rgba(var(--color-surface-rgb), 0.6);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ box-shadow: 0 0 40px rgba(0,0,0,0.5);
}
-.login-container h1 {
+.brand-header {
text-align: center;
- margin-bottom: 2rem;
- color: #333;
- font-size: 2rem;
+ margin-bottom: 2.5rem;
}
-.login-form {
- display: flex;
- flex-direction: column;
- gap: 1.5rem;
+.logo-icon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+ filter: drop-shadow(0 0 10px var(--primary));
}
-.form-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
+h1 {
+ color: var(--color-text-main);
+ font-size: 2rem;
+ font-weight: 800;
+ letter-spacing: -1px;
+ text-transform: uppercase;
+ margin-bottom: 0.5rem;
}
-.form-group label {
- font-weight: 500;
- color: #666;
+.subtitle {
+ color: var(--color-text-muted);
+ font-family: var(--font-family-mono);
+ font-size: 0.75rem;
+ letter-spacing: 2px;
}
-.form-input {
- padding: 0.75rem;
- border: 1px solid #ddd;
- border-radius: 8px;
- font-size: 1rem;
- outline: none;
- transition: border-color 0.2s;
+.form-group {
+ margin-bottom: 1.5rem;
}
-.form-input:focus {
- border-color: #667eea;
+label {
+ display: block;
+ color: var(--primary);
+ font-family: var(--font-family-mono);
+ font-size: 0.75rem;
+ margin-bottom: 0.5rem;
+ letter-spacing: 1px;
}
-.error-message {
- color: #e74c3c;
- font-size: 0.9rem;
- text-align: center;
-}
-
-.submit-btn {
- padding: 0.75rem;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+.input-field {
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(255, 255, 255, 0.1);
color: white;
- border: none;
- border-radius: 8px;
- font-size: 1rem;
- font-weight: 600;
- cursor: pointer;
- transition: transform 0.2s;
+ transition: all 0.3s ease;
}
-.submit-btn:hover:not(:disabled) {
- transform: translateY(-2px);
+.input-field:focus {
+ background: rgba(0, 0, 0, 0.5);
+ border-color: var(--primary);
+ box-shadow: 0 0 15px rgba(var(--color-primary-rgb), 0.2);
}
-.submit-btn:disabled {
- opacity: 0.6;
- cursor: not-allowed;
+.submit-btn {
+ width: 100%;
+ margin-top: 1rem;
+ font-family: var(--font-family-mono);
+ letter-spacing: 2px;
}
.form-footer {
+ margin-top: 2rem;
text-align: center;
- color: #666;
- margin-top: 1rem;
+ font-family: var(--font-family-mono);
+ font-size: 0.75rem;
+ color: var(--color-text-muted);
}
-.form-footer a {
- color: #667eea;
- text-decoration: none;
- font-weight: 500;
+.link {
+ color: var(--color-text-main);
+ margin-left: 0.5rem;
+ text-decoration: underline;
+ text-decoration-color: var(--primary);
+ text-underline-offset: 4px;
}
-.form-footer a:hover {
- text-decoration: underline;
+.link:hover {
+ color: var(--primary);
+ text-decoration-color: transparent;
+ text-shadow: 0 0 8px var(--primary);
+}
+
+.error-message {
+ color: var(--accent);
+ background: rgba(var(--color-accent-rgb), 0.1);
+ border: 1px solid rgba(var(--color-accent-rgb), 0.3);
+ padding: 0.75rem;
+ border-radius: var(--radius-sm);
+ margin-bottom: 1rem;
+ font-size: 0.875rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
}
-
+
\ No newline at end of file
diff --git a/frontend/src/views/Project.vue b/frontend/src/views/Project.vue
index 17bbed5..b05a107 100644
--- a/frontend/src/views/Project.vue
+++ b/frontend/src/views/Project.vue
@@ -7,53 +7,61 @@
sandbox="allow-scripts allow-same-origin allow-forms"
>
-
-
+
-
-
{{ project.title }}
+
-
- 分类:{{ project.category }}
-
-
- 标签:
- {{ tag }}
-
-
-
创建时间:{{ formatDate(project.created_at) }}
+
+
- 编辑
- 删除
+ EDIT_SOURCE
+ TERMINATE
-
附件
+
ATTACHMENTS
-
- {{ attachment.file_name }}
+ 📎
+ {{ attachment.file_name }}
- 下载
+ DOWNLOAD
-
文档
+
DOCUMENTATION
-
- {{ document.title }}
+ 📄
+ {{ document.title }}
+ >
-
加载中...
-
加载失败
+
+
SYSTEM ERROR: LOAD FAILED
-
+
@@ -84,9 +97,11 @@ import { useRoute, useRouter } from 'vue-router';
import { marked } from 'marked';
import Drawer from '@/components/Drawer.vue';
import { projectApi, Project, Document } from '@/api/project';
+import { useUserStore } from '@/store';
const route = useRoute();
const router = useRouter();
+const userStore = useUserStore();
const projectId = parseInt(route.params.id as string);
const project = ref(null);
@@ -96,6 +111,12 @@ const documentVisible = ref(false);
const currentDocument = ref(null);
const previewUrl = ref('');
+const canEdit = computed(() => {
+ if (!project.value) return false;
+ return userStore.isAuthenticated &&
+ (userStore.user?.id === project.value.user_id || userStore.isSuperAdmin);
+});
+
const renderedMarkdown = computed(() => {
if (!currentDocument.value?.content) return '';
return marked(currentDocument.value.content);
@@ -133,7 +154,7 @@ const goHome = () => {
};
const handleDelete = async () => {
- if (!confirm('确定要删除这个项目吗?')) {
+ if (!confirm('WARNING: PERMANENT DELETION PROTOCOL INITIATED. PROCEED?')) {
return;
}
@@ -141,7 +162,7 @@ const handleDelete = async () => {
await projectApi.delete(projectId);
router.push('/');
} catch (error: any) {
- alert(error.response?.data?.error?.message || '删除失败');
+ alert(error.response?.data?.error?.message || 'DELETION FAILED');
}
};
@@ -161,136 +182,194 @@ onMounted(() => {
width: 100vw;
height: 100vh;
overflow: hidden;
+ background-color: var(--bg-body);
}
.preview-iframe {
width: 100%;
height: 100%;
border: none;
+ background: white;
}
.control-buttons {
position: fixed;
right: 0;
top: 50%;
- transform: translateY(-50%) translateX(calc(100% - 20px));
+ transform: translateY(-50%) translateX(calc(100% - 12px));
display: flex;
flex-direction: column;
- gap: 0.75rem;
+ gap: 1rem;
z-index: 999;
- transition: transform 0.3s ease;
- padding-right: 0.5rem;
+ transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+ padding: 1rem 0.5rem 1rem 1rem;
+ background: rgba(0, 0, 0, 0.7);
+ backdrop-filter: blur(10px);
+ border-radius: 20px 0 0 20px;
+ border: 1px solid var(--primary);
+ border-right: none;
}
.control-buttons:hover {
transform: translateY(-50%) translateX(0);
+ background: rgba(0, 0, 0, 0.9);
+ box-shadow: var(--glow-primary);
}
.control-btn {
- width: 44px;
- height: 44px;
+ width: 48px;
+ height: 48px;
border-radius: 50%;
- background: rgba(102, 126, 234, 0.7);
- backdrop-filter: blur(8px);
- color: white;
- border: 1px solid rgba(255, 255, 255, 0.2);
+ background: black;
+ color: var(--primary);
+ border: 1px solid var(--primary);
cursor: pointer;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
- font-size: 1.2rem;
+ font-size: 1.4rem;
display: flex;
align-items: center;
justify-content: center;
- transition: all 0.3s ease;
- opacity: 0.8;
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+ position: relative;
}
.control-btn:hover {
- opacity: 1;
- background: rgba(102, 126, 234, 0.9);
- transform: scale(1.1);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
+ transform: scale(1.15);
+ background: var(--primary);
+ box-shadow: 0 0 20px rgba(var(--color-primary-rgb), 0.5);
+ color: black;
+ z-index: 2;
}
.project-info {
display: flex;
flex-direction: column;
- gap: 1.5rem;
-}
-
-.info-section {
- margin-bottom: 1rem;
+ gap: 2rem;
+ padding-bottom: 2rem;
}
.info-section h3 {
margin: 0 0 0.5rem 0;
- color: #333;
- font-size: 1.5rem;
+ color: white;
+ font-size: 1.8rem;
+ font-weight: 900;
+ letter-spacing: -1px;
+ text-transform: uppercase;
}
.info-section h4 {
- margin: 0 0 0.75rem 0;
- color: #666;
- font-size: 1.1rem;
+ margin: 0 0 1rem 0;
+ color: var(--primary);
+ font-size: 0.85rem;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ font-weight: 600;
+ font-family: var(--font-family-mono);
+ border-bottom: 1px solid var(--border-color);
+ padding-bottom: 0.5rem;
}
.description {
- color: #666;
- line-height: 1.6;
+ color: var(--color-text-muted);
+ line-height: 1.7;
margin: 0.5rem 0;
+ font-size: 1rem;
+}
+
+.meta-section {
+ background: rgba(255,255,255,0.03);
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
}
.info-item {
- margin-bottom: 0.75rem;
- color: #666;
+ display: flex;
+ align-items: center;
+ gap: 1rem;
}
-.info-item strong {
- color: #333;
+.info-item .label {
+ width: 80px;
+ font-weight: 600;
+ color: var(--secondary);
+ font-size: 0.8rem;
+ font-family: var(--font-family-mono);
+ letter-spacing: 1px;
+}
+
+.info-item .value {
+ color: white;
+ font-weight: 500;
+ font-family: var(--font-family-mono);
+}
+
+.category-badge {
+ background: var(--primary);
+ color: black !important;
+ padding: 0.2rem 0.8rem;
+ font-weight: 800 !important;
+ text-transform: uppercase;
+ box-shadow: 0 0 10px rgba(var(--color-primary-rgb), 0.3);
+}
+
+.tags-wrapper {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
}
.tag {
- display: inline-block;
- background: #f0f0f0;
- color: #666;
- padding: 0.25rem 0.5rem;
- border-radius: 4px;
- font-size: 0.85rem;
- margin-right: 0.5rem;
+ background: transparent;
+ border: 1px solid var(--secondary);
+ color: var(--secondary);
+ padding: 0.2rem 0.6rem;
+ font-size: 0.8rem;
+ font-family: var(--font-family-mono);
}
.actions-section {
- display: flex;
- gap: 0.75rem;
- margin-top: 1.5rem;
- padding-top: 1.5rem;
- border-top: 1px solid #eee;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ padding-top: 1rem;
+ border-top: 1px dashed var(--border-color);
}
.action-btn {
- padding: 0.75rem 1.5rem;
- border: none;
- border-radius: 8px;
+ padding: 1rem;
+ border: 1px solid transparent;
cursor: pointer;
- font-weight: 500;
- transition: all 0.2s;
+ font-weight: 800;
+ transition: all var(--transition-fast);
+ text-align: center;
+ text-transform: uppercase;
+ font-family: var(--font-family-mono);
+ letter-spacing: 1px;
}
.edit-btn {
- background: #667eea;
- color: white;
+ background: black;
+ border-color: var(--primary);
+ color: var(--primary);
}
.edit-btn:hover {
- background: #5568d3;
+ background: var(--primary);
+ color: black;
+ box-shadow: var(--glow-primary);
}
.delete-btn {
- background: #e74c3c;
- color: white;
+ background: black;
+ border-color: var(--accent);
+ color: var(--accent);
}
.delete-btn:hover {
- background: #c0392b;
+ background: var(--accent);
+ color: white;
+ box-shadow: var(--glow-accent);
}
.attachment-list,
@@ -298,83 +377,140 @@ onMounted(() => {
list-style: none;
padding: 0;
margin: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 0.8rem;
}
.attachment-item,
.document-item {
- padding: 0.75rem;
- background: #f9f9f9;
- border-radius: 6px;
- margin-bottom: 0.5rem;
+ padding: 1rem;
+ background: rgba(255,255,255,0.03);
+ border: 1px solid var(--border-color);
display: flex;
- justify-content: space-between;
align-items: center;
+ gap: 0.8rem;
+ transition: all var(--transition-fast);
}
.document-item {
cursor: pointer;
- transition: background 0.2s;
}
+.attachment-item:hover,
.document-item:hover {
- background: #f0f0f0;
+ transform: translateX(4px);
+ border-color: var(--primary);
+ background: rgba(0,0,0,0.5);
+ box-shadow: var(--glow-text);
+}
+
+.file-icon, .doc-icon {
+ font-size: 1.2rem;
+ filter: grayscale(100%);
+}
+
+.file-name, .doc-title {
+ flex: 1;
+ font-weight: 500;
+ color: white;
+ font-family: var(--font-family-mono);
+ font-size: 0.9rem;
}
.download-link {
- color: #667eea;
+ color: var(--primary);
+ font-weight: 800;
+ font-size: 0.8rem;
+ padding: 0.4rem 0.8rem;
+ border: 1px solid var(--primary);
+ transition: all var(--transition-fast);
+ text-transform: uppercase;
text-decoration: none;
- font-weight: 500;
}
.download-link:hover {
- text-decoration: underline;
+ background: var(--primary);
+ color: black;
+ box-shadow: var(--glow-primary);
+}
+
+.doc-arrow {
+ color: var(--secondary);
+ font-weight: bold;
+ font-family: monospace;
}
.loading,
.error {
text-align: center;
- padding: 2rem;
- color: #999;
+ padding: 4rem 2rem;
+ color: var(--color-text-muted);
+ font-family: var(--font-family-mono);
+}
+
+.spinner {
+ width: 40px;
+ height: 40px;
+ border: 3px solid rgba(255,255,255,0.1);
+ border-top: 3px solid var(--primary);
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+ margin: 0 auto 1rem;
}
-.document-viewer {
- padding: 1rem 0;
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
}
.markdown-content {
line-height: 1.8;
- color: #333;
+ color: #ccc;
+ padding: 0.5rem;
+ font-family: sans-serif;
}
.markdown-content :deep(h1),
.markdown-content :deep(h2),
.markdown-content :deep(h3) {
- margin-top: 1.5rem;
- margin-bottom: 1rem;
- color: #333;
+ color: white;
+ border-bottom: 1px solid var(--border-color);
+ padding-bottom: 0.5rem;
+ margin-top: 2rem;
+ text-transform: uppercase;
}
-.markdown-content :deep(p) {
- margin-bottom: 1rem;
+.markdown-content :deep(a) {
+ color: var(--primary);
}
.markdown-content :deep(code) {
- background: #f4f4f4;
+ background: #222;
padding: 0.2rem 0.4rem;
- border-radius: 4px;
- font-family: 'Courier New', monospace;
+ border: 1px solid #333;
+ font-family: var(--font-family-mono);
+ color: var(--secondary);
}
.markdown-content :deep(pre) {
- background: #f4f4f4;
- padding: 1rem;
- border-radius: 6px;
+ background: #000;
+ color: #0f0;
+ padding: 1.5rem;
+ border: 1px solid #333;
overflow-x: auto;
+ margin: 1.5rem 0;
+}
+
+.markdown-content :deep(pre code) {
+ background: transparent;
+ color: inherit;
+ padding: 0;
+ border: none;
}
-.markdown-content :deep(ul),
-.markdown-content :deep(ol) {
- margin-left: 1.5rem;
- margin-bottom: 1rem;
+.markdown-content :deep(img) {
+ max-width: 100%;
+ border: 1px solid var(--border-color);
}
-
+
\ No newline at end of file
diff --git a/frontend/src/views/Register.vue b/frontend/src/views/Register.vue
index 02b0f09..f478185 100644
--- a/frontend/src/views/Register.vue
+++ b/frontend/src/views/Register.vue
@@ -1,44 +1,63 @@
-
-
注册
+
+
+
+
✨
+
创建账号
+
INITIATE NEW USER PROTOCOL
+
+
@@ -72,7 +91,7 @@ const handleRegister = async () => {
userStore.setUser(response.user);
router.push('/');
} catch (err: any) {
- error.value = err.response?.data?.error?.message || '注册失败,请重试';
+ error.value = err.response?.data?.error?.message || 'Registration Failed';
} finally {
loading.value = false;
}
@@ -85,96 +104,139 @@ const handleRegister = async () => {
display: flex;
align-items: center;
justify-content: center;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- padding: 2rem;
+ background-color: var(--bg-body);
+ position: relative;
+ overflow: hidden;
+}
+
+.glow-bg {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 70vw;
+ height: 70vw;
+ background: radial-gradient(circle, rgba(var(--color-secondary-rgb), 0.15) 0%, rgba(0,0,0,0) 70%);
+ filter: blur(80px);
+ z-index: 0;
+ animation: pulse 10s infinite ease-in-out;
+}
+
+@keyframes pulse {
+ 0%, 100% { opacity: 0.5; transform: translate(-50%, -50%) scale(1); }
+ 50% { opacity: 0.7; transform: translate(-50%, -50%) scale(1.05); }
}
.register-container {
- background: white;
- border-radius: 16px;
- padding: 3rem;
width: 100%;
- max-width: 400px;
- box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
+ max-width: 440px;
+ z-index: 1;
+ backdrop-filter: blur(20px);
+ background: rgba(var(--color-surface-rgb), 0.6);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ box-shadow: 0 0 40px rgba(0,0,0,0.5);
}
-.register-container h1 {
+.brand-header {
text-align: center;
- margin-bottom: 2rem;
- color: #333;
- font-size: 2rem;
+ margin-bottom: 2.5rem;
}
-.register-form {
- display: flex;
- flex-direction: column;
- gap: 1.5rem;
+.logo-icon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+ filter: drop-shadow(0 0 10px var(--secondary));
}
-.form-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
+h1 {
+ color: var(--color-text-main);
+ font-size: 2rem;
+ font-weight: 800;
+ letter-spacing: -1px;
+ text-transform: uppercase;
+ margin-bottom: 0.5rem;
}
-.form-group label {
- font-weight: 500;
- color: #666;
+.subtitle {
+ color: var(--color-text-muted);
+ font-family: var(--font-family-mono);
+ font-size: 0.75rem;
+ letter-spacing: 2px;
}
-.form-input {
- padding: 0.75rem;
- border: 1px solid #ddd;
- border-radius: 8px;
- font-size: 1rem;
- outline: none;
- transition: border-color 0.2s;
+.form-group {
+ margin-bottom: 1.5rem;
}
-.form-input:focus {
- border-color: #667eea;
+label {
+ display: block;
+ color: var(--secondary);
+ font-family: var(--font-family-mono);
+ font-size: 0.75rem;
+ margin-bottom: 0.5rem;
+ letter-spacing: 1px;
}
-.error-message {
- color: #e74c3c;
- font-size: 0.9rem;
- text-align: center;
+.input-field {
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ color: white;
+ transition: all 0.3s ease;
+}
+
+.input-field:focus {
+ background: rgba(0, 0, 0, 0.5);
+ border-color: var(--secondary);
+ box-shadow: 0 0 15px rgba(var(--color-secondary-rgb), 0.2);
}
.submit-btn {
- padding: 0.75rem;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ width: 100%;
+ margin-top: 1rem;
+ font-family: var(--font-family-mono);
+ letter-spacing: 2px;
+ background-color: var(--secondary);
color: white;
- border: none;
- border-radius: 8px;
- font-size: 1rem;
- font-weight: 600;
- cursor: pointer;
- transition: transform 0.2s;
}
.submit-btn:hover:not(:disabled) {
- transform: translateY(-2px);
-}
-
-.submit-btn:disabled {
- opacity: 0.6;
- cursor: not-allowed;
+ background-color: var(--secondary);
+ box-shadow: 0 0 25px rgba(var(--color-secondary-rgb), 0.6);
+ color: white;
}
.form-footer {
+ margin-top: 2rem;
text-align: center;
- color: #666;
- margin-top: 1rem;
+ font-family: var(--font-family-mono);
+ font-size: 0.75rem;
+ color: var(--color-text-muted);
}
-.form-footer a {
- color: #667eea;
- text-decoration: none;
- font-weight: 500;
+.link {
+ color: var(--color-text-main);
+ margin-left: 0.5rem;
+ text-decoration: underline;
+ text-decoration-color: var(--secondary);
+ text-underline-offset: 4px;
}
-.form-footer a:hover {
- text-decoration: underline;
+.link:hover {
+ color: var(--secondary);
+ text-decoration-color: transparent;
+ text-shadow: 0 0 8px var(--secondary);
+}
+
+.error-message {
+ color: var(--accent);
+ background: rgba(var(--color-accent-rgb), 0.1);
+ border: 1px solid rgba(var(--color-accent-rgb), 0.3);
+ padding: 0.75rem;
+ border-radius: var(--radius-sm);
+ margin-bottom: 1rem;
+ font-size: 0.875rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
}
-
+
\ No newline at end of file
diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue
index cfeb20a..381b8d4 100644
--- a/frontend/src/views/Settings.vue
+++ b/frontend/src/views/Settings.vue
@@ -2,37 +2,57 @@
-
系统设置
-
加载中...
-
{{ error }}
-
-
-
-
允许注册
-
控制是否允许新用户注册
+
+
+
+
+
LOADING CONFIGURATION...
+
+
+
+
+
+
+
-
-
-
-
-
允许上传
-
控制是否允许用户上传网页
+
+
+
+
OPEN REGISTRATION
+
ALLOW NEW USERS TO GENERATE IDENTITIES
+
+
+
+
+
+
+
UPLOAD PERMISSION
+
ENABLE DEPLOYMENT FOR STANDARD USERS
+
+
-
@@ -60,13 +80,12 @@ const loadSettings = async () => {
settings[setting.key] = setting.value;
});
} catch (err: any) {
- const errorMessage = err.response?.data?.error?.message || '加载设置失败';
+ const errorMessage = err.response?.data?.error?.message || 'LOAD FAILED';
error.value = errorMessage;
- // 如果是权限错误,显示友好提示
if (err.response?.status === 403) {
- error.value = '您没有权限访问设置页面';
+ error.value = 'ACCESS DENIED';
} else if (err.response?.status === 401) {
- error.value = '请先登录';
+ error.value = 'AUTHENTICATION REQUIRED';
}
} finally {
loading.value = false;
@@ -81,8 +100,7 @@ const updateSetting = async (key: string, event: Event) => {
await settingApi.update(key, value);
settings[key] = value;
} catch (err: any) {
- error.value = err.response?.data?.error?.message || '更新设置失败';
- // 恢复原值
+ error.value = err.response?.data?.error?.message || 'UPDATE FAILED';
target.checked = settings[key] === 'true';
}
};
@@ -95,7 +113,7 @@ onMounted(() => {
+
\ No newline at end of file
diff --git a/frontend/src/views/Upload.vue b/frontend/src/views/Upload.vue
index 090eec6..306a7ba 100644
--- a/frontend/src/views/Upload.vue
+++ b/frontend/src/views/Upload.vue
@@ -2,124 +2,162 @@
-
{{ isEditMode ? '编辑项目' : '上传项目' }}
-