Ver código fonte

Merge branch 'master' of http://git.fmode.cn:3000/19323826807/travel-wed

0235624 3 semanas atrás
pai
commit
1656796c1d

BIN
travel-web/public/public/images/chihong.webp


BIN
travel-web/public/public/images/image.png


BIN
travel-web/public/public/images/zengshaoxiong.webp


BIN
travel-web/public/public/images/zhangmingyuan.webp


BIN
travel-web/public/public/images/zhuhong.webp


+ 170 - 0
travel-web/src/lib/completion.ts

@@ -0,0 +1,170 @@
+
+export interface TestMessage{
+    role:string
+    content:string
+}
+
+export class TestCompletion{
+    token:string = "r:60abef69e7cd8181b146ceaba1fdbf02"
+    messageList:any = []
+    stream:boolean = true;
+    constructor(messageList:any){
+        this.messageList = messageList || this.messageList
+    }
+    async sendMessage(messageList?:null|Array<TestMessage>,onMessage?: (content: string) => void):Promise<any>{
+        
+        this.messageList = messageList || this.messageList
+        let body = {
+            "messages": this.messageList,
+            "stream": this.stream,
+            "model": "fmode-4.5-128k",
+            "temperature": 0.5,
+            "presence_penalty": 0,
+            "frequency_penalty": 0,
+            "token": "Bearer "+this.token
+        }
+
+        let response = await fetch("https://server.fmode.cn/api/apig/aigc/gpt/v1/chat/completions", {
+            "headers": {
+            },
+            "body": JSON.stringify(body),
+            "method": "POST",
+            "mode": "cors",
+            "credentials": "omit"
+        });
+
+        
+        /** 单次响应 HTTP短连接请求
+         {"choices":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"您好!我是一个人工智能助手,旨在帮助您回答问题、提供信息和解决各种问题。我可以处理许多主题,包括科技、历史、文化、语言学习等。如果您有任何具体的问题或需要了解的内容,请随时告诉我!","refusal":null,"role":"assistant"}}],"created":1751509370,"id":"chatcmpl-Bp3t41MP4pb2NR38n1ylrJw922SBZ","model":"gpt-4o-mini-2024-07-18","object":"chat.completion","system_fingerprint":"fp_efad92c60b","usage":{"completion_tokens":55,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":15,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":70}}
+        */
+        if(this.stream == false){
+            let data = await response.json()
+            console.log(data)
+            let lastContent = data?.choices?.[0]?.message?.content
+            return lastContent
+        }
+        /**
+         * 流式加载 HTTP Event Stream 模式 长连接获取
+         */
+        
+        // Stream mode handling
+        if (!response.body) {
+            throw new Error("No response body in stream mode");
+        }
+
+        const reader = response.body.getReader();
+        const decoder = new TextDecoder("utf-8");
+        let accumulatedContent = "";
+        try {
+            while (true) {
+                const { done, value } = await reader.read();
+                if (done) break;
+
+                const chunk = decoder.decode(value, { stream: true });
+                const lines = chunk.split('\n').filter(line => line.trim() !== '');
+
+                for (const line of lines) {
+                    if (line.startsWith('data:') && !line.includes('[DONE]')) {
+                        try {
+                            const jsonStr = line.substring(5).trim();
+                            const data = JSON.parse(jsonStr);
+                            const content = data?.choices?.[0]?.delta?.content || '';
+                            
+                            if (content) {
+                                accumulatedContent += content;
+                                if (onMessage) {
+                                    onMessage(accumulatedContent);
+                                }
+                            }
+                        } catch (e) {
+                            console.error("Error parsing stream data:", e);
+                        }
+                    }
+                }
+            }
+        } finally {
+            reader.releaseLock();
+        }
+
+        return accumulatedContent;
+    }
+}
+
+/**
+ * 使用AI生成符合指定结构的JSON数据
+ * @param prompt 任务要求的整体提示词
+ * @param jsonSchema 期望的JSON结构描述(用于提示词)
+ * @param example 可选的JSON示例(帮助AI理解格式)
+ * @param onMessage 实时生成内容回调
+ * @returns 解析后的JSON对象
+ */
+export async function completionJSON(
+    prompt:string,
+  jsonSchema: string,
+  example: object | null = null,
+  onMessage?: (content: string) => void
+): Promise<any> {
+  // 1. 构建提示词
+  const JsonResultParsePrompt = `请严格按照以下要求生成JSON数据:
+- 数据结构要求:${jsonSchema}
+- 只能返回一个完整的JSON对象 确保JSON格式正确
+- 注意返回的JSON格式每个KEY都有""包裹和Value之间都有:`;
+// ${example ? `2. 参考示例格式:\n${JSON.stringify(example, null, 2)}` : ''}
+
+  // 2. 初始化消息列表
+  const messages: TestMessage[] = [
+    {
+      role: "user",
+      content: prompt+JsonResultParsePrompt
+    }
+  ];
+
+  // 3. 创建TestCompletion实例
+  const completion = new TestCompletion(messages);
+  
+  // 4. 存储累积内容和JSON对象
+  let fullContent = "";
+  let jsonObject: any = null;
+  
+  // 5. 发送请求并处理流式响应
+  const result = await completion.sendMessage(null, (content) => {
+    fullContent = content;
+  });
+  console.log("fullContent",fullContent)
+  // 6. 最终JSON提取(确保获取完整内容)
+  try {
+    // 再次尝试从完整内容中提取JSON
+      jsonObject = extractJSON(fullContent);
+  } catch (e) {
+    console.error("JSON解析失败:", e);
+    console.log("原始内容:", fullContent);
+    throw new Error("生成的响应不符合JSON格式");
+  }
+  
+  return jsonObject;
+}
+
+function extractJSON(str:string){
+  let stack = 0;
+  let startIndex = -1;
+  let result = null;
+
+  for (let i = 0; i < str.length; i++) {
+    if (str[i] === '{') {
+      if (stack === 0) startIndex = i;
+      stack++;
+    } else if (str[i] === '}') {
+      stack--;
+      if (stack === 0 && startIndex !== -1) {
+        try {
+          result = JSON.parse(str.slice(startIndex, i + 1));
+          break;
+        } catch (e) {
+          // 继续尝试下一个可能的 JSON
+          startIndex = -1;
+        }
+      }
+    }
+  }
+  return result;
+};

+ 6 - 6
travel-web/src/modules/pc-home/pages/page-association/page-association.html

@@ -21,30 +21,30 @@
     
     <div class="leaders-container">
       <div class="leader-card">
-        <div class="leader-img"></div>
+        <div class="leader-img" style="background-image: url('public/images/zhuhong.webp');"></div>
         <div class="leader-info">
           <div class="ar-tag">AR名片</div>
-          <h3 class="leader-name">张明远</h3>
+          <h3 class="leader-name">朱虹</h3>
           <p class="leader-title">协会主席 · 江西文化研究专家</p>
           <p class="leader-desc">负责协会全面工作,主管学术研究、对外交流。曾主持国家级文化研究项目5项,出版专著8部。</p>
         </div>
       </div>
       
       <div class="leader-card">
-        <div class="leader-img"></div>
+        <div class="leader-img" style="background-image: url('public/images/chihong.webp');"></div>
         <div class="leader-info">
           <div class="ar-tag">AR名片</div>
-          <h3 class="leader-name">李红梅</h3>
+          <h3 class="leader-name">池红</h3>
           <p class="leader-title">常务副主席 · 非遗保护专家</p>
           <p class="leader-desc">分管会员服务、人才培养工作。致力于江西非物质文化遗产保护与数字化传承20余年。</p>
         </div>
       </div>
       
       <div class="leader-card">
-        <div class="leader-img"></div>
+        <div class="leader-img" style="background-image: url('public/images/zengshaoxiong.webp');"></div>
         <div class="leader-info">
           <div class="ar-tag">AR名片</div>
-          <h3 class="leader-name">王建国</h3>
+          <h3 class="leader-name">曾少雄</h3>
           <p class="leader-title">秘书长 · 数字技术专家</p>
           <p class="leader-desc">分管技术研发、平台建设工作。主持开发多个省级文化数字化平台,获国家专利3项。</p>
         </div>

+ 20 - 14
travel-web/src/modules/pc-home/pages/page-association/page-association.scss

@@ -155,22 +155,28 @@ body {
 .leader-img {
   width: 150px;
   height: 180px;
-  background: #ddd;
+  background-size: cover;
+  background-position: center;
+  background-repeat: no-repeat;
   position: relative;
+  border-radius: 50% / 60%; /* 水平半径50%,垂直半径60% */
   overflow: hidden;
-}
-
-.leader-img::after {
-  content: '';
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  background: radial-gradient(circle, transparent 60%, rgba(0,0,0,0.7));
-  border: 5px solid var(--wood-light);
-  border-radius: 50%;
-  box-sizing: border-box;
+  
+  /* 移除或修改原有的伪元素样式 */
+  &::after {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    border: 3px solid var(--wood-light);
+    border-radius: 50% / 60%; /* 与父元素保持一致 */
+    box-sizing: border-box;
+    pointer-events: none;
+    /* 调整渐变效果 */
+    background: radial-gradient(circle, transparent 60%, rgba(0,0,0,0.2));
+  }
 }
 
 .leader-info {

+ 2 - 2
travel-web/src/modules/pc-home/pages/page-dynamic/page-dynamic.html

@@ -41,7 +41,7 @@
             </button>
           </div>
         </div>
-        <p>采用南昌万寿宫牌坊造型设计,识别成功时灯笼亮起,失败时显示碎瓷动画效果</p>
+        <p>借助OCR光学字符识别技术,自动提取身份证、营业执照等证件信息,30秒极速注册,降低手动录入误差,提升注册效率。</p>
       </div>
     </div>
     
@@ -232,7 +232,7 @@
             <i class="fas fa-dove"></i>
           </div>
         </div>
-        <p>采用候鸟迁徙路线图概念,匹配度高的单位以白鹤群聚呈现,生成青花瓷开片纹关系图谱</p>
+        <p>依托大数据分析构建智能匹配体系,依据会员业务范畴、资源诉求等维度,精准对接合作方,推动会员间资源整合与协同共赢。</p>
       </div>
     </div>
   </div>

+ 1 - 1
travel-web/src/modules/pc-home/pages/page-dynamic/page-dynamic.ts

@@ -18,7 +18,7 @@ export class TruncatePipe implements PipeTransform {
   standalone: true,
   templateUrl: './page-dynamic.html',
   styleUrls: ['./page-dynamic.scss'],
-  imports: [FormsModule, TruncatePipe,DatePipe]
+  imports: [FormsModule, TruncatePipe,DatePipe,CommonModule]
 })
 
 export class PageDynamic implements AfterViewInit {