first commit
This commit is contained in:
641
pages/aitools/aitools.js
Normal file
641
pages/aitools/aitools.js
Normal file
@@ -0,0 +1,641 @@
|
||||
//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
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
7
pages/aitools/aitools.json
Normal file
7
pages/aitools/aitools.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {},
|
||||
"navigationBarTitleText": "创作助手",
|
||||
"navigationBarBackgroundColor": "#222238",
|
||||
"navigationBarTextStyle": "white",
|
||||
"custom-tab-bar": "/custom-tab-bar/index"
|
||||
}
|
||||
73
pages/aitools/aitools.wxml
Normal file
73
pages/aitools/aitools.wxml
Normal file
@@ -0,0 +1,73 @@
|
||||
<view class="container">
|
||||
<view class="navbar"></view>
|
||||
<view wx:if="{{currentTab==='textToVideo'}}">
|
||||
<view class="input-container">
|
||||
<textarea bindinput="onInput" class="input-box" maxlength="320" placeholder="输入文本或者图片即可生成原创视频,请用一句话描述您的视频主题、场景、风格等,简洁明了!" value="{{inputValue}}"></textarea>
|
||||
<view class="char-count">{{charCount}}/320</view>
|
||||
</view>
|
||||
<view class="style-selector">
|
||||
<view class="style-text">选择风格:</view>
|
||||
<view class="style-options">
|
||||
<view bindtap="selectStyle" class="style-option {{selectedStyle===key?'active':''}}" data-key="{{key}}" wx:for="{{styles}}" wx:for-index="key" wx:for-item="style" wx:key="{{key}}"> {{style}} </view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="size-selector">
|
||||
<text class="size-text">选择尺寸:</text>
|
||||
<view class="size-options">
|
||||
<view bindtap="selectSize" class="size-option {{selectedSize===item.ratio?'active':''}}" data-height="{{item.height}}" data-ratio="{{item.ratio}}" data-width="{{item.width}}" wx:for="{{sizes}}" wx:key="index"> {{item.ratio}} </view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="enhance-container">
|
||||
<text class="enhance-text">运动增强:</text>
|
||||
<slider showValue bindchange="onSliderChange" class="enhance-slider" max="10" min="0" value="{{enhanceValue}}"></slider>
|
||||
</view>
|
||||
<text class="description-text">数值越高,视频画面越丰富 【文生视频消耗 10创意点/次】</text>
|
||||
<button bindtap="textGenerateSubmit" class="generate-button">生成视频</button>
|
||||
</view>
|
||||
<view class="full-container" wx:if="{{currentTab==='imageToVideo'}}">
|
||||
<view bindtap="uploadImage" class="upload-container">
|
||||
<image class="upload-pic" mode="aspectFit" src="{{ShowPicUrl}}" wx:if="{{ShowPicUrl}}"></image>
|
||||
<view class="upload-wrap" wx:else>
|
||||
<image class="upload-icon" src="/images/icon-upload.png"></image>
|
||||
<text class="upload-text">
|
||||
<text class="upload-link">点击上传图片</text>
|
||||
</text>
|
||||
<text class="upload-info">只能上传jpg/png文件,且不超过10MB</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="img-input-container">
|
||||
<textarea bindinput="onPicInput" class="input-box" maxlength="320" placeholder="输入提示词来描述您想要的视频内容" value="{{picInputValue}}"></textarea>
|
||||
<view class="char-count">{{picCharCount}}/320</view>
|
||||
</view>
|
||||
<view class="enhance-container" style="margin-top: 10px;">
|
||||
<text class="enhance-text">运动增强:</text>
|
||||
<slider showValue bindchange="onPicSliderChange" class="enhance-slider" max="10" min="0" value="{{picEnhanceValue}}"></slider>
|
||||
</view>
|
||||
<text class="description-text" style="float: left;">数值越高,视频画面越丰富 【图生视频消耗 10创意点/次】</text>
|
||||
<button bindtap="picGenerateSubmit" class="generate-button">生成视频</button>
|
||||
</view>
|
||||
<view class="chat-box" wx:if="{{currentTab==='ToText'}}">
|
||||
<view class="role-switch">
|
||||
<button bindtap="toggleRoleDropdown" class="role-button">{{currentRoleText}} <image class="role-icon" src="../../images/切换角色.png"></image>
|
||||
</button>
|
||||
<view class="role-dropdown" wx:if="{{showRoleDropdown}}">
|
||||
<view bindtap="switchRole" class="role-option" data-role="{{index}}" wx:for="{{roles}}" wx:key="index">{{item.name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="chat-window" scrollIntoView="{{toView}}" scrollY="true">
|
||||
<view class="message {{item.is_response?'ai':'user'}}" wx:for="{{messages[currentRole?currentRole:9]}}" wx:key="index">
|
||||
<image class="avatar" src="{{item.is_response?'../../images/人工智能机器人.png':'../../images/老师教师男人.png'}}"></image>
|
||||
<view class="bubble">
|
||||
<view class="loading-dot" wx:if="{{item.isGenerating}}"></view>
|
||||
<text bindtap="copyContent" class="content" data-content="{{item.message_content}}" wx:else>{{item.message_content}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view id="toBottom1"></view>
|
||||
<view id="toBottom2"></view>
|
||||
</scroll-view>
|
||||
<view class="input-area">
|
||||
<input autoHeight adjust-position='true' bindinput="bindInput" class="input-field" placeholder="请输入消息..." value="{{inputMessage}}"></input>
|
||||
<button bindtap="sendMessage" class="send-button">发送</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
414
pages/aitools/aitools.wxss
Normal file
414
pages/aitools/aitools.wxss
Normal file
@@ -0,0 +1,414 @@
|
||||
.container,page {
|
||||
background-color: #222238;
|
||||
}
|
||||
|
||||
.container {
|
||||
border-top: 1px solid hsla(0,31%,87%,.5);
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
padding: 10px 10px 61px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: linear-gradient(180deg,#8d72d2,#7183f3);
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
color: #fff;
|
||||
flex: 1;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
background: linear-gradient(90deg,#6949bb,#4d65fd);
|
||||
border-bottom: 3px solid #d9d4e4;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
color: #a790e2;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
margin: 10px 0;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
background-color: #333;
|
||||
border: none;
|
||||
color: #fff;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.char-count {
|
||||
bottom: 10px;
|
||||
color: #ccc;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.optimize-button {
|
||||
background: linear-gradient(90deg,#6949bb,#4d65fd);
|
||||
border-radius: 5px;
|
||||
bottom: 3px;
|
||||
font-size: 13px;
|
||||
left: 3px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.platform-selector {
|
||||
background-color: #333;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.platform-text {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.platform-dropdown {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.size-selector,.style-selector {
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.size-text,.style-text {
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.size-options,.style-options {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.size-option,.style-option {
|
||||
background-color: #333;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 3px 3px 1px rgba(0,0,0,.3);
|
||||
color: #fff;
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 10px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
transition: all .3s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.size-option.active,.style-option.active {
|
||||
background-color: #4a90e2;
|
||||
}
|
||||
|
||||
.size-option:last-child,.style-option:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.enhance-container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.enhance-text {
|
||||
font-weight: 700;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.enhance-slider {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.generate-button {
|
||||
background: linear-gradient(90deg,#6949bb,#4d65fd);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: #fff;
|
||||
margin: 10px auto;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.full-container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.upload-container {
|
||||
background-color: #333;
|
||||
border: 1px dashed #666;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,.1);
|
||||
cursor: pointer;
|
||||
height: 250px;
|
||||
margin-top: 15px;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.upload-wrap {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 250px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.upload-pic {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
height: 50px;
|
||||
margin-bottom: 10px;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.upload-link {
|
||||
color: #4a90e2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.upload-info {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.img-input-container {
|
||||
margin-top: 10px;
|
||||
max-width: 400px;
|
||||
min-height: 200px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
font-size: 14px;
|
||||
min-height: 200px;
|
||||
padding: 10px;
|
||||
resize: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.char-count {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.chat-box {
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 127px);
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.chat-box,.role-switch {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.role-switch {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.role-button {
|
||||
align-items: center;
|
||||
background: linear-gradient(180deg,#2b2b49,#26263a);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,.3),0 1px 3px rgba(0,0,0,.08);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.role-icon {
|
||||
height: 16px;
|
||||
margin-left: 5px;
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.role-dropdown {
|
||||
background: linear-gradient(180deg,#2b2b49,#26263a);
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,.3);
|
||||
left: 50%;
|
||||
margin-top: 5px;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.role-option {
|
||||
border-bottom: 1px solid #b39494;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.role-option:hover {
|
||||
background: #444;
|
||||
}
|
||||
|
||||
.chat-window {
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.message .avatar {
|
||||
border-radius: 20px;
|
||||
height: 40px;
|
||||
margin: 0 3px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 5px rgba(0,0,0,.5);
|
||||
color: #d6d3dd;
|
||||
max-width: 70%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.message.user .bubble {
|
||||
background: #6949bb;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.message.ai .bubble {
|
||||
background: #505579;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.username {
|
||||
color: #888;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 14px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.input-area {
|
||||
background-color: #222238;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
min-height: 40px;
|
||||
padding: 8px;
|
||||
|
||||
}
|
||||
|
||||
.send-button {
|
||||
background: linear-gradient(90deg,#6949bb,#4d65fd);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
margin-left: 10px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.buttom {
|
||||
background-color: initial;
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.loading-dot {
|
||||
animation: pulse .8s infinite alternate;
|
||||
background-color: #007bff;
|
||||
border-radius: 50%;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
@-webkit-keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user