From 9de2ef37346c01604547c552d7506e606d76b025 Mon Sep 17 00:00:00 2001
From: fhysy <1149505133@qq.com>
Date: Fri, 21 Mar 2025 11:52:33 +0800
Subject: [PATCH] =?UTF-8?q?refactor(fun):=20=E9=87=8D=E6=9E=84=20AI?=
=?UTF-8?q?=E5=89=A7=E6=9C=AC=E7=94=9F=E6=88=90=E5=8A=9F=E8=83=BD=EF=BC=8C?=
=?UTF-8?q?=E5=B1=8F=E8=94=BD=E8=A7=86=E9=A2=91=E4=B8=8B=E8=BD=BD=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=EF=BC=8C=E8=B0=83=E6=95=B4=E6=94=AF=E4=BB=98=E5=BC=95?=
=?UTF-8?q?=E5=85=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package.json | 6 +-
pages/fun/AiDrama.vue | 512 +++++++++++++++-------------------------
pages/fun/videoView.vue | 4 +-
pages/order/detail.vue | 2 +-
4 files changed, 197 insertions(+), 327 deletions(-)
diff --git a/package.json b/package.json
index 0967ef4..a690ac8 100644
--- a/package.json
+++ b/package.json
@@ -1 +1,5 @@
-{}
+{
+ "dependencies": {
+ "jweixin-module": "^1.6.0"
+ }
+}
diff --git a/pages/fun/AiDrama.vue b/pages/fun/AiDrama.vue
index 7c91cb6..3d27a6a 100644
--- a/pages/fun/AiDrama.vue
+++ b/pages/fun/AiDrama.vue
@@ -23,9 +23,9 @@
-
@@ -34,7 +34,7 @@
-
+
@@ -45,16 +45,16 @@
-
+
正在生成剧本...
-
+
-
+
@@ -67,7 +67,7 @@
v-model="inputMessage"
placeholder="请输入剧本相关描述,AI将为您生成专业剧本..."
:disabled="loading"
- type='textarea'
+ type='textarea'
:auto-height="true"
:custom-style="{flex: 1, minHeight: '80rpx', maxHeight: '200rpx'}"
@confirm="sendMessage"
@@ -244,236 +244,151 @@ export default {
// 使用fetch API进行流式请求(仅H5环境)
async fetchStreamResponse(apiMessages) {
- try {
- // 添加一个空的AI回复,用于流式更新
- this.currentAiMessageIndex = this.messages.length;
- this.messages.push({
- role: 'assistant',
- content: '',
- renderedContent: '',
- time: this.formatTime(new Date()),
- endStatus: false
- });
-
- const response = await fetch(`${config.baseUrl}/ai/generateStream`, {
- method: 'POST',
- headers: {
- 'Authorization': `Bearer ${this.token}`,
- 'clientid': config.clientId,
- 'Content-Type': 'application/json'
- },
- redirect: 'follow',
- body: JSON.stringify(apiMessages)
- });
-
- if (!response.ok) {
- throw new Error(`API请求失败: ${response.status}`);
- }
-
- if (!response.body) {
- throw new Error('响应体为空');
- }
-
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
- let result = '';
- let buffer = ''; // 用于存储未完整的数据
-
- while (true) {
- const { done, value } = await reader.read();
- if (done) break;
-
- const chunk = decoder.decode(value);
- buffer += chunk; // 将新的chunk添加到buffer中
- console.log("buffer",buffer)
- // 按换行符分割,但保留buffer中可能不完整的最后一行
- const lines = buffer.split('\n');
- buffer = lines.pop() || ''; // 保存最后一行到buffer,如果是空行则置空
- console.log("lines",lines)
- for (const line of lines.filter(l => l.trim())) {
- // debugger
- console.log('处理行:', line);
- let data = line;
-
- if (line.startsWith('data:')) {
- data = line.substring(5).trim();
- }
- console.log("data",data)
- if (data === '[DONE]') {
- // 设置消息已完成状态
- if (this.currentAiMessageIndex >= 0 && this.currentAiMessageIndex < this.messages.length) {
- this.messages[this.currentAiMessageIndex].endStatus = true;
- // 最后一次滚动到底部
- this.throttledScrollToBottom();
- }
- continue;
- }
- // debugger
- try {
- result += data;
- console.log("result",result)
- if (this.messages && this.currentAiMessageIndex < this.messages.length) {
- this.messages[this.currentAiMessageIndex].content = result;
- this.messages[this.currentAiMessageIndex].renderedContent = renderMarkdown(result);
- console.log("messages1",this.messages)
- // 最后一次滚动到底部
- this.throttledScrollToBottom();
- } else {
- console.warn('无法更新消息,索引无效:', aiMessageIndex);
- }
- } catch (e) {
- console.error('解析流数据失败:', e, line);
- }
- }
-
- // 处理buffer中剩余的数据
- if (buffer) {
- try {
- let data = buffer;
- if (buffer.startsWith('data:')) {
- data = buffer.substring(5).trim();
- }
- if (data && data !== '[DONE]') {
- result += data;
- this.messages[this.currentAiMessageIndex].content = result;
- this.messages[this.currentAiMessageIndex].renderedContent = renderMarkdown(result);
- this.throttledScrollToBottom();
- }
- } catch (e) {
- console.error('处理剩余数据失败:', e, buffer);
- }
- }
-
- }
-
- return result;
- } catch (error) {
- console.error('调用DeepSeek流式API失败:', error);
- // 如果出错,确保移除空的AI消息
- if (this.messages.length > 0 && this.messages[this.messages.length - 1].content === '') {
- this.messages.pop();
- this.currentAiMessageIndex = -1;
- }
- throw error;
- }
-
-
-
- // try {
- // // 添加一个空的AI回复,用于流式更新
- // this.currentAiMessageIndex = this.messages.length;
- // this.messages.push({
- // role: 'assistant',
- // content: '',
- // renderedContent: '',
- // time: this.formatTime(new Date()),
- // endStatus: false
- // });
+ try {
+ // 添加一个空的AI回复,用于流式更新
+ this.currentAiMessageIndex = this.messages.length;
+ this.messages.push({
+ role: 'assistant',
+ content: '',
+ renderedContent: '',
+ time: this.formatTime(new Date()),
+ endStatus: false
+ });
- // const response = await fetch('https://api.siliconflow.cn/v1/chat/completions', {
- // method: 'POST',
- // headers: {
- // 'Authorization': `Bearer ${this.apiKey}`,
- // 'Content-Type': 'application/json'
- // },
- // body: JSON.stringify({
- // model: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-7B',
- // messages: apiMessages,
- // stream: true,
- // max_tokens: 8192,
- // stop: '',
- // temperature: 0.6,
- // top_p: 0.7,
- // top_k: 50,
- // frequency_penalty: 0
- // })
- // });
-
- // if (!response.ok) {
- // throw new Error(`API请求失败: ${response.status}`);
- // }
-
- // if (!response.body) {
- // throw new Error('响应体为空');
- // }
-
- // const reader = response.body.getReader();
- // const decoder = new TextDecoder();
- // let result = '';
-
- // while (true) {
- // const { done, value } = await reader.read();
- // if (done) break;
+ const response = await fetch(`${config.baseUrl}/ai/generateStream`, {
+ method: 'POST',
+ headers: {
+ 'Authorization': `Bearer ${this.token}`,
+ 'clientid': config.clientId,
+ 'Content-Type': 'application/json'
+ },
+ redirect: 'follow',
+ body: JSON.stringify(apiMessages)
+ });
+
+ if (!response.ok) {
+ throw new Error(`API请求失败: ${response.status}`);
+ }
+
+ if (!response.body) {
+ throw new Error('响应体为空');
+ }
+
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder();
+ let result = '';
+ let buffer = ''; // 用于存储未完整的数据
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
- // const chunk = decoder.decode(value);
- // const lines = chunk.split('\n').filter(line => line.trim() !== '');
+ const chunk = decoder.decode(value, { stream: true }); // Use streaming mode
+ buffer += chunk;
- // for (const line of lines) {
- // if (line.startsWith('data: ')) {
- // const data = line.substring(6).trim();
- // if (data === '[DONE]') {
- // // 设置消息已完成状态
- // if (this.currentAiMessageIndex >= 0 && this.currentAiMessageIndex < this.messages.length) {
- // this.messages[this.currentAiMessageIndex].endStatus = true;
- // // 最后一次滚动到底部
- // this.throttledScrollToBottom();
- // }
- // continue;
- // }
+ // 将新的chunk添加到buffer中
+ const lines = buffer.split('\n');
+ // 按换行符分割,但保留buffer中可能不完整的最后一行
+ buffer = lines.pop() || '';
+
+ for (const line of lines) {
+ if (!line.trim()) continue; // Skip empty lines
+
+ let data = line;
+
+ if (line.startsWith('data:')) {
+ data = line.substring(5).trim();
+ }
+
+ if (data === '[DONE]') {
+ // 设置消息已完成状态
+ if (this.currentAiMessageIndex >= 0 && this.currentAiMessageIndex < this.messages.length) {
+ this.messages[this.currentAiMessageIndex].endStatus = true;
+ this.throttledScrollToBottom();
+ }
+ continue;
+ }
+
+ try {
+ // For JSON data (if your API returns JSON)
+ if (data.startsWith('{') && data.endsWith('}')) {
+ const parsed = JSON.parse(data);
+ const content = parsed.choices?.[0]?.delta?.content || '';
+ if (content) {
+ result += content;
+ }
+ } else {
+ // For plain text data
+ result += data;
+ }
- // try {
- // const parsed = JSON.parse(data);
- // // 检查parsed和choices是否存在
- // if (!parsed || !parsed.choices || !Array.isArray(parsed.choices) || parsed.choices.length === 0) {
- // console.warn('无效的响应格式:', data);
- // continue;
- // }
-
- // // 安全地访问delta属性
- // const delta = parsed.choices[0].delta || {};
-
- // // 根据您提供的格式解析内容
- // const content = delta.content;
- // // 有些响应可能包含reasoning_content而不是content
- // const reasoningContent = delta.reasoning_content || '';
-
- // // 只有当content不是null且有值,或者reasoningContent有值时才添加
- // const textToAdd = (content !== null && content !== undefined) ? content : reasoningContent;
-
- // if (textToAdd) {
- // result += textToAdd;
- // // 确保messages[currentAiMessageIndex]存在
- // if (this.currentAiMessageIndex >= 0 && this.currentAiMessageIndex < this.messages.length) {
- // this.messages[this.currentAiMessageIndex].content = result;
- // this.messages[this.currentAiMessageIndex].renderedContent = renderMarkdown(result);
-
- // // 滚动到底部,但限制频率以提高性能
- // this.throttledScrollToBottom();
- // }
- // }
- // } catch (e) {
- // console.error('解析流数据失败:', e, line);
- // }
- // }
- // }
- // }
+ // Update message content
+ if (this.currentAiMessageIndex >= 0 && this.currentAiMessageIndex < this.messages.length) {
+ this.messages[this.currentAiMessageIndex].content = result;
+ this.messages[this.currentAiMessageIndex].renderedContent = renderMarkdown(result);
+ this.throttledScrollToBottom();
+ }
+ } catch (e) {
+ console.error('解析流数据失败:', e, line);
+ }
+ }
+ }
- // return result;
- // } catch (error) {
- // console.error('调用DeepSeek流式API失败:', error);
- // // 如果出错,确保移除空的AI消息
- // if (this.messages.length > 0 && this.messages[this.messages.length - 1].content === '') {
- // this.messages.pop();
- // this.currentAiMessageIndex = -1;
- // }
- // throw error;
- // }
+ // Process any remaining data in buffer
+ if (buffer.trim()) {
+ try {
+ let data = buffer;
+ if (buffer.startsWith('data:')) {
+ data = buffer.substring(5).trim();
+ }
+ if (data && data !== '[DONE]') {
+ // For JSON data
+ if (data.startsWith('{') && data.endsWith('}')) {
+ try {
+ const parsed = JSON.parse(data);
+ const content = parsed.choices?.[0]?.delta?.content || '';
+ if (content) {
+ result += content;
+ }
+ } catch (e) {
+ // If not valid JSON, treat as plain text
+ result += data;
+ }
+ } else {
+ // For plain text data
+ result += data;
+ }
+
+ this.messages[this.currentAiMessageIndex].content = result;
+ this.messages[this.currentAiMessageIndex].renderedContent = renderMarkdown(result);
+ this.throttledScrollToBottom();
+ }
+ } catch (e) {
+ console.error('处理剩余数据失败:', e, buffer);
+ }
+ }
+
+ // Ensure message is marked as complete
+ if (this.currentAiMessageIndex >= 0 && this.currentAiMessageIndex < this.messages.length) {
+ this.messages[this.currentAiMessageIndex].endStatus = true;
+ }
+
+ return result;
+ } catch (error) {
+ console.error('调用流式API失败:', error);
+ // If error occurs, ensure empty AI message is removed
+ if (this.messages.length > 0 && this.messages[this.messages.length - 1].content === '') {
+ this.messages.pop();
+ this.currentAiMessageIndex = -1;
+ }
+ throw error;
+ }
},
- // 使用普通请求(非H5环境)
+ // Use normal request (non-H5 environment)
async fetchNormalResponse(apiMessages) {
try {
- // 添加一个空的AI回复
+ // Add an empty AI reply
this.currentAiMessageIndex = this.messages.length;
this.messages.push({
role: 'assistant',
@@ -484,46 +399,37 @@ export default {
});
const response = await uni.request({
- url: 'https://api.siliconflow.cn/v1/chat/completions',
+ url: `${config.baseUrl}/ai/generate`,
method: 'POST',
header: {
- 'Authorization': `Bearer ${this.apiKey}`,
+ 'Authorization': `Bearer ${this.token}`,
+ 'clientid': config.clientId,
'Content-Type': 'application/json'
},
- data: {
- model: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-7B',
- messages: apiMessages,
- stream: false,
- max_tokens: 8192,
- stop: '',
- temperature: 0.6,
- top_p: 0.7,
- top_k: 50,
- frequency_penalty: 0
- },
+ data: apiMessages,
dataType: 'json'
});
- // 检查响应状态
+ // Check response status
if (response.statusCode !== 200) {
throw new Error(`API请求失败: ${response.statusCode}`);
}
- // 获取响应内容
- const result = response.data.choices[0].message.content;
+ // Get response content
+ const result = response.data.content || '';
- // 更新消息内容
+ // Update message content
this.messages[this.currentAiMessageIndex].content = result;
this.messages[this.currentAiMessageIndex].renderedContent = renderMarkdown(result);
this.messages[this.currentAiMessageIndex].endStatus = true;
- // 滚动到底部
+ // Scroll to bottom
this.throttledScrollToBottom();
return result;
} catch (error) {
- console.error('调用DeepSeek API失败:', error);
- // 如果出错,确保移除空的AI消息
+ console.error('调用API失败:', error);
+ // If error occurs, ensure empty AI message is removed
if (this.messages.length > 0 && this.messages[this.messages.length - 1].content === '') {
this.messages.pop();
this.currentAiMessageIndex = -1;
@@ -532,72 +438,42 @@ export default {
}
},
- // 接受剧本
+ // Accept script
acceptScript(scriptContent) {
- // // 使用全局方法返回选择的剧本
- // getApp().globalData.selectedScript = {
- // orderId: this.orderId,
- // content: scriptContent
- // };
- // const pages = getCurrentPages();
- // // 上一个页面实例(假设是 pageA)
- // const prevPage = pages[pages.length - 2];
- // console.log("prevPage",prevPage)
-
uni.showToast({
title: '已确认使用此剧本',
icon: 'success'
});
- // 返回上一页
- // setTimeout(() => {
- // uni.navigateBack();
- // }, 1500);
-
- // 当前页面(假设是 pageB)
- uni.navigateBack({
- delta: 1, // 返回的页面层数,1 表示返回上一个页面
- success: function() {
- // 获取页面栈
- const pages = getCurrentPages();
- // 上一个页面实例(假设是 pageA)
- const prevPage = pages[pages.length - 2];
- console.log("prevPage",prevPage)
- // 调用上一个页面的方法
- prevPage.getAiDramaTxt(scriptContent);
- }
- });
+ // Return to previous page
+ uni.navigateBack({
+ delta: 1, // Number of pages to go back, 1 means return to previous page
+ success: function() {
+ // Get page stack
+ const pages = getCurrentPages();
+ // Previous page instance
+ const prevPage = pages[pages.length - 1];
+ // Call method on previous page
+ if (prevPage && typeof prevPage.getAiDramaTxt === 'function') {
+ prevPage.getAiDramaTxt(scriptContent);
+ }
+ }
+ });
},
- // 节流滚动到底部函数,避免频繁滚动
+ // Throttled scroll to bottom function to avoid frequent scrolling
throttledScrollToBottom() {
- // if (this.scrollTimer) return;
-
- // this.scrollTimer = setTimeout(() => {
- // this.scrollToBottom();
- // this.scrollTimer = null;
- // }, 1000); // 300ms内只执行一次滚动
- this.$u.throttle(this.scrollToBottom, 300)
+ this.$u.throttle(this.scrollToBottom, 300);
},
- // 滚动到底部
+ // Scroll to bottom
scrollToBottom() {
this.$nextTick(() => {
- // 方法1: 使用scrollTop设置滚动位置
- // const query = uni.createSelectorQuery().in(this);
- // query.select('.chat-content').boundingClientRect(data => {
- // if (data) {
- // // 设置一个非常大的值确保滚动到底部
- // this.scrollTop = 999999;
- // }
- // }).exec();
-
- // 方法2: 使用选择器定位到底部锚点元素
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
query.select('#scroll-bottom-anchor').boundingClientRect(data => {
if (data) {
- // 滚动到锚点元素位置
+ // Scroll to anchor element position
uni.pageScrollTo({
selector: '#scroll-bottom-anchor',
duration: 100
@@ -608,13 +484,13 @@ export default {
});
},
- // 加载更多消息(上拉加载)
+ // Load more messages (pull-up loading)
loadMoreMessages() {
- // 这里可以实现加载历史消息的逻辑
- // 目前不需要,保留接口
- this.needScrollToBottom = false; // 上拉加载时禁用自动滚动
+ // Logic for loading history messages can be implemented here
+ // Currently not needed, keeping the interface
+ this.needScrollToBottom = false; // Disable auto-scrolling when pulling up
- // 加载完成后恢复自动滚动
+ // Restore auto-scrolling after loading
setTimeout(() => {
this.needScrollToBottom = true;
}, 1000);
@@ -633,14 +509,11 @@ export default {
.chat-content {
flex: 1;
- background-color: #f5f7fa;
- // padding: 20rpx;
- // padding-bottom: 180rpx; /* 为底部输入框留出空间 */
+ background-color: #f5f7fa;
}
.message-wrapper-box{
- padding: 20rpx;
- // padding-bottom: 180rpx; /* 为底部输入框留出空间 */
+ padding: 20rpx;
}
.message-wrapper {
@@ -683,7 +556,7 @@ export default {
word-break: break-word;
}
-/* Markdown样式 */
+/* Markdown styles */
.markdown-body {
color: #333;
}
@@ -699,21 +572,16 @@ export default {
color: #909399;
}
-/* 固定在底部的输入区域 */
+/* Input area fixed at the bottom */
.chat-input-container {
- // position: fixed;
- // bottom: 0;
- // left: 0;
- // right: 0;
background-color: #fff;
border-top: 1px solid #ebeef5;
padding: 20rpx 30rpx;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
z-index: 100;
- // min-height: 170rpx;
- margin-top: auto;
- position: sticky;
- bottom: 0;
+ margin-top: auto;
+ position: sticky;
+ bottom: 0;
}
.chat-input {
@@ -722,13 +590,10 @@ export default {
}
.bottom-placeholder {
- height: 40rpx; /* 确保内容不被输入框遮挡 */
+ height: 40rpx; /* Ensure content is not hidden by input box */
}
.accept-button-container {
- // display: flex;
- // justify-content: flex-start;
- // margin-top: 20rpx;
margin-bottom: 40rpx;
}
@@ -748,4 +613,5 @@ export default {
.button-icon {
margin-right: 8rpx;
}
-
\ No newline at end of file
+
+
diff --git a/pages/fun/videoView.vue b/pages/fun/videoView.vue
index 7b17f10..d379da5 100644
--- a/pages/fun/videoView.vue
+++ b/pages/fun/videoView.vue
@@ -27,13 +27,13 @@
-
+