diff --git a/agent/application/states/conversation.py b/agent/application/states/conversation.py index 19fa38f..89f2999 100644 --- a/agent/application/states/conversation.py +++ b/agent/application/states/conversation.py @@ -2,7 +2,7 @@ """ 会话状态 """ -from datetime import datetime +from datetime import date as Date, datetime from typing import AsyncGenerator from pydantic_ai import DeferredToolRequests, DeferredToolResults, ToolApproved @@ -388,10 +388,7 @@ class ConversationState(rx.State): # 运行并流式输出事件 stream_events = run_stream_events( - deps=Deps( - account_id=conversation.workflow.deps["account_id"], - connection_pool=connection_pool, - ), + user_id=self.user_id, user_prompt=user_prompt, message_history=message_history, usage=usage, @@ -696,10 +693,17 @@ class ConversationState(rx.State): match type: # 预定航班 case WorkflowType.BOOK_FLIGHT: - from application.workshop.book_flight import deps + from application.workshop.book_flight import Deps # 初始化预定航班工作流 - workflow = Workflow(type=type, deps=deps) + workflow = Workflow( + type=type, + deps=Deps( + date=Date(2025, 1, 10), + origin_airport_code="SFO", + destination_airport_code="ANC", + ), + ) # 设置用户提示词 self.set_user_prompt( f"帮我查询并预定在 {workflow.deps.date.strftime('%Y-%m-%d')} 从 {workflow.deps.origin_airport_code} 到 {workflow.deps.destination_airport_code} 的航班" @@ -707,8 +711,10 @@ class ConversationState(rx.State): # 银行客户服务 case WorkflowType.BANK_CUSTOMER_SERVICE: + from application.workshop.bank_customer_service import Deps + # 初始化银行客户服务工作流 - workflow = Workflow(type=type, deps={"account_id": self.user_id}) + workflow = Workflow(type=type) # 设置用户提示词 self.set_user_prompt(f"帮我查询账户余额") diff --git a/agent/application/workshop/bank_customer_service.py b/agent/application/workshop/bank_customer_service.py index f055df1..afb7cb1 100644 --- a/agent/application/workshop/bank_customer_service.py +++ b/agent/application/workshop/bank_customer_service.py @@ -2,9 +2,8 @@ """ 银行客户服务 """ -from typing import Any, AsyncGenerator +from typing import AsyncGenerator -from asyncpg import Pool from pydantic import BaseModel, Field from pydantic_ai import ( Agent, @@ -18,6 +17,7 @@ from pydantic_ai import ( from pydantic_ai.messages import AgentStreamEvent from pydantic_ai.run import AgentRunResultEvent +from application.workshop.database import connection_pool from application.workshop.models import ( DEEPSEEK_V4_FLASH_CHAT_MODEL, DEEPSEEK_V4_FLASH_CHAT_MODEL_SETTINGS, @@ -29,48 +29,51 @@ class Deps(BaseModel): 依赖类 """ - model_config = {"arbitrary_types_allowed": True} # 允许任意类型 - - account_id: str = Field(..., description="账户唯一标识") - connection_pool: Pool = Field(..., description="连接池") + user_id: str = Field(..., description="用户唯一标识") -# 账户上下文能力 -account_context = Capability[Deps]( - id="account-context", - description="提供账户信息,用于客服应答", - defer_loading=False, # 延迟加载置为否,立即加载 +# 用户上下文能力 +user_context = Capability[Deps]( + id="user-context", + description="提供用户信息,用于客服应答", + defer_loading=False, # 延迟加载置为否(立即加载) ) -@account_context.instructions -async def query_account_name(ctx: RunContext[Deps]) -> str: +@user_context.instructions +async def query_user_name(ctx: RunContext[Deps]) -> str: """ - 查询账户户名 + 查询用户姓名 """ - async with ctx.deps.connection_pool.acquire() as conn: - account_name = await conn.fetchval( - "SELECT account_name FROM bank_customer_service WHERE account_id = $1", - ctx.deps.account_id, + if connection_pool is None: + return "数据库连接池未初始化" + + async with connection_pool.acquire() as conn: + user_name = await conn.fetchval( + "SELECT user_name FROM bank_customer_service WHERE user_id = $1", + ctx.deps.user_id, ) - if account_name is None: - return "该账户不存在" - return f"该账户户名是 {account_name!r}" + if user_name is None: + return "该用户不存在" + return f"用户姓名是 {user_name!r}" -@account_context.tool(name="查询账户余额") -async def query_account_balance(ctx: RunContext[Deps]) -> str: +@user_context.tool(name="查询账户余额") +async def query_balance(ctx: RunContext[Deps]) -> str: """ 查询账户余额 """ - async with ctx.deps.connection_pool.acquire() as conn: + if connection_pool is None: + return "数据库连接池未初始化" + + async with connection_pool.acquire() as conn: account_balance = await conn.fetchval( - "SELECT account_balance FROM bank_customer_service WHERE account_id = $1", - ctx.deps.account_id, + "SELECT account_balance FROM bank_customer_service WHERE user_id = $1", + ctx.deps.user_id, ) if account_balance is None: - return "该账户不存在" - return f"该账户余额: {account_balance:.2f}" + return "该用户不存在" + return f"该用户的账户余额: {account_balance:.2f}" # 智能体 @@ -80,7 +83,7 @@ agent = Agent[Deps, str]( deps_type=Deps, output_type=str, # 若输出类型为 str,则智能体输出结果时不进行输出类型校验。若定义输出类型,需考虑处理相应事件 instructions="你是我方银行的客服智能体,为客户提供客服应答。", # 优先使用 instructions - capabilities=[account_context], + capabilities=[user_context], ) """ @@ -131,7 +134,7 @@ PartEndEvent(index=0, part=TextPart(content='您好,刘弼仁先生。您账 async def run_stream_events( - deps: Any, + user_id: str, user_prompt: str | None, message_history: list[ModelMessage], usage: RunUsage, @@ -141,17 +144,13 @@ async def run_stream_events( """ 运行并流式输出事件 """ - if not isinstance(deps, Deps): - deps = Deps.model_validate(deps) - async with agent.run_stream_events( user_prompt=user_prompt, - deps=deps, + deps=Deps(user_id=user_id), message_history=message_history, usage=usage, usage_limits=usage_limits, deferred_tool_results=deferred_tool_results, ) as events: async for event in events: - print(event) yield event diff --git a/agent/application/workshop/book_flight.py b/agent/application/workshop/book_flight.py index 4b97939..5aa7eda 100644 --- a/agent/application/workshop/book_flight.py +++ b/agent/application/workshop/book_flight.py @@ -2,7 +2,7 @@ """ 预定航班工作流(范式) """ -import datetime +from datetime import date as Date from typing import Any, AsyncGenerator, cast from pydantic import BaseModel, Field, field_validator @@ -39,7 +39,7 @@ class Flight(BaseModel): """ number: str = Field(..., description="航班号") - date: datetime.date = Field(..., description="日期") + date: Date = Field(..., description="日期") origin_airport_code: str = Field(..., description="出发机场代码") destination_airport_code: str = Field(..., description="到达机场代码") airfare: int = Field(..., description="机票价格") @@ -62,7 +62,7 @@ class Deps(BaseModel): 依赖类 """ - date: datetime.date = Field(..., description="日期") + date: Date = Field(..., description="日期") origin_airport_code: str = Field(..., description="出发机场代码") destination_airport_code: str = Field(..., description="到达机场代码") searched_flights: list[Flight] | None = Field( @@ -277,13 +277,6 @@ async def validate_output( return output -deps = Deps( - date=datetime.date(2025, 1, 10), - origin_airport_code="SFO", - destination_airport_code="ANC", -) - - async def run_stream_events( deps: Any, user_prompt: str | None, diff --git a/agent/application/workshop/research.py b/agent/application/workshop/research.py index aa486b8..d6db4ae 100644 --- a/agent/application/workshop/research.py +++ b/agent/application/workshop/research.py @@ -3,15 +3,27 @@ 研究 """ from typing import AsyncGenerator - +from asyncpg import Pool import httpx -from pydantic import BaseModel, Field -from pydantic_ai import Agent, ModelMessage, RunContext, RunUsage +from pydantic import BaseModel, Field, cast +from pydantic_ai import Agent, ModelMessage, RunContext +from pydantic_ai.usage import RunUsage from pydantic_ai.messages import AgentStreamEvent from pydantic_ai.run import AgentRunResultEvent from pydantic_ai.toolsets import FunctionToolset +from sqlmodel import REAL from application.workshop.models import DEEPSEEK_V4_FLASH_RESPONSE_MODEL +from application.workshop.database import connection_pool + + +class Deps(BaseModel): + """ + 依赖类 + """ + + model_config = {"arbitrary_types_allowed": True} # 允许任意类型 + connection_pool: Pool = Field(..., description="连接池") class Args(BaseModel): @@ -22,11 +34,11 @@ class Args(BaseModel): bocha_web_search = FunctionToolset() -@bocha_web_search.tool_plain() # 普通工具:不使用运行上下文 -async def web_search(args: Args) -> str: +@bocha_web_search.tool(name="联网搜索") # type: ignore +async def web_search(ctx: RunContext[Deps], args: Args) -> str: """ 联网搜索工具: - 用于查询互联网实时信息、新闻、政策、行业报告、企业公告、最新数据。 + 用于查询互联网实时信息、新闻、政策法规、行业报告、企业公告、最新数据。 适合查询模型静态知识库不存在的外部网页信息。 回答时必须标注引用来源URL,禁止编造链接。 不要用于简单常识、数学计算、代码编写等无需联网的任务。 @@ -89,17 +101,66 @@ async def web_search(args: Args) -> str: instruction = """ 你是研究助手,可调用联网搜索工具。 -1. 事实、时效、外部资料类问题必须搜索;静态常识可直接回答,支持多次检索、改写query。 -2. 优先采用一手资料、官方权威信源,慎用自媒体与转载内容。 -3. 所有事实描述必须标注来源链接,引用格式:`[参考{序号}] {URL}`,序号匹配搜索结果编号。 -4. 严格区分:【事实】来自网页原文;【推论】基于事实推导;资料不足时标注【推测】,不可当作事实。 -5. 严禁编造链接和事实;证据不足直接说明,不要强行下结论。 -6. 组织回答:先陈列证据,再总结结论,结论不能超出资料支撑范围。 + +## 一、联网判断 +需要联网:时效类信息、新闻、声明公告、政策法规、最新数据,以及模型静态知识库无法可靠回答的问题。 +无需联网:基础常识、数学计算、代码编写与解释、用户已提供完整材料的分析任务、无时间依赖的静态问题。 + +【搜索硬约束】 +1. 最多**2轮联网搜索**,严禁发起第3轮;优先在第一轮构造高信息密度的Query尝试获取完整答案,非必要不执行第二轮搜索。 +2. 发起新一轮搜索前,必须评估已获取的搜索摘要,现有信息足以回答问题则立即停止调用工具。 +3. 禁止仅改写同义词、做语义几乎等价的重复搜索;若存在局部信息缺失,优先从已有结果中提取可用内容,不要直接发起新搜索。 + +## 二、时间与Query规则 +时效判断严格以运行时传入的当前日期、年份、时区为准,禁止依靠模型内置记忆猜测时间。 +- 用户未指定年份:**禁止自行向搜索Query中追加年份**。 +- 用户明确给出年份:搜索Query必须完整保留用户指定的年份。 + +## 三、搜索效率 +默认只执行1次真实联网搜索;拿到搜索结果后评估证据,满足以下任意条件,必须停止搜索: +- 现有信息足以作答;官方一手资料已给出答案;多个可靠来源结论一致;继续搜索仅起到重复确认的作用。 + +❌禁止以“再次确认、查找更多来源、补充更多资料”等理由发起额外搜索。 + +✅仅在以下4种场景,才允许执行第2轮搜索: +①第一轮无有效搜索结果;②回答问题必需的关键事实完全缺失;③权威信源之间事实存在明显冲突;④第一轮搜索结果严重偏题。 + +第二轮搜索必须瞄准明确的信息缺口,禁止全盘复刻上一轮查询;**不允许单次回合同时生成多条搜索请求**。 +严格执行流程:执行搜索 → 阅读解析结果 → 判断信息缺口 → 再决定是否发起二次搜索。 + +## 四、信源优先级 +1级(最高):官网、官方文档、官方公告、一手原始资料 +2级:权威媒体、专业机构、科研机构 +3级:其他可信赖网页 + +官方资料已经可以完整回答问题时,无需再搜索其他来源做重复验证。 +自媒体、论坛、转载内容,不可作为重大事实的唯一证据。 + +## 五、最新内容校验 +查询“最新”类问题,不可仅凭网页排序判断时效性;必须核对资料的**发布时间、版本时间,结合运行时提供的当前日期综合判断**。 +当存在多份结果时,优先选用发布时间更近、信源等级更高的资料。 + +## 六、事实规范 +- 【事实】:搜索返回资料原文直接支持的内容 +- 【推论】:基于已确认事实做合理推导 +- 【推测】:证据不足前提下的主观判断 + +严禁编造URL、日期、新闻事件、数据、官方声明等任何信息;证据不足时直接如实说明,不得强行得出结论。 + +## 七、引用规范 +引用编号区分搜索轮次:S1‑1、S1‑2 代表第1轮搜索结果;S2‑1、S2‑2 代表第2轮搜索结果。 +只引用回答中实际用到的资料。 +引用格式:`[参考 S1‑1] https://xxx`,链接必须来源于 **web_search** 工具返回结果,禁止编造链接。 + +## 八、输出规则 +简单事实类问题:优先给出结论,附带关键证据与来源,回答简洁,避免冗余。 +复杂研究类问题,按「关键证据 → 分析 → 结论 → 参考来源」结构组织内容;先陈列证据再输出总结,结论不能超出现有资料可支撑的范围。 """ # 智能体 -agent = Agent( +agent = Agent[Deps, str]( model=DEEPSEEK_V4_FLASH_RESPONSE_MODEL, + deps_type=Deps, output_type=str, # 若输出类型为 str,则智能体输出结果时不进行输出类型校验。若定义输出类型,需考虑处理相应事件 instructions=instruction, toolsets=[bocha_web_search], @@ -118,7 +179,11 @@ async def run_stream_events( :param usage: 使用量 :return: AsyncGenerator """ + if connection_pool is None: + return + async with agent.run_stream_events( + deps=Deps(connection_pool=connection_pool), user_prompt=user_prompt, message_history=message_history, usage=usage, diff --git a/agent/database.db b/agent/database.db index 1a212cc..46c6af0 100644 Binary files a/agent/database.db and b/agent/database.db differ diff --git a/玄潮官网/assets/about-bg.png b/玄潮官网/assets/about-bg.png new file mode 100644 index 0000000..fbda654 Binary files /dev/null and b/玄潮官网/assets/about-bg.png differ diff --git a/玄潮官网/assets/hero-bg2.png b/玄潮官网/assets/hero-bg2.png new file mode 100644 index 0000000..5aa6707 Binary files /dev/null and b/玄潮官网/assets/hero-bg2.png differ diff --git a/玄潮官网/assets/xuanchao-logo.png b/玄潮官网/assets/xuanchao-logo.png new file mode 100644 index 0000000..594f4d3 Binary files /dev/null and b/玄潮官网/assets/xuanchao-logo.png differ diff --git a/玄潮官网/css/style.css b/玄潮官网/css/style.css new file mode 100644 index 0000000..aee0a78 --- /dev/null +++ b/玄潮官网/css/style.css @@ -0,0 +1,235 @@ +/* ==================== 玄潮科技 - Custom Styles ==================== */ + +/* ----- Base ----- */ +* { + scroll-behavior: smooth; +} + +body { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow-x: hidden; +} + +/* ----- Hero Background Pattern ----- */ +.hero-pattern { + background-image: + linear-gradient(rgba(154, 25, 30, 0.03) 1px, transparent 1px), + linear-gradient(90deg, rgba(154, 25, 30, 0.03) 1px, transparent 1px); + background-size: 50px 50px; + background-position: center center; +} + +.hero-pattern::before { + content: ''; + position: absolute; + inset: 0; + background-image: radial-gradient(circle, rgba(154, 25, 30, 0.08) 1px, transparent 1px); + background-size: 30px 30px; +} + +/* ----- Floating Animations ----- */ +@keyframes float-slow { + 0%, 100% { transform: translate(0, 0) scale(1); } + 50% { transform: translate(30px, -30px) scale(1.05); } +} + +@keyframes float-delayed { + 0%, 100% { transform: translate(0, 0) scale(1); } + 50% { transform: translate(-20px, 20px) scale(0.95); } +} + +.animate-float-slow { + animation: float-slow 8s ease-in-out infinite; +} + +.animate-float-delayed { + animation: float-delayed 10s ease-in-out infinite; + animation-delay: 2s; +} + +/* ----- Scroll Indicator Bounce ----- */ +@keyframes bounce-slow { + 0%, 100% { transform: translateY(0); opacity: 0.5; } + 50% { transform: translateY(10px); opacity: 0.8; } +} + +.animate-bounce-slow { + animation: bounce-slow 2s ease-in-out infinite; +} + +/* ----- Reveal Animations (Scroll-triggered) ----- */ +.reveal-up, +.reveal-left, +.reveal-right { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.8s ease, transform 0.8s ease; +} + +.reveal-left { + transform: translateX(-40px); +} + +.reveal-right { + transform: translateX(40px); +} + +.reveal-up.revealed, +.reveal-left.revealed, +.reveal-right.revealed { + opacity: 1; + transform: translate(0, 0); +} + +/* Apply reveal animation to elements that have inline animation-delay */ +.reveal-up { + animation: none; +} + +.reveal-up[style*="animation-delay"] { + transition-delay: var(--reveal-delay, 0s); +} + +/* ----- Nav Link Active State ----- */ +.nav-link.active { + color: #9a191e; + background-color: #fdf0ee; +} + +.nav-link.active::after { + content: ''; + display: block; + width: 20px; + height: 2px; + background: #9a191e; + margin: 2px auto 0; + border-radius: 2px; +} + +/* ----- Header Scroll Effect ----- */ +#header.scrolled { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); +} + +/* ----- Service Card Hover ----- */ +.service-card:hover { + transform: translateY(-4px); +} + +/* ----- Advantage Card Hover ----- */ +.advantage-card:hover { + transform: translateY(-4px); +} + +/* ----- Industry Card Hover ----- */ +.industry-card:hover { + transform: translateY(-3px); +} + +/* ----- Stat Card Hover ----- */ +.stat-card:hover { + transform: translateY(-4px); +} + +/* ----- Form Input Styles ----- */ +.form-input:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(154, 25, 30, 0.15); + border-color: #9a191e; +} + +.form-input.error { + border-color: #ef4444; + box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1); +} + +/* ----- Back to Top Button ----- */ +#back-to-top.visible { + opacity: 1; + visibility: visible; +} + +/* ----- Custom Scrollbar ----- */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: #f1f5f9; +} + +::-webkit-scrollbar-thumb { + background: #94a3b8; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #64748b; +} + +/* ----- Selection ----- */ +::selection { + background: rgba(154, 25, 30, 0.2); + color: #171717; +} + +/* ----- Mobile Menu Transition ----- */ +#mobile-menu { + transition: max-height 0.3s ease, opacity 0.3s ease; + overflow: hidden; +} + +#mobile-menu.show { + display: block; + animation: slideDown 0.3s ease; +} + +@keyframes slideDown { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ----- Gradient Text ----- */ +.text-gradient { + background: linear-gradient(135deg, #e53935, #9a191e); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* ----- Responsive Adjustments ----- */ +@media (max-width: 768px) { + .service-card, + .advantage-card, + .stat-card, + .industry-card { + transform: none; + } + + .reveal-left, + .reveal-right { + transform: translateY(30px); + } + + .reveal-left.revealed, + .reveal-right.revealed { + transform: translate(0, 0); + } +} + +/* ----- Print Styles ----- */ +@media print { + header, + #back-to-top, + .animate-float-slow, + .animate-float-delayed { + display: none !important; + } +} diff --git a/玄潮官网/index.html b/玄潮官网/index.html new file mode 100644 index 0000000..2830c02 --- /dev/null +++ b/玄潮官网/index.html @@ -0,0 +1,1257 @@ + + + + + + 玄潮科技 - 全域数据营销服务,赋能产业数智增长 + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ +
+
+ + +
+
+ + 数智营销 · 合规驱动 · 全域增长 +
+

+ 全域数据营销服务
+ 赋能产业数智增长 +

+

+ 合规产业洞察 | 智能用户分析 | 全场景营销增长解决方案 +

+ +
+ + + + + +
+ + +
+
+ +
+
+
+
+ + + +
+
+
+ +
+ 数据治理 +
+
+ +
+ +
+ 智能分析 +
+
+ +
+ +
+ 营销增长 +
+
+ +
+ +
+ 合规体系 +
+
+
+
+
+
+
+
+ 关于玄潮 +

+ 数智科技企业
深耕产业数据营销 +

+

+ 玄潮是一家聚焦数据营销场景、数据服务、产业智能分析的数智科技企业,深耕商业数据与产业营销领域多年,汇聚资深技术研发与产业运营团队,具备成熟的数智化服务落地能力。 +

+

+ 公司立足合规数据体系,依托自主研发的算法模型与智能分析能力,为多垂直行业客户提供标准化、定制化的产业数据服务与营销增长解决方案,聚焦解决企业营销粗放、用户价值挖掘不足、运营效率偏低等核心痛点,助力企业实现精细化运营、降本增效与可持续增长,已落地多行业标杆服务项目。 +

+
+ + 精细化运营 + + + 降本增效 + + + 可持续增长 + +
+
+
+ + +
+
+
+ +
+
+ 0+ +
+
覆盖垂直行业
+
+
+
+ +
+
+ 0%+ +
+
客户满意度
+
+
+
+ +
+
+ 0%+ +
+
企业营销投入效益提效
+
+
+ + +
+ Our Strengths +

+ 核心优势 +

+
+
+
+
+
+ +
+

+ 行业深度洞察 +

+

+ 深耕多领域产业营销场景,深度拆解各行业运营特征与增长痛点,结合产业发展趋势与客户业务场景,输出适配性极强的数智化运营与增长策略。 +

+
+
+
+ +
+

+ 合规数据体系 +

+

+ 严格恪守国家数据安全、个人隐私保护相关法律法规,建立全流程合规数据治理机制,标准化数据采集、分析、应用流程,保障所有服务合规可控、风险可控。 +

+
+
+
+ +
+

+ 全域闭环赋能 +

+

+ 打通公私域产业运营链路,构建「用户分析-策略匹配-流量运营-效果复盘」全闭环服务体系,实现方案可落地、运营可追踪、增长可量化。 +

+
+
+
+ +
+

+ 专业落地服务 +

+

+ 配备专属技术与运营服务团队,基于不同行业属性定制差异化服务方案,全程跟进项目落地、优化迭代,保障服务实效与客户价值落地。 +

+
+
+ + +
+
+ Our Team +

+ 团队背景 +

+

+ 团队核心成员深耕产业数据、智能算法、数字营销、产业运营领域多年,具备丰富的技术研发与项目落地实战经验。团队立足产业真实需求,持续迭代智能分析模型与服务体系,快速响应各行业客户的定制化需求,已成功落地多个跨区域、跨行业数智服务项目,持续为客户输出稳定、高效、合规的产业增长服务能力。 +

+
+
+
+ +
+ 技术研发 +
+
+
+ +
+ 产业运营 +
+
+
+ +
+ 智能算法 +
+
+
+ +
+ 数字营销 +
+
+
+
+ +
+
+
+
+
+
+
+ +
+ 企业使命 +

+ 以合规化产业数据服务与智能分析能力,赋能企业精细化营销运营,让每一次产业投入都收获可量化的真实增长价值。 +

+
+
+
+
+ + +
+ Industries +

+ 覆盖行业 +

+

+ 深耕多领域产业营销场景,已服务多个垂直行业标杆项目 +

+
+
+
+
+ +
汽车
+
+
+ +
信贷
+
+
+ +
母婴
+
+
+ +
医美
+
+
+ +
美妆
+
+
+ +
植发
+
+
+ +
快消
+
+
+ +
文旅
+
+
+ +
游戏
+
+
+ +
品牌MCN
+
+
+
+
+ + +
+
+ +
+ Our Services +

+ 产品服务 +

+

+ 全链路数智化营销服务体系,赋能企业精细化运营与可持续增长 +

+
+
+ + +
+ +
+
+
+ +
+ 01 +
+

+ 产业用户智能评级服务 +

+

+ 依托多维产业数据与自研算法模型,构建标准化用户价值评估体系,基于用户行为特征、产业需求、消费偏好等多维度信号,完成用户分层分级与价值研判。 +

+

+ 通过智能化标签体系区分用户潜力层级,为企业运营决策、用户跟进、资源配置提供数据参考,结合不同行业属性完成模型迭代调优,有效提升产业用户匹配精准度与运营转化效率。 +

+
+ + +
+
+
+ +
+ 02 +
+

+ 精准产业拓新服务 +

+

+ 基于行业产业特征与目标用户画像,搭建精细化人群研判体系,精准挖掘具备真实产业需求与消费潜力的目标客群。 +

+

+ 适配多类型用户承接与运营场景,结合行业特性定制差异化拓新与运营策略,精准过滤无效流量与非目标客群,帮助企业高效完成优质用户扩容,实现低成本精准拓新。 +

+
+ + +
+
+
+ +
+ 03 +
+

+ 全域智能营销赋能服务 +

+

+ 整合全域公私域运营渠道,搭建「智能人群分析、策略适配、全渠道赋能、数据复盘优化」的全链路营销服务体系。 +

+

+ 依托产业数据沉淀与智能分析能力,完成精细化人群划分、竞品客群挖掘、自有用户数据联动分析,配套标准化运营工具与落地策略支撑。通过全维度数据复盘,梳理运营链路核心痛点,助力客户持续优化营销资源配置,提升整体运营收益。 +

+
+ + +
+
+
+ +
+ 04 +
+

+ 营销智能风控服务 +

+

+ 针对各类产业营销运营场景,搭建智能化风险识别与防护体系,依托算法能力精准识别异常流量、批量作弊、恶意薅羊毛等各类营销风险行为。 +

+

+ 实现异常账号、异常访问行为的智能监测与拦截,全方位守护企业营销预算与运营秩序,适配线上活动运营、全域拓新、广告投放等多类商业场景,保障营销运营公平高效。 +

+
+
+ + +
+
+
+
+
+ +
+
+
+
+
+ +
+ 05 +
+

+ 垂直行业数智解决方案 +

+

+ 聚焦多类主流垂直行业,基于行业产业特征与增长痛点,定制专属数智化营销与数据服务方案,以产业智能分析、精细化用户运营、全域增长赋能为核心,助力各行业企业实现数字化转型与业务增长。 +

+
+
+ + +
+
+
+ +

汽车行业

+
+

+ 依托用户购车需求研判、用户价值分层能力,赋能车企及渠道精细化运营与销售转化提升。 +

+
+
+
+ +

金融信贷行业

+
+

+ 挖掘用户金融服务需求与潜力,构建高价值客群体系,助力金融机构精准运营、合规拓客。 +

+
+
+
+ +

母婴消费行业

+
+

+ 精准识别备孕、孕期、育儿全周期人群,匹配精细化运营与拓新方案,赋能消费品牌用户增长。 +

+
+
+
+ +

医美行业

+
+

+ 挖掘医美消费意向与潜力客群,为线下医美机构提供精准用户运营与增长赋能。 +

+
+
+
+ +

美妆快消行业

+
+

+ 覆盖竞品客群挖掘、大促节点拓新、存量用户唤醒、精细化会员运营等全场景增长服务。 +

+
+
+
+ +

游戏与品牌MCN行业

+
+

+ 精准挖掘潜力用户、智能防控运营风险、复盘优化投放效果,助力内容品牌长效增长。 +

+
+
+
+
+
+
+ + +
+
+ +
+ Contact Us +

+ 联系我们 +

+

+ 商务合作咨询:欢迎各行业品牌企业、广告机构、渠道服务商洽谈深度合作,共创产业数智增长新价值。 +

+
+
+ +
+ +
+
+

联系方式

+
+
+
+ +
+
+
+ 公司地址 +
+

+ 浙江省杭州市西湖区古荡街道西溪路525号C楼5686室 +

+
+
+
+
+ +
+
+
+ 联系电话 +
+

+ 19521568866 +

+
+
+
+
+ +
+
+
+ 电子邮箱 +
+

+ q@pangjukeji.com +

+
+
+
+
+ + +
+
+
+
+ +
+

+ 商务合作咨询 +

+

+ 欢迎各行业品牌企业、广告机构、渠道服务商洽谈深度合作,共创产业数智增长新价值。 +

+ + 立即致电 + +
+
+
+ + +
+

在线留言

+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+ +
+ + +
+
+
+
+
+ + + + + + + + + + + diff --git a/玄潮官网/js/main.js b/玄潮官网/js/main.js new file mode 100644 index 0000000..e801130 --- /dev/null +++ b/玄潮官网/js/main.js @@ -0,0 +1,307 @@ +/* ==================== 玄潮科技 - Main JavaScript ==================== */ + +(function () { + 'use strict'; + + /* ----- DOM Ready ----- */ + document.addEventListener('DOMContentLoaded', function () { + initMobileMenu(); + initSmoothScroll(); + initHeaderScroll(); + initActiveNav(); + initRevealAnimations(); + initCounters(); + initBackToTop(); + initContactForm(); + initFooterYear(); + }); + + /* ==================== Mobile Menu ==================== */ + function initMobileMenu() { + var btn = document.getElementById('mobile-menu-btn'); + var menu = document.getElementById('mobile-menu'); + if (!btn || !menu) return; + + btn.addEventListener('click', function () { + menu.classList.toggle('hidden'); + var icon = btn.querySelector('i'); + if (menu.classList.contains('hidden')) { + icon.className = 'fas fa-bars text-xl'; + } else { + icon.className = 'fas fa-xmark text-xl'; + } + }); + + // Close mobile menu when a link is clicked + var links = menu.querySelectorAll('.mobile-nav-link'); + links.forEach(function (link) { + link.addEventListener('click', function () { + menu.classList.add('hidden'); + btn.querySelector('i').className = 'fas fa-bars text-xl'; + }); + }); + } + + /* ==================== Smooth Scroll ==================== */ + function initSmoothScroll() { + var links = document.querySelectorAll('a[href^="#"]'); + links.forEach(function (link) { + link.addEventListener('click', function (e) { + var href = link.getAttribute('href'); + if (href === '#' || href === '') return; + var target = document.querySelector(href); + if (!target) return; + e.preventDefault(); + var headerHeight = document.getElementById('header').offsetHeight; + var targetPos = target.getBoundingClientRect().top + window.pageYOffset - headerHeight + 1; + window.scrollTo({ + top: targetPos, + behavior: 'smooth' + }); + }); + }); + } + + /* ==================== Header Scroll Effect ==================== */ + function initHeaderScroll() { + var header = document.getElementById('header'); + if (!header) return; + window.addEventListener('scroll', function () { + if (window.scrollY > 10) { + header.classList.add('scrolled'); + } else { + header.classList.remove('scrolled'); + } + }); + } + + /* ==================== Active Nav Highlighting ==================== */ + function initActiveNav() { + var sections = document.querySelectorAll('section[id]'); + var navLinks = document.querySelectorAll('.nav-link'); + if (!sections.length || !navLinks.length) return; + + var observer = new IntersectionObserver(function (entries) { + entries.forEach(function (entry) { + if (entry.isIntersecting) { + var id = entry.target.getAttribute('id'); + navLinks.forEach(function (link) { + if (link.getAttribute('href') === '#' + id) { + link.classList.add('active'); + link.classList.remove('text-gray-600'); + } else { + link.classList.remove('active'); + link.classList.add('text-gray-600'); + } + }); + } + }); + }, { + rootMargin: '-40% 0px -55% 0px' + }); + + sections.forEach(function (section) { + observer.observe(section); + }); + } + + /* ==================== Reveal Animations ==================== */ + function initRevealAnimations() { + var elements = document.querySelectorAll('.reveal-up, .reveal-left, .reveal-right'); + if (!elements.length) return; + + // Set animation delay from inline style + elements.forEach(function (el) { + var styleDelay = el.style.animationDelay; + if (styleDelay) { + el.style.setProperty('--reveal-delay', styleDelay); + } + }); + + var observer = new IntersectionObserver(function (entries) { + entries.forEach(function (entry) { + if (entry.isIntersecting) { + entry.target.classList.add('revealed'); + observer.unobserve(entry.target); + } + }); + }, { + threshold: 0.15, + rootMargin: '0px 0px -50px 0px' + }); + + elements.forEach(function (el) { + observer.observe(el); + }); + } + + /* ==================== Counter Animation ==================== */ + function initCounters() { + var counters = document.querySelectorAll('.counter'); + if (!counters.length) return; + + var observer = new IntersectionObserver(function (entries) { + entries.forEach(function (entry) { + if (entry.isIntersecting) { + animateCounter(entry.target); + observer.unobserve(entry.target); + } + }); + }, { + threshold: 0.5 + }); + + counters.forEach(function (counter) { + observer.observe(counter); + }); + } + + function animateCounter(el) { + var target = parseInt(el.getAttribute('data-target'), 10); + var duration = 2000; + var startTime = null; + + function step(timestamp) { + if (!startTime) startTime = timestamp; + var progress = Math.min((timestamp - startTime) / duration, 1); + // Ease out cubic + var eased = 1 - Math.pow(1 - progress, 3); + var current = Math.floor(eased * target); + el.textContent = current; + if (progress < 1) { + requestAnimationFrame(step); + } else { + el.textContent = target; + } + } + + requestAnimationFrame(step); + } + + /* ==================== Back to Top ==================== */ + function initBackToTop() { + var btn = document.getElementById('back-to-top'); + if (!btn) return; + + window.addEventListener('scroll', function () { + if (window.scrollY > 500) { + btn.classList.add('visible'); + btn.classList.remove('opacity-0', 'invisible'); + } else { + btn.classList.remove('visible'); + btn.classList.add('opacity-0', 'invisible'); + } + }); + + btn.addEventListener('click', function () { + window.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }); + } + + /* ==================== Contact Form ==================== */ + function initContactForm() { + var form = document.getElementById('contact-form'); + if (!form) return; + + var successMsg = document.getElementById('form-success'); + + form.addEventListener('submit', function (e) { + e.preventDefault(); + + // Clear previous errors + var errorMessages = form.querySelectorAll('.error-msg'); + errorMessages.forEach(function (msg) { msg.classList.add('hidden'); }); + var inputs = form.querySelectorAll('.form-input'); + inputs.forEach(function (input) { input.classList.remove('error'); }); + + var isValid = true; + + // Validate name + var name = document.getElementById('name'); + if (!name.value.trim()) { + showError(name, 'name'); + isValid = false; + } + + // Validate phone (Chinese phone: 11 digits starting with 1, or landline) + var phone = document.getElementById('phone'); + var phoneVal = phone.value.trim(); + if (!phoneVal || !/^[\d\s\-+()]{7,20}$/.test(phoneVal)) { + showError(phone, 'phone'); + isValid = false; + } + + // Validate email + var email = document.getElementById('email'); + var emailVal = email.value.trim(); + if (!emailVal || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailVal)) { + showError(email, 'email'); + isValid = false; + } + + // Validate company + var company = document.getElementById('company'); + if (!company.value.trim()) { + showError(company, 'company'); + isValid = false; + } + + // Validate message + var message = document.getElementById('message'); + if (!message.value.trim()) { + showError(message, 'message'); + isValid = false; + } + + if (isValid) { + // === Submit logic === + // 此处可对接后端API,示例: + // fetch('/api/contact', { method: 'POST', body: new FormData(form) }) + // .then(res => res.json()) + // .then(data => { ... }) + // .catch(err => { ... }); + + // 模拟提交成功 + form.style.display = 'none'; + successMsg.classList.remove('hidden'); + + // 5秒后恢复表单 + setTimeout(function () { + form.reset(); + form.style.display = ''; + successMsg.classList.add('hidden'); + }, 5000); + } + }); + + function showError(input, fieldId) { + input.classList.add('error'); + var errorMsg = input.parentElement.querySelector('.error-msg'); + if (errorMsg) { + errorMsg.classList.remove('hidden'); + } + } + + // Clear error on input + var allInputs = form.querySelectorAll('.form-input'); + allInputs.forEach(function (input) { + input.addEventListener('input', function () { + input.classList.remove('error'); + var errorMsg = input.parentElement.querySelector('.error-msg'); + if (errorMsg) errorMsg.classList.add('hidden'); + }); + }); + } + + /* ==================== Footer Year ==================== */ + function initFooterYear() { + var yearEl = document.getElementById('current-year'); + if (yearEl) { + yearEl.textContent = new Date().getFullYear(); + } + } + +})();