From 38fb8417dc4a2ea90e26856ec9eaa001b78f79b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Sat, 5 Jul 2025 12:29:09 +0800 Subject: [PATCH] =?UTF-8?q?next=E7=89=88=E6=9C=AC=E7=9A=84pc=E7=AB=AF?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 + .idea/inspectionProfiles/Project_Default.xml | 6 + .idea/modules.xml | 8 + .idea/next-10398.iml | 12 + .idea/vcs.xml | 6 + next.config.ts | 63 ++++- src/api/bszx/bszxBm/index.ts | 4 +- src/api/cms/cmsArticle/index.ts | 10 +- src/api/index.ts | 68 +++-- src/api/system/parameter/index.ts | 2 +- src/app/globals.css | 246 +++++++++++++++++-- src/app/layout.tsx | 41 ++-- src/app/page.tsx | 117 ++------- src/config/setting.ts | 59 ++--- src/utils/request.ts | 4 +- tsconfig.json | 1 + 16 files changed, 464 insertions(+), 191 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/next-10398.iml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..1a4017e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/next-10398.iml b/.idea/next-10398.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/next-10398.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index e9ffa30..1617a52 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,68 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + images: { + remotePatterns: [ + // OSS 图片域名 + { + protocol: 'https', + hostname: 'oss.wsdns.cn', + port: '', + pathname: '/**', + }, + { + protocol: 'http', + hostname: 'oss.wsdns.cn', + port: '', + pathname: '/**', + }, + // API 服务器图片 + { + protocol: 'https', + hostname: 'cms-api.websoft.top', + port: '', + pathname: '/**', + }, + { + protocol: 'http', + hostname: 'cms-api.websoft.top', + port: '', + pathname: '/**', + }, + // 常见的图片 CDN 域名 + { + protocol: 'https', + hostname: '*.aliyuncs.com', + port: '', + pathname: '/**', + }, + { + protocol: 'https', + hostname: '*.qiniudn.com', + port: '', + pathname: '/**', + }, + { + protocol: 'https', + hostname: '*.qiniu.com', + port: '', + pathname: '/**', + }, + // 本地开发 + { + protocol: 'http', + hostname: 'localhost', + port: '', + pathname: '/**', + }, + { + protocol: 'https', + hostname: 'localhost', + port: '', + pathname: '/**', + }, + ], + }, }; export default nextConfig; diff --git a/src/api/bszx/bszxBm/index.ts b/src/api/bszx/bszxBm/index.ts index f1cb134..2c25bfd 100644 --- a/src/api/bszx/bszxBm/index.ts +++ b/src/api/bszx/bszxBm/index.ts @@ -10,7 +10,7 @@ export async function pageBszxBm(params: BszxBmParam) { const res = await request.get>>( MODULES_API_URL + '/bszx/bszx-bm/page', { - params: params as Record + params } ); if (res.data.code === 0) { @@ -26,7 +26,7 @@ export async function listBszxBm(params?: BszxBmParam) { const res = await request.get>( MODULES_API_URL + '/bszx/bszx-bm', { - params: params as Record + params } ); if (res.data.code === 0 && res.data.data) { diff --git a/src/api/cms/cmsArticle/index.ts b/src/api/cms/cmsArticle/index.ts index f8feab8..63974a2 100644 --- a/src/api/cms/cmsArticle/index.ts +++ b/src/api/cms/cmsArticle/index.ts @@ -7,11 +7,11 @@ import {MODULES_API_URL} from '@/config/setting'; * 分页查询文章 */ export async function pageCmsArticle(params: CmsArticleParam) { - const res = await request.get>>( - MODULES_API_URL + '/cms/cms-article/page', - { - params - } + const res = await request.get>( + MODULES_API_URL + '/cms/cms-article/page', + { + params + } ); if (res.data.code === 0) { return res.data.data; diff --git a/src/api/index.ts b/src/api/index.ts index bb82dc6..85c01ed 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -3,38 +3,30 @@ * 基于 Fetch API 的现代化请求库 */ +import { APP_CONFIG } from '@/config/setting'; + // ==================== 基础类型定义 ==================== /** * 接口统一返回结果 */ -export interface ApiResult { +export interface ApiResult { // 状态码 code: number; // 状态信息 message?: string; // 返回数据 data?: T; - // 是否成功 - success?: boolean; - // 时间戳 - timestamp?: string; } /** * 分页查询统一结果 */ -export interface PageResult { +export interface PageResult { // 返回数据 list: T[]; // 总数量 count: number; - // 当前页 - page?: number; - // 每页数量 - limit?: number; - // 总页数 - totalPages?: number; } /** @@ -49,7 +41,7 @@ export interface PageParam { sort?: string; sortNum?: string; // 排序方式, asc升序, desc降序 - order?: 'asc' | 'desc'; + order?: string; // 租户ID tenantId?: number; // 企业ID @@ -57,7 +49,7 @@ export interface PageParam { // 商户ID merchantId?: number; merchantName?: string; - categoryIds?: number[]; + categoryIds?: any; // 商品分类 categoryId?: number; categoryName?: string; @@ -217,6 +209,26 @@ export class ApiClient { }; } + /** + * 为请求数据添加租户ID + */ + private addTenantIdToData(data?: unknown): unknown { + // 如果数据为空或不是对象,直接返回 + if (!data || typeof data !== 'object' || data instanceof FormData) { + return data; + } + + // 如果是普通对象,添加租户ID + if (data.constructor === Object || Array.isArray(data)) { + return { + ...data as Record + }; + } + + // 其他情况直接返回 + return data; + } + /** * 核心请求方法 */ @@ -251,6 +263,9 @@ export class ApiClient { } } + // 添加租户ID头 + (requestConfig.headers as Record)['TenantId'] = APP_CONFIG.TENANT_ID; + // 添加请求体 if (data && ['POST', 'PUT', 'PATCH'].includes(method)) { if (data instanceof FormData) { @@ -315,11 +330,16 @@ export class ApiClient { * GET 请求 */ async get(url: string, params?: Record, config?: RequestConfig): Promise> { - if (params) { + // 合并租户ID到查询参数 + const mergedParams: Record = { + ...params + }; + + if (mergedParams) { const searchParams = new URLSearchParams(); - Object.keys(params).forEach((key) => { - if (params[key] !== undefined && params[key] !== null) { - searchParams.append(key, String(params[key])); + Object.keys(mergedParams).forEach((key) => { + if (mergedParams[key] !== undefined && mergedParams[key] !== null) { + searchParams.append(key, String(mergedParams[key])); } }); url += `?${searchParams.toString()}`; @@ -331,14 +351,18 @@ export class ApiClient { * POST 请求 */ async post(url: string, data?: unknown, config?: RequestConfig): Promise> { - return this.request(url, 'POST', data, config); + // 为对象数据添加租户ID + const mergedData = this.addTenantIdToData(data); + return this.request(url, 'POST', mergedData, config); } /** * PUT 请求 */ async put(url: string, data?: unknown, config?: RequestConfig): Promise> { - return this.request(url, 'PUT', data, config); + // 为对象数据添加租户ID + const mergedData = this.addTenantIdToData(data); + return this.request(url, 'PUT', mergedData, config); } /** @@ -352,7 +376,9 @@ export class ApiClient { * PATCH 请求 */ async patch(url: string, data?: unknown, config?: RequestConfig): Promise> { - return this.request(url, 'PATCH', data, config); + // 为对象数据添加租户ID + const mergedData = this.addTenantIdToData(data); + return this.request(url, 'PATCH', mergedData, config); } } diff --git a/src/api/system/parameter/index.ts b/src/api/system/parameter/index.ts index 54ee4b1..158338f 100644 --- a/src/api/system/parameter/index.ts +++ b/src/api/system/parameter/index.ts @@ -10,7 +10,7 @@ export async function pageParameter(params: ParameterParam) { const res = await request.get>>( SERVER_API_URL + '/system/parameter/page', { - params: params as Record + params } ); if (res.data.code === 0) { diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..b49f4f5 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,240 @@ -@import "tailwindcss"; +@tailwind base; +@tailwind components; +@tailwind utilities; +/* 企业官网全局样式 */ :root { - --background: #ffffff; - --foreground: #171717; + --primary-color: #2563eb; + --primary-dark: #1d4ed8; + --secondary-color: #64748b; + --accent-color: #f59e0b; + --text-primary: #1f2937; + --text-secondary: #6b7280; + --text-light: #9ca3af; + --bg-primary: #ffffff; + --bg-secondary: #f8fafc; + --bg-dark: #1f2937; + --border-color: #e5e7eb; } -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); +* { + box-sizing: border-box; + padding: 0; + margin: 0; } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +html, +body { + max-width: 100vw; + overflow-x: hidden; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + line-height: 1.6; + color: var(--text-primary); } body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + background-color: var(--bg-primary); +} + +a { + color: inherit; + text-decoration: none; + transition: color 0.3s ease; +} + +a:hover { + color: var(--primary-color); +} + +/* 通用组件样式 */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.btn { + @apply inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-lg transition-all duration-300 cursor-pointer; +} + +.btn-primary { + @apply bg-blue-600 text-white hover:bg-blue-700 focus:ring-4 focus:ring-blue-200; +} + +.btn-secondary { + @apply bg-gray-100 text-gray-900 hover:bg-gray-200 focus:ring-4 focus:ring-gray-100; +} + +.btn-outline { + @apply border-2 border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white focus:ring-4 focus:ring-blue-200; +} + +.card { + @apply bg-white rounded-lg shadow-md overflow-hidden transition-shadow duration-300 hover:shadow-lg; +} + +.section-padding { + @apply py-16 lg:py-24; +} + +.section-title { + @apply text-3xl lg:text-4xl font-bold text-center mb-4; +} + +.section-subtitle { + @apply text-lg text-gray-600 text-center mb-12 max-w-2xl mx-auto; +} + +/* 导航栏样式 */ +.navbar { + @apply bg-white shadow-sm border-b border-gray-100 sticky top-0 z-50; +} + +.navbar-brand { + @apply text-2xl font-bold text-blue-600; +} + +.navbar-nav { + @apply flex items-center space-x-8; +} + +.navbar-link { + @apply text-gray-700 hover:text-blue-600 font-medium transition-colors duration-300; +} + +.navbar-link.active { + @apply text-blue-600; +} + +/* 英雄区域样式 */ +.hero { + @apply bg-gradient-to-br from-blue-50 to-indigo-100 py-20 lg:py-32; +} + +.hero-title { + @apply text-4xl lg:text-6xl font-bold text-gray-900 mb-6; +} + +.hero-subtitle { + @apply text-xl lg:text-2xl text-gray-600 mb-8 max-w-3xl; +} + +/* 特色区域样式 */ +.feature-card { + @apply text-center p-8 rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow duration-300; +} + +.feature-icon { + @apply w-16 h-16 mx-auto mb-6 text-blue-600; +} + +.feature-title { + @apply text-xl font-semibold mb-4; +} + +.feature-description { + @apply text-gray-600; +} + +/* 文章卡片样式 */ +.article-card { + @apply bg-white rounded-lg shadow-sm overflow-hidden hover:shadow-md transition-shadow duration-300; +} + +.article-image { + @apply w-full h-48 object-cover; +} + +.article-content { + @apply p-6; +} + +.article-category { + @apply inline-block px-3 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full mb-3; +} + +.article-title { + @apply text-xl font-semibold mb-3 hover:text-blue-600 transition-colors duration-300; +} + +.article-excerpt { + @apply text-gray-600 mb-4 line-clamp-3; +} + +.article-meta { + @apply flex items-center justify-between text-sm text-gray-500; +} + +/* 页脚样式 */ +.footer { + @apply bg-gray-900 text-white py-12; +} + +.footer-section { + @apply mb-8 lg:mb-0; +} + +.footer-title { + @apply text-lg font-semibold mb-4; +} + +.footer-link { + @apply text-gray-300 hover:text-white transition-colors duration-300; +} + +/* 响应式样式 */ +@media (max-width: 768px) { + .container { + padding: 0 1rem; + } + + .hero-title { + @apply text-3xl lg:text-4xl; + } + + .hero-subtitle { + @apply text-lg; + } + + .section-title { + @apply text-2xl lg:text-3xl; + } +} + +/* 动画效果 */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.fade-in-up { + animation: fadeInUp 0.6s ease-out; +} + +/* 加载动画 */ +.loading { + @apply inline-block w-6 h-6 border-2 border-gray-300 border-t-blue-600 rounded-full animate-spin; +} + +/* 文本截断 */ +.line-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..c6bd764 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,20 +1,25 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; - -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); +import Header from "@/components/layout/Header"; +import Footer from "@/components/layout/Footer"; export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "企业官网 - 专业的企业解决方案服务商", + description: "我们致力于为企业提供全方位的数字化转型服务,以创新技术驱动业务增长,助力企业在数字时代取得成功。", + keywords: "企业官网,数字化转型,企业服务,解决方案,技术服务", + authors: [{ name: "企业官网" }], + robots: "index, follow", + openGraph: { + title: "企业官网 - 专业的企业解决方案服务商", + description: "我们致力于为企业提供全方位的数字化转型服务,以创新技术驱动业务增长,助力企业在数字时代取得成功。", + type: "website", + locale: "zh_CN", + }, +}; + +export const viewport = { + width: 'device-width', + initialScale: 1, }; export default function RootLayout({ @@ -23,11 +28,11 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - - {children} + + +
+
{children}
+