Преглед на файлове

复制调整 完善首页内容宽度展示 微信登录调整

肖栋 преди 2 седмици
родител
ревизия
b77d172c34

BIN
src/assets/images/doubao_img.png


BIN
src/assets/images/home_one_image.png


+ 18 - 7
src/pages/guide/index.vue

@@ -46,10 +46,15 @@
                   <div class="home-guide-token-icons">
                     <icon-svg :name="guideTokenVisible ? 'eye_not_displayed' : 'eye_show'" size="24px"
                       class="home-guide-token-icon" @click="guideTokenVisible = !guideTokenVisible" />
-                    <icon-svg name="http_copy" size="14px" class="home-guide-token-icon" @click="copyText(guideToken)" />
+                    <icon-svg name="http_copy" size="14px" class="home-guide-token-icon" @click="copyText(`Bearer ${guideToken}`)" />
                   </div>
                 </div>
-                <button type="button" class="home-guide-token-btn" @click="createToken">
+                <button
+                  v-else
+                  type="button"
+                  class="home-guide-token-btn"
+                  @click="createToken"
+                >
                   <icon-svg name="gain_token" size="14px" class="home-guide-token-btn-icon" />
                   <span>获取 Token</span>
                 </button>
@@ -624,7 +629,12 @@ const guideDoubaoContent = {
         "验证是否成功——在对话中发送「用环评云助手MCP检索《大气污染物综合排放标准》中关于 VOCs 排放限值的规定」",
     },
   ],
-  notes: ["自定义 Headers 内需要填写页面「获取 Token」生成的真实 Token"],
+  notes: [
+    "服务器名称可自行命名",
+    "服务器 URL 内填入对应的 server URL ,每个服务对应一个链接",
+    "自定义 Headers 内填入 Authorization",
+    "自定义 Headers 内需要填写页面「获取 Token」生成的真实 Token",
+  ],
 };
 const guideWpsContent = {
   alert:
@@ -1167,7 +1177,7 @@ const guideVerifyCards = [
   display: flex;
   align-items: flex-start;
   justify-content: space-between;
-  gap: 24px;
+  gap: 40px;
   margin-top: 16px;
   padding: 30px 24px;
   background: #F8FAFC;
@@ -1176,7 +1186,7 @@ const guideVerifyCards = [
 }
 
 .home-guide-feature {
-  flex: 1;
+  flex: 0 1 auto;
   display: flex;
   align-items: flex-start;
   gap: 12px;
@@ -1189,7 +1199,7 @@ const guideVerifyCards = [
   }
 
   > div {
-    flex: 1;
+    flex: 0 1 auto;
     min-width: 0;
   }
 }
@@ -1201,6 +1211,7 @@ const guideVerifyCards = [
   color: #0F172A;
   line-height: 26px;
   text-align: left;
+  white-space: nowrap;
 }
 
 .home-guide-feature-desc {
@@ -1210,7 +1221,7 @@ const guideVerifyCards = [
   color: #64748B;
   line-height: 20px;
   text-align: left;
-  word-break: break-word;
+  white-space: nowrap;
 }
 
 .home-guide-access-tabs {

+ 39 - 32
src/pages/home/index.vue

@@ -80,7 +80,7 @@
             <div class="home-overview-heading">
               <div class="home-overview-title">MCP 智能服务 — 让环保更智能</div>
               <div class="home-overview-subtitle">
-                基于 MCP 协议的下一代环保 AI 服务,让大模型具备专业环保知识和推理能力
+                基于 MCP 协议,为大模型接入专业环保知识、数据与业务工具,提供智能化环境服务能力
               </div>
             </div>
             <div class="home-overview-cards home-overview-services">
@@ -90,7 +90,7 @@
                 </div>
                 <div class="home-overview-service-title">智能理解</div>
                 <div class="home-overview-service-desc">
-                  支持自然语言查询、智能理解用户意图、提供精准的法律信息检索和分析
+                  支持自然语言查询,智能识别用户意图,精准检索生态环境政策、法律法规、标准规范及专业知识
                 </div>
               </div>
               <div class="home-overview-service-card">
@@ -99,7 +99,7 @@
                 </div>
                 <div class="home-overview-service-title">无缝集成</div>
                 <div class="home-overview-service-desc">
-                  与 DeepSeek、Claude、ChatGPT 等主流大模型完美集成,一键接入专业法律能力。
+                  支持与 Workbuddy、豆包、Codex 等主流大模型灵活集成,一键接入专业环境知识与数据服务能力。
                 </div>
               </div>
               <div class="home-overview-service-card">
@@ -108,7 +108,7 @@
                 </div>
                 <div class="home-overview-service-title">智能推理</div>
                 <div class="home-overview-service-desc">
-                  基于上下文感知的智能推理,提供专业的法律分析和建议,提升决策质量
+                  基于上下文理解与知识检索,为环境业务提供法规标准解读、政策分析和信息辅助,提升业务决策效率
                 </div>
               </div>
             </div>
@@ -231,10 +231,15 @@
                     <icon-svg :name="guideTokenVisible ? 'eye_not_displayed' : 'eye_show'" size="24px"
                       class="home-guide-token-icon" @click="guideTokenVisible = !guideTokenVisible" />
                     <icon-svg name="http_copy" size="14px" class="home-guide-token-icon"
-                      @click="copyText(guideToken)" />
+                      @click="copyText(`Bearer ${guideToken}`)" />
                   </div>
                 </div>
-                <button type="button" class="home-guide-token-btn" @click="createToken">
+                <button
+                  v-else
+                  type="button"
+                  class="home-guide-token-btn"
+                  @click="createToken"
+                >
                   <icon-svg name="gain_token" size="14px" class="home-guide-token-btn-icon" />
                   <span>获取 Token</span>
                 </button>
@@ -922,7 +927,12 @@ const guideDoubaoContent = {
         "验证是否成功——在对话中发送「用环评云助手MCP检索《大气污染物综合排放标准》中关于 VOCs 排放限值的规定」",
     },
   ],
-  notes: ["自定义 Headers 内需要填写页面「获取 Token」生成的真实 Token"],
+  notes: [
+    "服务器名称可自行命名",
+    "服务器 URL 内填入对应的 server URL ,每个服务对应一个链接",
+    "自定义 Headers 内填入 Authorization",
+    "自定义 Headers 内需要填写页面「获取 Token」生成的真实 Token",
+  ],
 };
 const guideWpsContent = {
   alert:
@@ -1279,6 +1289,13 @@ const guideVerifyCards = [
   max-width: 1320px;
   margin-left: auto;
   margin-right: auto;
+  width: 100%;
+}
+
+/* 内容限宽 + 左右内边距(与 overview / guide 一致) */
+.home-section-content-box() {
+  .home-section-content-width();
+  .home-section-inner-padding();
 }
 
 .home-overview {
@@ -1291,16 +1308,14 @@ const guideVerifyCards = [
   flex-direction: column;
   align-items: stretch;
   gap: 120px;
-  width: 100%;
-  .home-section-inner-padding();
-  .home-section-content-width();
+  .home-section-content-box();
 }
 
 .home-overview-block {
   display: flex;
   flex-direction: column;
   align-items: center;
-  gap: 20px;
+  gap: 32px;
 }
 
 .home-overview-block:last-child {
@@ -1494,15 +1509,14 @@ const guideVerifyCards = [
   padding: 80px 0;
   background: linear-gradient(180deg, #FFFFFF 0%, #F3F7FF 100%);
   border-radius: 0;
-  .home-section-inner-padding();
 }
 
 .home-scenes-heading {
   display: flex;
   flex-direction: column;
   align-items: center;
-  width: 100%;
-  .home-section-content-width();
+  gap: 8px;
+  .home-section-content-box();
 }
 
 .home-scenes-title {
@@ -1525,10 +1539,9 @@ const guideVerifyCards = [
 
 .home-scenes-cards {
   display: flex;
-  width: 100%;
   min-width: 0;
   gap: 16px;
-  .home-section-content-width();
+  .home-section-content-box();
 }
 
 .home-scenes-card {
@@ -1652,8 +1665,8 @@ const guideVerifyCards = [
   width: 100%;
   background: #F3F7FF;
   border-radius: 10px;
-  margin: 36px 0 80px;
-  padding: 36px var(--home-inline-padding);
+  margin: 36px 0 0;
+  padding: 36px 0 80px;
   box-sizing: border-box;
 }
 
@@ -1662,7 +1675,7 @@ const guideVerifyCards = [
   grid-template-columns: 1fr 1fr;
   align-items: start;
   gap: 40px;
-  .home-section-content-width();
+  .home-section-content-box();
 }
 
 .home-scenes-demo-copy {
@@ -1797,13 +1810,11 @@ const guideVerifyCards = [
 }
 
 .home-guide-inner {
-  width: 100%;
   display: flex;
   flex-direction: column;
   align-items: stretch;
   gap: 32px;
-  .home-section-inner-padding();
-  .home-section-content-width();
+  .home-section-content-box();
 }
 
 .home-guide-heading {
@@ -1936,7 +1947,7 @@ const guideVerifyCards = [
 .home-guide-block {
   background: #FFFFFF;
   border-radius: 16px;
-  padding: 24px;
+  padding: 24px 0;
 }
 
 .home-guide-block-head {
@@ -2143,6 +2154,7 @@ const guideVerifyCards = [
 .home-guide-features {
   display: flex;
   align-items: center;
+  justify-content: space-between;
   gap: 40px;
   margin-top: 16px;
   padding: 30px 40px;
@@ -2152,7 +2164,7 @@ const guideVerifyCards = [
 }
 
 .home-guide-feature {
-  flex: 1;
+  flex: 0 1 auto;
   display: flex;
   align-items: flex-start;
   gap: 12px;
@@ -2166,7 +2178,7 @@ const guideVerifyCards = [
 }
 
 .home-guide-feature > div {
-  flex: 1;
+  flex: 0 1 auto;
   min-width: 0;
 }
 
@@ -2177,6 +2189,7 @@ const guideVerifyCards = [
   color: #0F172A;
   line-height: 26px;
   text-align: left;
+  white-space: nowrap;
 }
 
 .home-guide-feature-desc {
@@ -2186,7 +2199,7 @@ const guideVerifyCards = [
   color: #64748B;
   line-height: 20px;
   text-align: left;
-  word-break: break-word;
+  white-space: nowrap;
 }
 
 .home-guide-access-tabs {
@@ -3262,12 +3275,6 @@ const guideVerifyCards = [
 
   .home-footer-inner {
     box-sizing: border-box;
-    width: 100%;
-    max-width: 1320px;
-    margin-left: auto;
-    margin-right: auto;
-    padding-left: calc(var(--home-inline-padding) + 24px);
-    padding-right: calc(var(--home-inline-padding) + 24px);
     flex-direction: row;
     justify-content: space-between;
     align-items: flex-start;

+ 122 - 3
src/pages/mcp/onlineTest.vue

@@ -63,7 +63,11 @@
               <div class="otp-header-desc">{{ currentService.describe }}</div>
             </div>
             <div class="otp-header-right">
-              <template v-if="isConnected">
+              <template v-if="contentLoading">
+                <div class="otp-skeleton-block otp-skeleton-block--pill"></div>
+                <div class="otp-skeleton-block otp-skeleton-block--btn"></div>
+              </template>
+              <template v-else-if="isConnected">
                 <span class="otp-connect-pill">
                   <i class="otp-connect-dot"></i>
                   <span>已连接</span>
@@ -96,6 +100,27 @@
           </div>
         </section>
 
+        <template v-if="contentLoading">
+          <div class="otp-skeleton-block otp-skeleton-block--warn"></div>
+          <section class="otp-card otp-info-card">
+            <div v-for="n in 4" :key="`info-${n}`" class="otp-info-row">
+              <div class="otp-skeleton-block otp-skeleton-block--label"></div>
+              <div class="otp-skeleton-block otp-skeleton-block--value"></div>
+            </div>
+          </section>
+          <section class="otp-card otp-tools-card">
+            <div class="otp-skeleton-block otp-skeleton-block--section-title"></div>
+            <div class="otp-skeleton-tools">
+              <div v-for="n in 3" :key="`tool-${n}`" class="otp-skeleton-tool"></div>
+            </div>
+            <div class="otp-skeleton-block otp-skeleton-block--section-title"></div>
+            <div class="otp-skeleton-params">
+              <div v-for="n in 3" :key="`param-${n}`" class="otp-skeleton-param"></div>
+            </div>
+            <div class="otp-skeleton-block otp-skeleton-block--run"></div>
+          </section>
+        </template>
+        <template v-else>
         <div v-if="!isConnected" class="otp-connect-warn">
           <icon-svg name="service_warning" size="14px" class="otp-connect-warn-icon" />
           <span class="otp-connect-warn-text">当前服务未开启,请先连接服务后进行测试</span>
@@ -308,6 +333,7 @@
           </div>
           </template>
         </section>
+        </template>
       </main>
 
       <!-- 右侧响应结果 -->
@@ -507,6 +533,7 @@ const serviceList = ref([]);
 const activeServiceId = ref("");
 const isConnected = ref(false);
 const connecting = ref(false);
+const contentLoading = ref(false);
 const running = ref(false);
 // 在线测试检索结果
 const searchResult = ref(null);
@@ -607,6 +634,7 @@ const resetTestState = () => {
 const disconnectServer = () => {
   // 断开接口后续接入,先按前端状态切到未连接展示
   ++toolRequestId.value;
+  contentLoading.value = false;
   isConnected.value = false;
   connecting.value = false;
   resetTestState();
@@ -796,11 +824,13 @@ const fetchToolsByServerId = async (serverId) => {
     requestParams.value = [];
     responseStructure.value = [];
     isConnected.value = false;
+    contentLoading.value = false;
     saveConnectState(false, "");
     return;
   }
-  isConnected.value = false;
-  serverDetailUrl.value = "";
+  contentLoading.value = true;
+  searchResult.value = null;
+  resultMeta.value = { code: null, time: null, ok: false, label: "-" };
   try {
     const detailRes = await getMcpServerDetail(serverId);
     if (requestId !== toolRequestId.value) return;
@@ -856,6 +886,10 @@ const fetchToolsByServerId = async (serverId) => {
     responseStructure.value = [];
     isConnected.value = false;
     saveConnectState(false, serverId);
+  } finally {
+    if (requestId === toolRequestId.value) {
+      contentLoading.value = false;
+    }
   }
 };
 
@@ -1395,6 +1429,91 @@ const runTest = async () => {
   gap: 16px;
 }
 
+@keyframes otp-skeleton-shimmer {
+  0% {
+    background-position: 200% 0;
+  }
+
+  100% {
+    background-position: -200% 0;
+  }
+}
+
+.otp-skeleton-block,
+.otp-skeleton-tool,
+.otp-skeleton-param {
+  background: linear-gradient(90deg, #eef2f7 25%, #e2e8f0 50%, #eef2f7 75%);
+  background-size: 200% 100%;
+  animation: otp-skeleton-shimmer 1.2s ease-in-out infinite;
+  border-radius: 6px;
+}
+
+.otp-skeleton-block--pill {
+  width: 72px;
+  height: 28px;
+  border-radius: 14px;
+}
+
+.otp-skeleton-block--btn {
+  width: 96px;
+  height: 32px;
+  border-radius: 8px;
+}
+
+.otp-skeleton-block--warn {
+  width: 100%;
+  height: 40px;
+  border-radius: 8px;
+}
+
+.otp-skeleton-block--label {
+  width: 72px;
+  height: 16px;
+  flex-shrink: 0;
+}
+
+.otp-skeleton-block--value {
+  flex: 1;
+  min-width: 0;
+  height: 16px;
+}
+
+.otp-skeleton-block--section-title {
+  width: 120px;
+  height: 20px;
+  margin-bottom: 12px;
+}
+
+.otp-skeleton-tools {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  margin-bottom: 16px;
+}
+
+.otp-skeleton-tool {
+  height: 88px;
+  border-radius: 10px;
+}
+
+.otp-skeleton-params {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+  margin-bottom: 16px;
+}
+
+.otp-skeleton-param {
+  height: 72px;
+  border-radius: 8px;
+}
+
+.otp-skeleton-block--run {
+  width: 100%;
+  height: 40px;
+  border-radius: 8px;
+}
+
 .otp-card {
   box-sizing: border-box;
   padding: 16px;

+ 3 - 3
src/pages/mcp/serverDetail.vue

@@ -255,7 +255,7 @@
               class="mcp-server-token-icon"
               @click="tokenVisible = !tokenVisible"
             />
-            <icon-svg name="token_copy" size="14px" class="mcp-server-token-icon" @click="copyText(mcpToken)" />
+            <icon-svg name="token_copy" size="14px" class="mcp-server-token-icon" @click="copyText(`Bearer ${mcpToken}`)" />
           </div>
         </div>
       </div>
@@ -470,12 +470,12 @@ const mapReqParams = (reqParams) => {
 };
 
 const buildMcpConfig = (data) => {
-  const serverKey = data.code || "mcp-server";
+  const code = data.code || "mcp-server";
+  const serverKey = code.startsWith("hpyzs-") ? code : `hpyzs-${code}`;
   const config = {
     mcpServers: {
       [serverKey]: {
         url: data.url || "",
-        type: "http",
       },
     },
   };

+ 1 - 1
src/utils/config.js

@@ -10,4 +10,4 @@ export const orgDomain = isPcBoolean
 
 // 微信登录页基础URL
 const WECHAT_PAGE_BASE_URL = 'https://www.eiacloud.com/hpyzs/weChat/wxThirdLoginPage';
-export const wechatLoginUrl = `${WECHAT_PAGE_BASE_URL}?rootDomain=${isPcBoolean ? 'ckTest' : 'ai'}`;
+export const wechatLoginUrl = `${WECHAT_PAGE_BASE_URL}?rootDomain=mcp`;