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
 | ||
|         });
 | ||
|       }
 | ||
|     }
 | ||
|   },
 | ||
| }) | 
