diff --git a/public/wx.jpg b/public/wx.jpg new file mode 100644 index 0000000..98dc4ea Binary files /dev/null and b/public/wx.jpg differ diff --git a/src/components/FormSection.vue b/src/components/FormSection.vue new file mode 100644 index 0000000..9a9ac37 --- /dev/null +++ b/src/components/FormSection.vue @@ -0,0 +1,50 @@ + + + + + + + diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue index ede687b..d0ebc56 100644 --- a/src/layouts/AdminLayout.vue +++ b/src/layouts/AdminLayout.vue @@ -184,13 +184,12 @@ const navigateTo = (path) => { - - - - -
- + + + + +
diff --git a/src/main.js b/src/main.js index 56cbbd2..ed262e3 100644 --- a/src/main.js +++ b/src/main.js @@ -8,6 +8,7 @@ import App from './App.vue' // 注册路由 import router from './router' + const app = createApp(App) // 初始化AOS动画 diff --git a/src/router/index.js b/src/router/index.js index 68c94e8..03905c1 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -40,6 +40,7 @@ const routes = [ { path: '', redirect: '/admin/dashboard' }, { path: 'dashboard', name: 'Dashboard', component: () => import('@/views/admin/Dashboard.vue') }, { path: 'projects', name: 'ProjectManage', component: () => import('@/views/admin/Projects.vue') }, + { path: 'projects/create', name: 'ProjectCreate', component: () => import('@/views/admin/ProjectCreate.vue') }, { path: 'users', name: 'UsersManage', component: () => import('@/views/admin/Users.vue') }, { path: 'setting', name: 'SettingManage', component: () => import('@/views/admin/Setting.vue') }, { path: 'orders', name: 'OrdersManage', component: () => import('@/views/admin/Orders.vue') } @@ -69,4 +70,4 @@ router.beforeEach((to, from) => { if (to.meta.requiresAuth && !userStore.user) { return { name: 'Login', query: { redirect: to.fullPath } } } -}) \ No newline at end of file +}) diff --git a/src/style.css b/src/style.css index f1d8c73..d896a30 100644 --- a/src/style.css +++ b/src/style.css @@ -1 +1,2 @@ @import "tailwindcss"; +@import "./styles/theme.css"; diff --git a/src/styles/theme.css b/src/styles/theme.css new file mode 100644 index 0000000..7cff6b1 --- /dev/null +++ b/src/styles/theme.css @@ -0,0 +1,164 @@ +/* 全局主题变量:颜色、阴影、圆角、过渡 */ +:root { + /* 主题色 */ + --color-primary: #e11d48; /* rose-600 */ + --color-primary-soft: #fecaca; + --color-bg-soft: #f9fafb; + --color-border-soft: #e5e7eb; + + /* 中性色 */ + --color-gray-50: #f9fafb; + --color-gray-100: #f3f4f6; + --color-gray-200: #e5e7eb; + --color-gray-700: #374151; + --color-gray-800: #1f2933; + + /* 阴影与圆角 */ + --shadow-soft: 0 10px 30px rgba(15, 23, 42, 0.08); + --shadow-strong: 0 24px 60px rgba(15, 23, 42, 0.16); + --radius-lg: 1rem; + --radius-xl: 1.5rem; + + /* 过渡 */ + --transition-fast: 150ms ease-out; + --transition-normal: 250ms cubic-bezier(0.4, 0, 0.2, 1); + --transition-slow: 400ms cubic-bezier(0.22, 1, 0.36, 1); +} + +.dark { + --color-primary: #fb7185; + --color-primary-soft: rgba(248, 113, 113, 0.12); + --color-bg-soft: #020617; + --color-border-soft: rgba(148, 163, 184, 0.25); + --color-gray-50: #020617; + --color-gray-100: #111827; + --color-gray-200: #1f2937; + --color-gray-700: #9ca3af; + --color-gray-800: #020617; +} + +/* 通用卡片样式 */ +.ui-card { + border-radius: var(--radius-xl); + box-shadow: var(--shadow-soft); + background: radial-gradient(circle at top left, rgba(244, 63, 94, 0.06), transparent 55%), + radial-gradient(circle at bottom right, rgba(59, 130, 246, 0.05), transparent 55%), + #ffffff; + transition: transform var(--transition-normal), box-shadow var(--transition-normal), + background var(--transition-slow); +} + +.dark .ui-card { + background: + radial-gradient(circle at top left, rgba(248, 113, 113, 0.1), transparent 55%), + radial-gradient(circle at bottom right, rgba(56, 189, 248, 0.08), transparent 55%), + linear-gradient(135deg, #020617, #020617); + box-shadow: 0 18px 45px rgba(15, 23, 42, 0.6); +} + +.ui-card-hover:hover { + transform: translateY(-4px) translateZ(0); + box-shadow: var(--shadow-strong); +} + +/* 主按钮统一动效 */ +.ui-btn-primary { + border-radius: 9999px; + background: linear-gradient(135deg, #fb7185, #e11d48); + color: #ffffff; + box-shadow: 0 10px 25px rgba(244, 63, 94, 0.45); + transition: transform var(--transition-fast), box-shadow var(--transition-fast), + filter var(--transition-fast); +} + +.ui-btn-primary:hover { + transform: translateY(-1px) scale(1.02); + box-shadow: 0 18px 40px rgba(244, 63, 94, 0.55); + filter: brightness(1.03); +} + +.ui-btn-primary:active { + transform: translateY(0) scale(0.98); + box-shadow: 0 6px 18px rgba(244, 63, 94, 0.4); +} + +/* 页面路由过渡 */ +.page-fade-slide-enter-active, +.page-fade-slide-leave-active { + transition: opacity var(--transition-normal), transform var(--transition-normal); +} + +.page-fade-slide-enter-from, +.page-fade-slide-leave-to { + opacity: 0; + transform: translateY(8px); +} + +/* 表单焦点与错误状态统一样式 */ +.ui-input, +.ui-select, +.ui-textarea { + border-radius: 0.9rem; + border-width: 1px; + border-color: var(--color-border-soft); + transition: border-color var(--transition-fast), box-shadow var(--transition-fast), + background-color var(--transition-fast), transform var(--transition-fast); +} + +.ui-input:focus, +.ui-select:focus, +.ui-textarea:focus, +.ui-input:focus-visible, +.ui-select:focus-visible, +.ui-textarea:focus-visible { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 0 1px rgba(244, 63, 94, 0.6), 0 18px 45px rgba(15, 23, 42, 0.08); + background-color: rgba(248, 250, 252, 0.9); + transform: translateY(-1px); +} + +.dark .ui-input, +.dark .ui-select, +.dark .ui-textarea { + background-color: rgba(15, 23, 42, 0.95); + border-color: rgba(148, 163, 184, 0.45); +} + +.ui-input-error, +.ui-select-error, +.ui-textarea-error { + border-color: #f97373 !important; + box-shadow: 0 0 0 1px rgba(248, 113, 113, 0.7); +} + +.ui-error-text { + font-size: 0.75rem; + color: #f97373; + margin-top: 0.15rem; + opacity: 0; + transform: translateY(-2px); + transition: opacity var(--transition-fast), transform var(--transition-fast); +} + +.ui-error-text.show { + opacity: 1; + transform: translateY(0); +} + +/* 列表行动效 */ +.ui-row-hover { + transition: background-color var(--transition-fast), transform var(--transition-fast), + box-shadow var(--transition-fast); +} + +.ui-row-hover:hover { + background-color: rgba(248, 250, 252, 0.95); + transform: translateY(-1px); +} + +.dark .ui-row-hover:hover { + background-color: rgba(30, 64, 175, 0.25); +} + + diff --git a/src/views/admin/Orders.vue b/src/views/admin/Orders.vue index 467bd33..e5c6fb9 100644 --- a/src/views/admin/Orders.vue +++ b/src/views/admin/Orders.vue @@ -756,10 +756,9 @@ const batchDelete = () => { - - - + - - + - - @@ -1410,4 +1410,4 @@ const batchDelete = () => { .dark ::-webkit-scrollbar-thumb:hover { background-color: rgba(75, 85, 99, 0.7); } - \ No newline at end of file + diff --git a/src/views/admin/ProjectCreate.vue b/src/views/admin/ProjectCreate.vue new file mode 100644 index 0000000..8694b09 --- /dev/null +++ b/src/views/admin/ProjectCreate.vue @@ -0,0 +1,645 @@ + + + + + diff --git a/src/views/admin/Projects.vue b/src/views/admin/Projects.vue index 3c185d4..ad0b1ba 100644 --- a/src/views/admin/Projects.vue +++ b/src/views/admin/Projects.vue @@ -1,5 +1,6 @@ \ No newline at end of file + diff --git a/src/views/admin/Users.vue b/src/views/admin/Users.vue index 69d2524..6a7b37e 100644 --- a/src/views/admin/Users.vue +++ b/src/views/admin/Users.vue @@ -305,9 +305,10 @@ const reset = () => { \ No newline at end of file + diff --git a/src/views/admin/common/ProjectDetails.vue b/src/views/admin/common/ProjectDetails.vue index ad98610..97ee8fd 100644 --- a/src/views/admin/common/ProjectDetails.vue +++ b/src/views/admin/common/ProjectDetails.vue @@ -256,8 +256,31 @@ const stopPropagation = (e) => { /> - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/views/frontend/Detail.vue b/src/views/frontend/Detail.vue index 68acbb7..e906af0 100644 --- a/src/views/frontend/Detail.vue +++ b/src/views/frontend/Detail.vue @@ -12,7 +12,7 @@ import 'swiper/css/effect-fade' import {homeProjectDetailApi} from "@/api/request/home.js"; import {DollarSign, User, X} from "lucide-vue-next"; import {createCollectionApi, unCollectionApi} from "@/api/request/collection.js"; -import {message, Image} from "ant-design-vue"; +import {message, Image, ImagePreviewGroup} from "ant-design-vue"; import {useUserStore} from "@/stores/user.js"; import {MdPreview} from 'md-editor-v3'; import 'md-editor-v3/lib/style.css'; @@ -359,32 +359,59 @@ const unCollection = () => {
- - -
- -
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
@@ -686,4 +713,4 @@ const unCollection = () => { .cursor-grab:active { cursor: grabbing; } - \ No newline at end of file + diff --git a/src/views/frontend/Home.vue b/src/views/frontend/Home.vue index 1989673..5e45b98 100644 --- a/src/views/frontend/Home.vue +++ b/src/views/frontend/Home.vue @@ -408,49 +408,49 @@ const breakpoints = { -
-
-

- - 合作伙伴 - - -

-

- 我们与以下品牌的合作夥伴一起合作,提供更好的服务体验 -

-
+ + + + + + + + + + + + -
- - -
-
- Partner Logo -
-
- {{ partner.name }} -
-
-
-
-
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +