641 lines
15 KiB
JavaScript
641 lines
15 KiB
JavaScript
![]() |
//index.js
|
|||
|
const app = getApp()
|
|||
|
import TextDecoder from '../../utils/miniprogram-text-decoder'
|
|||
|
Page({
|
|||
|
data: {
|
|||
|
currentTab: 'ToText', // 初始选择文生视频
|
|||
|
uploadedImage: '',
|
|||
|
userInfo: {},
|
|||
|
videoUrl: '',
|
|||
|
uuid: '',
|
|||
|
inputValue: '',
|
|||
|
charCount: 0,
|
|||
|
picInputValue: '',
|
|||
|
picCharCount: 0,
|
|||
|
sizes: [{
|
|||
|
ratio: '1:1',
|
|||
|
width: 1080,
|
|||
|
height: 1080
|
|||
|
},
|
|||
|
{
|
|||
|
ratio: '16:9',
|
|||
|
width: 1920,
|
|||
|
height: 1080
|
|||
|
},
|
|||
|
{
|
|||
|
ratio: '9:16',
|
|||
|
width: 1080,
|
|||
|
height: 1920
|
|||
|
},
|
|||
|
{
|
|||
|
ratio: '4:3',
|
|||
|
width: 1440,
|
|||
|
height: 1080
|
|||
|
},
|
|||
|
{
|
|||
|
ratio: '3:4',
|
|||
|
width: 1080,
|
|||
|
height: 1440
|
|||
|
}
|
|||
|
],
|
|||
|
selectedSize: '9:16',
|
|||
|
selectedWidth: 1080,
|
|||
|
selectedHeight: 1920,
|
|||
|
styles: {
|
|||
|
abandoned: '废弃',
|
|||
|
abstract_sculpture: '抽象',
|
|||
|
advertising: '广告',
|
|||
|
anime: '动漫',
|
|||
|
cine_lens: '电影镜头',
|
|||
|
cinematic: '电影',
|
|||
|
concept_art: '艺术',
|
|||
|
forestpunk: '赛博朋克',
|
|||
|
frost: '雪',
|
|||
|
graphite: '石墨',
|
|||
|
macro_photography: '宏观',
|
|||
|
pixel_art: '像素艺术',
|
|||
|
retro_photography: '复古',
|
|||
|
sci_fi_art: '科幻',
|
|||
|
thriller: '惊悚',
|
|||
|
'35mm': '35mm',
|
|||
|
vector: '矢量',
|
|||
|
watercolor: '水彩'
|
|||
|
},
|
|||
|
selectedStyle: '',
|
|||
|
enhanceValue: 5, // 初始值设置为5
|
|||
|
picEnhanceValue: 5,
|
|||
|
|
|||
|
ShowPicUrl: '',
|
|||
|
tempImg: null, // 图片
|
|||
|
messages: {},
|
|||
|
messagesTemp: {
|
|||
|
is_response: true,
|
|||
|
content: '您好,我是智能AI助手,请问有什么可以帮助您的?'
|
|||
|
},
|
|||
|
inputMessage: "",
|
|||
|
toView: 'toBottom1',
|
|||
|
showRoleDropdown: false,
|
|||
|
currentRole: 9, // 默认角色
|
|||
|
currentRoleText: '选择角色',
|
|||
|
roles: []
|
|||
|
|
|||
|
},
|
|||
|
|
|||
|
|
|||
|
// 文生视频提交
|
|||
|
textGenerateSubmit() {
|
|||
|
if (this.data.inputValue === "") {
|
|||
|
wx.showToast({
|
|||
|
title: '请输入视频描述',
|
|||
|
icon: 'error'
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
let userId = wx.getStorageSync('userId')
|
|||
|
const data = {
|
|||
|
user_id: userId,
|
|||
|
text_prompt: this.data.inputValue,
|
|||
|
width: this.data.selectedWidth,
|
|||
|
height: this.data.selectedHeight,
|
|||
|
motion_score: this.data.enhanceValue,
|
|||
|
style: this.data.selectedStyle
|
|||
|
}
|
|||
|
wx.showLoading({
|
|||
|
title: '任务提交中',
|
|||
|
})
|
|||
|
app.apiRequest({
|
|||
|
url: "/myapp/generate_video/",
|
|||
|
method: "POST",
|
|||
|
data,
|
|||
|
success: res => {
|
|||
|
console.log('res', res);
|
|||
|
if (res.data.success === false) {
|
|||
|
wx.showModal({
|
|||
|
title: "文生视频",
|
|||
|
content: "哎呀!创意点数不足, 请充值",
|
|||
|
confirmColor: "#00B269",
|
|||
|
cancelColor: "#858585",
|
|||
|
success: function (e) {
|
|||
|
e.confirm ? (console.log("确定"), wx.navigateTo({
|
|||
|
url: "../vip_recharge/vip_recharge?show=true"
|
|||
|
})) : e.cancel && console.log("取消");
|
|||
|
}
|
|||
|
})
|
|||
|
} else {
|
|||
|
wx.navigateTo({
|
|||
|
url: '/pages/tips/tips',
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
fail: err => {
|
|||
|
console.log('err', err);
|
|||
|
},
|
|||
|
complete: () => {
|
|||
|
wx.hideLoading()
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
// 图生视频提交
|
|||
|
async picGenerateSubmit() {
|
|||
|
if (this.data.ShowPicUrl === "") {
|
|||
|
wx.showToast({
|
|||
|
title: '请上传图片',
|
|||
|
icon: 'error'
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
if (this.data.picInputValue === "") {
|
|||
|
wx.showToast({
|
|||
|
title: '请输入视频描述',
|
|||
|
icon: 'error'
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
let imageUrl = ''
|
|||
|
wx.showLoading({
|
|||
|
title: '任务提交中',
|
|||
|
})
|
|||
|
try {
|
|||
|
let res = await app.uploadFile(this.data.ShowPicUrl)
|
|||
|
imageUrl = app.globalData.apiDomain + JSON.parse(res).file_url
|
|||
|
} catch (error) {
|
|||
|
console.log('error', error);
|
|||
|
wx.hideLoading()
|
|||
|
wx.showToast({
|
|||
|
title: '图片上传失败,请稍后重试~',
|
|||
|
icon: 'error'
|
|||
|
});
|
|||
|
return
|
|||
|
}
|
|||
|
let userId = wx.getStorageSync('userId')
|
|||
|
const data = {
|
|||
|
user_id: userId,
|
|||
|
image_url: imageUrl,
|
|||
|
text_prompt: this.data.picInputValue,
|
|||
|
motion_score: this.data.picEnhanceValue
|
|||
|
}
|
|||
|
app.apiRequest({
|
|||
|
url: "/myapp/generate_image_video/",
|
|||
|
method: "POST",
|
|||
|
data,
|
|||
|
success: res => {
|
|||
|
console.log('res', res);
|
|||
|
if (res.data.success === false) {
|
|||
|
wx.showModal({
|
|||
|
title: "图生视频",
|
|||
|
content: "哎呀!创意点数不足, 请充值",
|
|||
|
confirmColor: "#00B269",
|
|||
|
cancelColor: "#858585",
|
|||
|
success: function (e) {
|
|||
|
e.confirm ? (console.log("确定"), wx.navigateTo({
|
|||
|
url: "../vip_recharge/vip_recharge?show=true"
|
|||
|
})) : e.cancel && console.log("取消");
|
|||
|
}
|
|||
|
})
|
|||
|
} else {
|
|||
|
wx.navigateTo({
|
|||
|
url: '/pages/tips/tips',
|
|||
|
})
|
|||
|
|
|||
|
}
|
|||
|
},
|
|||
|
fail: err => {
|
|||
|
console.log('err', err);
|
|||
|
},
|
|||
|
complete: () => {
|
|||
|
wx.hideLoading()
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
// 点击上传图片
|
|||
|
uploadImage() {
|
|||
|
let that = this
|
|||
|
wx.chooseMedia({
|
|||
|
count: 1,
|
|||
|
mediaType: ['image'],
|
|||
|
sourceType: ['album'],
|
|||
|
success(res) {
|
|||
|
console.log(res)
|
|||
|
let tempImg = res.tempFiles[0]
|
|||
|
let pictureSize = tempImg.size
|
|||
|
let ShowPicUrl = tempImg.tempFilePath
|
|||
|
if (pictureSize > 1024 * 1024 * 10) {
|
|||
|
wx.showToast({
|
|||
|
title: '图片大小不能超过10MB',
|
|||
|
icon: 'error'
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
that.setData({
|
|||
|
tempImg,
|
|||
|
ShowPicUrl
|
|||
|
})
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
switchNav(e) {
|
|||
|
const nav = e.currentTarget.dataset.nav;
|
|||
|
console.log(nav)
|
|||
|
this.setData({
|
|||
|
currentTab: nav
|
|||
|
});
|
|||
|
},
|
|||
|
// 文生视频输入
|
|||
|
onInput(e) {
|
|||
|
const value = e.detail.value;
|
|||
|
this.setData({
|
|||
|
inputValue: value,
|
|||
|
charCount: value.length
|
|||
|
});
|
|||
|
},
|
|||
|
// 图生视频输入
|
|||
|
onPicInput(e) {
|
|||
|
const value = e.detail.value;
|
|||
|
this.setData({
|
|||
|
picInputValue: value,
|
|||
|
picCharCount: value.length
|
|||
|
});
|
|||
|
},
|
|||
|
optimizePrompt() {
|
|||
|
// 优化提示词的逻辑
|
|||
|
console.log("优化提示词按钮被点击");
|
|||
|
// 可以在这里实现优化提示词的功能
|
|||
|
},
|
|||
|
// 文生视频运动增强
|
|||
|
onSliderChange(e) {
|
|||
|
const value = e.detail.value;
|
|||
|
this.setData({
|
|||
|
enhanceValue: value
|
|||
|
});
|
|||
|
},
|
|||
|
// 图生视频运动增强
|
|||
|
onPicSliderChange(e) {
|
|||
|
const value = e.detail.value;
|
|||
|
this.setData({
|
|||
|
picEnhanceValue: value
|
|||
|
});
|
|||
|
},
|
|||
|
selectStyle(e) {
|
|||
|
const {
|
|||
|
key
|
|||
|
} = e.currentTarget.dataset;
|
|||
|
this.setData({
|
|||
|
selectedStyle: key
|
|||
|
});
|
|||
|
},
|
|||
|
selectSize(e) {
|
|||
|
const {
|
|||
|
ratio,
|
|||
|
width,
|
|||
|
height
|
|||
|
} = e.currentTarget.dataset;
|
|||
|
this.setData({
|
|||
|
selectedSize: ratio,
|
|||
|
selectedWidth: width,
|
|||
|
selectedHeight: height
|
|||
|
});
|
|||
|
},
|
|||
|
onSliderChange(e) {
|
|||
|
const value = e.detail.value;
|
|||
|
this.setData({
|
|||
|
enhanceValue: value
|
|||
|
});
|
|||
|
},
|
|||
|
onLoad: function (options) {
|
|||
|
let uuid = options.uuid || ''
|
|||
|
this.setData({
|
|||
|
uuid: uuid
|
|||
|
})
|
|||
|
wx.showShareMenu({
|
|||
|
withShareTicket: true,
|
|||
|
menus: ['shareAppMessage', 'shareTimeline']
|
|||
|
})
|
|||
|
|
|||
|
// 获取角色列表
|
|||
|
this.getRoles()
|
|||
|
// 获取聊天记录
|
|||
|
this.getChatRecords()
|
|||
|
},
|
|||
|
// 获取角色列表
|
|||
|
getRoles() {
|
|||
|
let that = this
|
|||
|
wx.showLoading({
|
|||
|
title: '加载中',
|
|||
|
})
|
|||
|
app.chatApiRequest({
|
|||
|
url: "/chat/getRoles",
|
|||
|
method: "GET",
|
|||
|
success: res => {
|
|||
|
console.log('res', res)
|
|||
|
this.setData({
|
|||
|
roles: res.data.roles,
|
|||
|
currentRole: 9 // 默认9 AI助手
|
|||
|
})
|
|||
|
},
|
|||
|
fail: err => {
|
|||
|
console.log('err', err)
|
|||
|
},
|
|||
|
complete: () => {
|
|||
|
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
// 获取聊天记录
|
|||
|
getChatRecords() {
|
|||
|
let that = this
|
|||
|
let userId = wx.getStorageSync('userId')
|
|||
|
let openId = wx.getStorageSync('openid')
|
|||
|
wx.showLoading({
|
|||
|
title: '加载中',
|
|||
|
})
|
|||
|
app.chatApiRequest({
|
|||
|
url: '/chat/getRecord',
|
|||
|
method: 'POST',
|
|||
|
data: {
|
|||
|
nickname: userId,
|
|||
|
openid: openId,
|
|||
|
role_id: this.data.currentRole
|
|||
|
},
|
|||
|
success: (res) => {
|
|||
|
let messages = this.data.messages
|
|||
|
messages[that.data.currentRole] = res.data.records
|
|||
|
that.setData({
|
|||
|
messages
|
|||
|
})
|
|||
|
that.scrollToBottom()
|
|||
|
},
|
|||
|
fail: (err) => {
|
|||
|
console.log('err', err)
|
|||
|
},
|
|||
|
complete: () => {
|
|||
|
wx.hideLoading()
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
bindInput(e) {
|
|||
|
this.setData({
|
|||
|
inputMessage: e.detail.value
|
|||
|
});
|
|||
|
},
|
|||
|
|
|||
|
// 滚动条置底
|
|||
|
scrollToBottom() {
|
|||
|
this.setData({
|
|||
|
toView: this.data.toView === 'toBottom1' ? 'toBottom2' : 'toBottom1'
|
|||
|
});
|
|||
|
},
|
|||
|
|
|||
|
// 发送
|
|||
|
sendMessage() {
|
|||
|
let that = this
|
|||
|
let inputMessage = this.data.inputMessage
|
|||
|
if (inputMessage === '') {
|
|||
|
wx.showToast({
|
|||
|
title: '请输入消息',
|
|||
|
icon: 'none'
|
|||
|
})
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
let messages = that.data.messages
|
|||
|
// 获取会话session_id
|
|||
|
let sessionID
|
|||
|
if (messages[this.data.currentRole].length !== 0) {
|
|||
|
sessionID = messages[this.data.currentRole][messages[this.data.currentRole].length - 1].session_id
|
|||
|
}
|
|||
|
messages[this.data.currentRole].push({
|
|||
|
is_response: false,
|
|||
|
message_content: inputMessage
|
|||
|
})
|
|||
|
this.setData({
|
|||
|
inputMessage: ''
|
|||
|
})
|
|||
|
|
|||
|
messages[this.data.currentRole].push({
|
|||
|
is_response: true,
|
|||
|
message_content: '',
|
|||
|
isGenerating: true
|
|||
|
})
|
|||
|
that.setData({
|
|||
|
messages: messages,
|
|||
|
})
|
|||
|
this.scrollToBottom()
|
|||
|
let userId = wx.getStorageSync('userId')
|
|||
|
let openid = wx.getStorageSync('openid')
|
|||
|
let role = this.data.currentRole
|
|||
|
|
|||
|
|
|||
|
let reqTask = app.chatApiRequest({
|
|||
|
url: '/chat/send',
|
|||
|
method: 'POST',
|
|||
|
enableChunked: true,
|
|||
|
data: {
|
|||
|
openid,
|
|||
|
userid: userId,
|
|||
|
prompt: inputMessage,
|
|||
|
role_id: role,
|
|||
|
session_id: sessionID
|
|||
|
},
|
|||
|
success: (res) => {
|
|||
|
// console.log('res', res)
|
|||
|
},
|
|||
|
fail: (err) => {
|
|||
|
console.log('err', err)
|
|||
|
}
|
|||
|
})
|
|||
|
let newMessages = this.data.messages
|
|||
|
let currentMessages = newMessages[this.data.currentRole]
|
|||
|
let lastMessages = currentMessages[currentMessages.length - 1]
|
|||
|
reqTask.onChunkReceived(r => {
|
|||
|
let decoder = new TextDecoder('utf-8');
|
|||
|
let str = decoder.decode(r.data);
|
|||
|
let lines = str.split('\n\n')
|
|||
|
lines.pop()
|
|||
|
for (let i of lines) {
|
|||
|
let jsonStr = i
|
|||
|
if (i.startsWith("data:")) {
|
|||
|
jsonStr = jsonStr.substring(5);
|
|||
|
}
|
|||
|
let messageObject = JSON.parse(jsonStr)
|
|||
|
lastMessages.isGenerating = false
|
|||
|
lastMessages.message_content += messageObject.output.text
|
|||
|
lastMessages.session_id = messageObject.output.session_id
|
|||
|
this.setData({
|
|||
|
messages: newMessages
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
that.scrollToBottom()
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
utf8ArrayToStr(array) {
|
|||
|
var out, i, len, c;
|
|||
|
var char2, char3;
|
|||
|
|
|||
|
out = "";
|
|||
|
len = array.length;
|
|||
|
i = 0;
|
|||
|
while (i < len) {
|
|||
|
c = array[i++];
|
|||
|
switch (c >> 4) {
|
|||
|
case 0:
|
|||
|
case 1:
|
|||
|
case 2:
|
|||
|
case 3:
|
|||
|
case 4:
|
|||
|
case 5:
|
|||
|
case 6:
|
|||
|
case 7:
|
|||
|
// 0xxxxxxx
|
|||
|
out += String.fromCharCode(c);
|
|||
|
break;
|
|||
|
case 12:
|
|||
|
case 13:
|
|||
|
// 110x xxxx 10xx xxxx
|
|||
|
char2 = array[i++];
|
|||
|
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
|
|||
|
break;
|
|||
|
case 14:
|
|||
|
// 1110 xxxx 10xx xxxx 10xx xxxx
|
|||
|
char2 = array[i++];
|
|||
|
char3 = array[i++];
|
|||
|
out += String.fromCharCode(((c & 0x0F) << 12) |
|
|||
|
((char2 & 0x3F) << 6) |
|
|||
|
((char3 & 0x3F) << 0));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return out;
|
|||
|
},
|
|||
|
|
|||
|
|
|||
|
toggleRoleDropdown() {
|
|||
|
this.setData({
|
|||
|
showRoleDropdown: !this.data.showRoleDropdown,
|
|||
|
});
|
|||
|
},
|
|||
|
switchRole(event) {
|
|||
|
const roleIndex = event.currentTarget.dataset.role;
|
|||
|
this.setData({
|
|||
|
currentRole: this.data.roles[roleIndex].id,
|
|||
|
currentRoleText: this.data.roles[roleIndex].name,
|
|||
|
showRoleDropdown: false,
|
|||
|
});
|
|||
|
this.getChatRecords()
|
|||
|
// 在这里你可以根据需要添加更多逻辑,比如切换到不同的AI模型
|
|||
|
},
|
|||
|
|
|||
|
// 判断邀请用户
|
|||
|
sendReward_invitation: function (uuid) {
|
|||
|
app.apiRequest({
|
|||
|
url: '/myapp/reward_invitation', // 后端接口URL
|
|||
|
method: 'POST',
|
|||
|
data: {
|
|||
|
openid: wx.getStorageSync('openid'),
|
|||
|
uuid: uuid,
|
|||
|
},
|
|||
|
success(res) {
|
|||
|
console.log(res);
|
|||
|
if (res.data.success == true) {
|
|||
|
wx.setStorageSync('defaultDailyFreeParseNum', wx.getStorageSync('defaultDailyFreeParseNum') + 10);
|
|||
|
}
|
|||
|
},
|
|||
|
fail(err) {
|
|||
|
console.error(err);
|
|||
|
// 错误处理
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
},
|
|||
|
|
|||
|
|
|||
|
onShow() {
|
|||
|
app.getCurrentTabbar(1, this);
|
|||
|
app.checkUpdateVersion()
|
|||
|
wx.showLoading()
|
|||
|
app.getUserInfo().then(() => {
|
|||
|
if (this.data.uuid != '' && wx.getStorageSync('openid') != '' && wx.getStorageSync('uuid') != this.data.uuid) {
|
|||
|
this.sendReward_invitation(this.data.uuid);
|
|||
|
}
|
|||
|
}).catch(error => {
|
|||
|
console.error('获取用户信息失败:', error);
|
|||
|
}).finally(() => {
|
|||
|
console.log('getUserInfo调用完成');
|
|||
|
});
|
|||
|
},
|
|||
|
|
|||
|
// 清空输入框
|
|||
|
inputClear: function () {
|
|||
|
this.setData({
|
|||
|
videoUrl: ''
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
copyContent(e) {
|
|||
|
console.log(e)
|
|||
|
const content = e.target.dataset.content;
|
|||
|
wx.setClipboardData({
|
|||
|
data: content,
|
|||
|
success() {
|
|||
|
wx.showToast({
|
|||
|
title: '内容已复制',
|
|||
|
icon: 'none',
|
|||
|
});
|
|||
|
},
|
|||
|
fail(err) {
|
|||
|
wx.showToast({
|
|||
|
title: '复制失败',
|
|||
|
icon: 'none',
|
|||
|
});
|
|||
|
console.error('复制失败', err);
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
|
|||
|
onShareAppMessage: function () {
|
|||
|
return {
|
|||
|
title: '推荐一款免费又超好用的AI视频文案创作工具,快来体验吧',
|
|||
|
path: '/pages/index/index?uuid=' + wx.getStorageSync('uuid'),
|
|||
|
imageUrl: '/images/index.jpg',
|
|||
|
success: function (e) {
|
|||
|
wx.showToast({
|
|||
|
title: "分享成功",
|
|||
|
icon: "success",
|
|||
|
duration: 2e3
|
|||
|
});
|
|||
|
},
|
|||
|
fail: function (e) {
|
|||
|
wx.showToast({
|
|||
|
title: "分享失败",
|
|||
|
icon: "none",
|
|||
|
duration: 2e3
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
onShareTimeline: function () {
|
|||
|
return {
|
|||
|
title: '推荐一款免费又超好用的AI视频文案创作工具,快来体验吧',
|
|||
|
path: '/pages/index/index?uuid=' + wx.getStorageSync('uuid'),
|
|||
|
imageUrl: '/images/index.jpg',
|
|||
|
success: function (e) {
|
|||
|
wx.showToast({
|
|||
|
title: "分享成功",
|
|||
|
icon: "success",
|
|||
|
duration: 2e3
|
|||
|
});
|
|||
|
},
|
|||
|
fail: function (e) {
|
|||
|
wx.showToast({
|
|||
|
title: "分享失败",
|
|||
|
icon: "none",
|
|||
|
duration: 2e3
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
})
|