Explorar o código

feat: 在导航栏添加服务热线小组件,重构服务支持页面咨询表单,并集成 ECharts 地图优化

nahida hai 1 mes
pai
achega
e78aa84905

+ 2 - 2
.env.production

@@ -1,5 +1,5 @@
-NEXT_PUBLIC_API_BASE=http://localhost:8040
-NEXT_PUBLIC_BASE_URL=http://localhost:8040
+NEXT_PUBLIC_API_BASE=http://47.107.107.47:8040
+NEXT_PUBLIC_BASE_URL=http://47.107.107.47:8040
 NEXT_PUBLIC_REMOTE_BASE_URL=http://47.107.107.47:8040
 NEXT_PUBLIC_BASE_WS_URL = 'ws://47.107.107.47:8081/ws'
 NEXT_PUBLIC_CLIENT_URL=http://47.107.107.47:8040

+ 1 - 1
next-env.d.ts

@@ -1,6 +1,6 @@
 /// <reference types="next" />
 /// <reference types="next/image-types/global" />
-import "./.next/types/routes.d.ts";
+import "./.next/dev/types/routes.d.ts";
 
 // NOTE: This file should not be edited
 // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

+ 129 - 0
src/app/support/ServiceFormClient.tsx

@@ -0,0 +1,129 @@
+"use client"
+
+import React, { useState } from "react"
+import { Form, Input, Button, App, ConfigProvider } from "antd"
+import { clientPost } from "@/utils/clientRequest"
+
+const { TextArea } = Input
+
+interface ServiceFormValues {
+  name: string
+  phone: string
+  content: string
+}
+
+function ServiceForm() {
+  const [form] = Form.useForm<ServiceFormValues>()
+  const [loading, setLoading] = useState(false)
+  const { message } = App.useApp()
+
+  const onFinish = async (values: ServiceFormValues) => {
+    setLoading(true)
+    try {
+      const res = await clientPost("/webSite/save", values)
+      if (res.code === 200) {
+        message.success("您的咨询已提交,我们会尽快联系您!")
+        form.resetFields()
+      } else {
+        message.error(res.msg || "提交失败,请稍后重试")
+      }
+    } catch (error) {
+      message.error("提交出错,请检查网络连接")
+    } finally {
+      setLoading(false)
+    }
+  }
+
+  return (
+    <div className="bg-white/5 backdrop-blur-sm p-6 rounded-2xl border border-white/10 shadow-2xl">
+      <Form
+        form={form}
+        layout="vertical"
+        onFinish={onFinish}
+        requiredMark={false}
+        autoComplete="off"
+      >
+        <div className="grid grid-cols-2 gap-4">
+          <Form.Item
+            label={<span className="text-gray-300 font-medium text-sm">联系人姓名</span>}
+            name="name"
+            className="mb-4"
+            rules={[{ required: true, message: "请输入您的姓名" }]}
+          >
+            <Input 
+              placeholder="请输入您的姓名" 
+              className="h-10 border-white/20 bg-white/5 text-white placeholder:text-gray-500 text-sm"
+            />
+          </Form.Item>
+
+          <Form.Item
+            label={<span className="text-gray-300 font-medium text-sm">联系电话</span>}
+            name="phone"
+            className="mb-4"
+            rules={[
+              { required: true, message: "请输入您的手机号码" },
+              { pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号码格式" }
+            ]}
+          >
+            <Input 
+              placeholder="请输入您的手机号码" 
+              className="h-10 border-white/20 bg-white/5 text-white placeholder:text-gray-500 text-sm"
+            />
+          </Form.Item>
+        </div>
+
+        <Form.Item
+          label={<span className="text-gray-300 font-medium text-sm">留言备注</span>}
+          name="content"
+          className="mb-4"
+        >
+          <TextArea 
+            placeholder="请输入您的其他需求或备注信息(选填)" 
+            rows={2}
+            className="border-white/20 bg-white/5 text-white placeholder:text-gray-500 hover:border-blue-500 text-sm"
+          />
+        </Form.Item>
+
+        <Form.Item className="mb-0">
+          <Button
+            type="primary"
+            htmlType="submit"
+            loading={loading}
+            className="w-full h-11 bg-orange-500 hover:bg-orange-600 border-none text-base font-bold rounded-xl transition-all duration-300 transform hover:scale-[1.01] active:scale-[0.99] shadow-lg shadow-orange-500/30"
+          >
+            免费咨询报价
+          </Button>
+        </Form.Item>
+      </Form>
+    </div>
+  )
+}
+
+export default function ServiceFormClient() {
+  return (
+    <App>
+      <ConfigProvider
+        theme={{
+          token: {
+            colorTextPlaceholder: "rgba(255, 255, 255, 0.4)",
+            colorBgContainer: "rgba(255, 255, 255, 0.1)",
+            colorBorder: "rgba(255, 255, 255, 0.2)",
+            colorText: "#fff",
+          },
+          components: {
+            Input: {
+              hoverBorderColor: "#3b82f6",
+              activeBorderColor: "#3b82f6",
+              colorBgContainer: "rgba(255, 255, 255, 0.05)",
+            },
+            TextArea: {
+              colorText: "#fff",
+            }
+          },
+        }}
+      >
+        <ServiceForm />
+      </ConfigProvider>
+    </App>
+  )
+}

+ 21 - 15
src/app/support/page.tsx

@@ -2,6 +2,7 @@ import SubTitle from "@/components/subTitle";
 import Image from "next/image";
 import {serverGet} from "@/utils/request";
 import AnimatedSection from "@/components/AnimatedSection";
+import ServiceFormClient from "./ServiceFormClient";
 
 export default async function ServicePage() {
   const res = await serverGet("/webSite/getBasicInfo");
@@ -79,7 +80,7 @@ export default async function ServicePage() {
 
       {/* Service Consultation Section */}
       <AnimatedSection effect="slide" direction="left">
-        <section className="bg-[url('/assets/support/3.png')] bg-cover py-16 px-4 relative overflow-hidden">
+        <section className="bg-[url('/assets/support/3.png')] bg-no-repeat bg-cover py-10 px-4 relative overflow-hidden">
           {/* Background Light Effects */}
           <div className="absolute right-0 top-1/2 transform -translate-y-1/2 w-96 h-96 opacity-30">
             <div
@@ -99,23 +100,28 @@ export default async function ServicePage() {
                   <SubTitle title={"服务咨询"} color={"#fff"}/>
                 </div>
 
-                {/* Contact Information */}
-                <div className="space-y-6">
-                  <div>
-                    <p className="text-gray-300 mb-2">中科盛阳服务热线:</p>
-                    <p className="text-4xl font-bold">{basicInfo.telephone}</p>
-                  </div>
-
-                  <div className="space-y-2">
-                    <p className="text-gray-300">如需自选以下业务,您可以直接拨打相关热线电话:</p>
-                    <p className="text-gray-300">24小时产品售前咨询服务热线:{basicInfo.consultationHotline}</p>
-                  </div>
-                </div>
+                {/* Contact Information & Form */}
+                <ServiceFormClient />
               </div>
 
               {/* Right Side - Light Effects Area */}
-              <div className="hidden lg:block">
-                {/* This space is for the light effects which are handled by the background */}
+              <div className="hidden lg:block space-y-8 pl-12">
+                <div className="text-white">
+                  <p className="text-gray-300 mb-2">中科盛阳服务热线:</p>
+                  <p className="text-5xl font-black text-blue-400 drop-shadow-lg tracking-tight">
+                    {basicInfo.telephone}
+                  </p>
+                </div>
+
+                <div className="space-y-4">
+                  <p className="text-gray-300 text-lg font-medium leading-relaxed">
+                    如需自选以下业务,您可以直接拨打相关热线电话:
+                  </p>
+                  <div className="bg-white/5 backdrop-blur-md p-6 rounded-xl border border-white/10 shadow-inner">
+                    <p className="text-gray-400 text-sm mb-1 uppercase tracking-widest font-bold">24小时产品售前咨询服务热线</p>
+                    <p className="text-2xl font-bold text-white tracking-tighter">{basicInfo.consultationHotline}</p>
+                  </div>
+                </div>
               </div>
             </div>
           </div>

+ 28 - 2
src/components/headerBlock.tsx

@@ -6,7 +6,7 @@ import {Drawer} from "antd"
 import Image from "next/image"
 import Link from "next/link"
 import {usePathname} from "next/navigation"
-import {MenuIcon, X} from "lucide-react"
+import {MenuIcon, PhoneCall, X} from "lucide-react"
 
 const Navigation: React.FC = () => {
   const pathname = usePathname()
@@ -49,7 +49,7 @@ const Navigation: React.FC = () => {
           </div>
 
           {/* 桌面端菜单 */}
-          <div className="hidden sm:flex flex-1 justify-end">
+          <div className="hidden sm:flex flex-1 justify-end items-center">
             <nav className="flex h-18">
               {menuItems.map((item) => (
                 <Link
@@ -71,6 +71,19 @@ const Navigation: React.FC = () => {
                 </Link>
               ))}
             </nav>
+
+            {/* 新增服务热线小组件 */}
+            <div className="hidden lg:flex items-center ml-10 border-l border-gray-100 pl-10 h-10">
+              <div className="flex items-center space-x-3 group">
+                <div className="text-blue-600 bg-blue-50 p-2.5 rounded-full transition-transform duration-300 group-hover:scale-110">
+                  <PhoneCall size={26} strokeWidth={2.5} />
+                </div>
+                <div className="flex flex-col justify-center">
+                  <span className="text-gray-500 text-base font-bold leading-tight tracking-tight">24小时服务热线</span>
+                  <span className="text-blue-600 text-xl font-black leading-tight tracking-tighter">400-666-7001</span>
+                </div>
+              </div>
+            </div>
           </div>
 
           {/* 移动端菜单按钮 */}
@@ -111,6 +124,19 @@ const Navigation: React.FC = () => {
             </Link>
           ))}
         </nav>
+
+        {/* 移动端服务热线 */}
+        <div className="mt-10 pt-8 border-t border-gray-100">
+          <div className="flex items-center space-x-4 bg-blue-50/50 p-4 rounded-xl border border-blue-100/50">
+            <div className="text-blue-600 bg-white p-3 rounded-full shadow-sm">
+              <PhoneCall size={24} strokeWidth={2.5} />
+            </div>
+            <div className="flex flex-col">
+              <span className="text-gray-500 text-xs font-bold leading-tight">24小时服务热线</span>
+              <span className="text-blue-600 text-lg font-black leading-tight tracking-tight">400-666-7001</span>
+            </div>
+          </div>
+        </div>
       </Drawer>
     </header>
   )