gy-app-shop/pages/fun/materialEdit.vue

715 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<view class="select-box" v-if="commitState === 'add'">
<view class="form-label">素材模板</view>
<view class="form-value" @click="openMaterialShow">
<view class="form-select">{{materialfrom.dictId?materialfrom.dictName:'请选择素材模板'}}</view>
<u-icon name="arrow-down-fill" color="#999" size="28"></u-icon>
</view>
</view>
<view class="form-item" v-if="commitState === 'back'">
<text class="form-label">修改意见</text>
<template>
<view class="comment-box">
{{ comment }}
</view>
</template>
</view>
<view class="form-item">
<text class="form-label">剧本 <text class="form-hint">视频的剧本</text> </text>
<!-- 文本输入 -->
<template>
<u-input style="max-height: 500rpx;overflow-y: auto;" :disabled="getDisabledStatus()" maxlength="9999" type='textarea' class="bg-gray" v-model="scriptContent" :placeholder="`请输入剧本`" />
</template>
<u-button @click="openAiDrama" type="primary" :disabled="getDisabledStatus()">Ai生成剧本</u-button>
</view>
<view v-for="(item,index) in materialTemplateList" :key="index" class="form-item">
<text class="form-label">{{ item.attrTitle }} <text class="form-hint">{{ item.attrHint ? '(' +item.attrHint + ')' : '' }}</text> </text>
<!-- 文本输入 -->
<template v-if="item.attrType === 0">
<u-input :disabled="getDisabledStatus()" class="bg-gray" v-model="item.attrValue" :placeholder="`请输入${item.attrTitle}`" />
</template>
<!-- 图片上传 -->
<template v-if="item.attrType === 1">
<view class="upload-area">
<view v-if="item.attrValue" class="preview-wrapper">
<image :src="item.fileUrl" mode="scaleToFill" class="preview-image" @click="previewImage(item.fileUrl)">
</image>
<u-icon v-if="!getDisabledStatus()" name="close" class="delete-icon" @click="deleteFile(item.attrValue,index)"></u-icon>
</view>
<u-button @click="chooseImage(item,index)" type="primary" :disabled="getDisabledStatus()"
:loading="item.uploading">{{ item.attrValue ? '重新上传' : '上传图片' }}</u-button>
<!-- 上传进度条 -->
<view v-if="item.uploadProgress > 0 && item.uploadProgress < 100" class="progress-container">
<u-line-progress :percent="item.uploadProgress" :show-percent="true" height="20"></u-line-progress>
</view>
</view>
</template>
<!-- 音频上传 -->
<template v-if="item.attrType === 2">
<view class="upload-area">
<view v-if="item.attrValue" class="audio-preview">
<text class="audio-name">{{ shortenFileName(item.fileName,20) || '已上传音频文件' }}</text>
<u-icon v-if="!getDisabledStatus()" name="close" class="delete-icon" @click="deleteFile(item.attrValue,index)"></u-icon>
</view>
<u-button @click="chooseAudio(item,index)" type="primary" :disabled="getDisabledStatus()"
:loading="item.uploading">{{ item.attrValue ? '重新上传' : '上传音频' }}</u-button>
<!-- 上传进度条 -->
<view v-if="item.uploadProgress > 0 && item.uploadProgress < 100" class="progress-container">
<u-line-progress :percent="item.uploadProgress" :show-percent="true" height="20"></u-line-progress>
</view>
<text class="upload-tip">{{'最大' + audioSize + 'MB'}}</text>
</view>
</template>
<!-- 视频上传 -->
<template v-if="item.attrType === 3">
<view class="upload-area">
<view v-if="item.attrValue" class="audio-preview">
<!-- <video :src="item.fileUrl" class="preview-video"></video> -->
<text class="audio-name">{{ shortenFileName(item.fileName,20) || '已上传音频文件' }}</text>
<u-icon v-if="!getDisabledStatus()" name="close" class="delete-icon" @click="deleteFile(item.attrValue,index)"></u-icon>
</view>
<u-button @click="chooseVideo(item,index)" type="primary" :disabled="getDisabledStatus()"
:loading="item.uploading">{{ item.attrValue ? '重新上传' : '上传视频' }}</u-button>
<!-- 上传进度条 -->
<view v-if="item.uploadProgress > 0 && item.uploadProgress < 100" class="progress-container">
<u-line-progress :percent="item.uploadProgress" :show-percent="true" height="20"></u-line-progress>
</view>
<text class="upload-tip">{{'最大' + videoSize + 'MB'}}</text>
</view>
</template>
<!-- 用户说明 -->
<u-input v-if="item.attrType !== 0" :disabled="getDisabledStatus()" type="textarea" class="bg-gray" v-model="item.userExplain" placeholder="请输入素材说明" />
<!-- 星级评分 -->
重要级别:<u-rate v-model="item.starLevel" :disabled="getDisabledStatus()" active-color="#f7ba2a" :count="5" />
</view>
<u-select v-model="materialShow" mode="single-column" :list="materialDictList" value-name="id" label-name="dictName" @confirm="changeTemplate"></u-select>
<!-- 提交按钮 -->
<view class="btn-box" v-if="commitState === 'add' || commitState === 'draft' || commitState === 'back'">
<u-button type="default" :loading="buttonLoading" class="bg-grey" @click="verifyForm('draft')">暂存</u-button>
<u-button type="primary" :loading="buttonLoading" @click="verifyForm('submit')">提交</u-button>
</view>
<u-toast ref="uToast" />
</view>
</template>
<script>
import config from '../../common/api/config';
export default {
data() {
return {
token: '',
orderId: "",
productId: "",
orderItemId: "",
// 素材提交状态
commitState:'add',
comment:'',
materialfrom:{
id: undefined,
dictId: undefined,
dictName: undefined,
productId: undefined,
productSn: undefined,
flowId: undefined,
},
// 素材模板列表
materialDictList:[],
materialTemplateList:[],
// 模板选择弹窗
materialShow:false,
audioSize: 10,
videoSize: 100,
audioType: ['.wav', '.mp3', '.aac', '.flac', '.ogg'],
audioH5Type: ['wav', 'mp3', 'aac', 'flac', 'ogg'],
buttonLoading:false,
scriptContent:'',
// videoType: ['.avi', '.mp4', '.mkv', '.flv', '.mov', '.wmv', '.mpeg', '.3gp'],
}
},
onLoad(option) {
console.log("获取参数为",option)
this.orderId = option.orderId;
this.productId = option.productId;
this.orderItemId = option.orderItemId;
this.token = uni.getStorageSync('userToken');
this.getProductDetail();
},
methods: {
getAiDramaTxt(txt){
this.scriptContent = txt;
},
openAiDrama(){
uni.navigateTo({
url:'./AiDrama?orderId=' + this.orderItemId
})
},
getDisabledStatus(){
if(this.commitState !== 'add' && this.commitState !== 'draft' && this.commitState !== 'back'){
return true;
}else{
return false;
}
},
openMaterialShow(){
this.materialShow = true;
},
async changeTemplate(e){
console.log("当前选择",e)
this.materialfrom.dictId = e[0].value;
this.materialfrom.dictName = e[0].label;
let res = await this.$api.orderApi.getProductMaterialDictItemList({ pageNum: 1, pageSize: 100, dictId: e[0].value, orderByColumn: 'orderNum', isAsc: 'asc' })
this.materialTemplateList = res.rows.map((item) => {
item.starLevel = 0;
item.userExplain = '';
item.attrValue = '';
item.orderId = this.orderId;
item.productId = this.productId;
item.orderItemId = this.orderItemId;
item.dictId = this.materialfrom.dictId;
item.id = null;
item.uploading = false;
item.uploadProgress = 0;
return item;
});
},
async getProductDetail(){
let res = await this.$api.orderApi.getOrderMaterialList({ orderItemId: this.orderItemId })
if(res.rows.length!=0){
this.materialfrom.flowId = res.rows[0].id;
this.commitState = res.rows[0].status;
this.comment = res.rows[0].comment || '';
this.scriptContent = res.rows[0].script || '';
this.materialTemplateList = res.rows[0].materialItems || [];
res.rows[0].materialItems.forEach(async (item,index)=>{
// 初始化上传状态和进度
this.$set(this.materialTemplateList[index], 'uploading', false);
this.$set(this.materialTemplateList[index], 'uploadProgress', 0);
if(item.attrType !== 0 && item.attrValue !== ''){
let {fileUrl,fileName} = await this.getFileDetail(item.attrValue);
console.log("fileUrl,fileName",fileUrl,fileName)
this.$nextTick(()=>{
this.$set(this.materialTemplateList[index],'fileUrl',fileUrl)
this.$set(this.materialTemplateList[index],'fileName',fileName)
})
}
})
}else{
this.getMaterialDictList();
}
},
async getFileDetail(ossId){
let res = await this.$api.getOssDetail(ossId)
if(res.code == 200){
return {
fileUrl: res.data[0].url || '',
fileName:res.data[0].originalName || '',
}
}else{
return {
fileUrl:'',
fileName:'',
}
}
},
async getMaterialDictList(){
let res = await this.$api.orderApi.getProductMaterialDictList({ pageNum: 1, pageSize: 100, productId: this.productId })
this.materialDictList = res.rows || [];
},
async getMaterialList(){
let res = await this.$api.orderApi.getMallOrderProductMaterialList({ orderId: this.orderId, productId: this.productId, orderByColumn: 'orderNum', isAsc: 'asc' })
this.materialTemplateList = res.rows || [];
},
shortenFileName(fileName, maxLength = 10) {
if(fileName==undefined){
return '';
}
// 检查文件名是否已经足够短
if (fileName.length <= maxLength) {
return fileName;
}
// 获取文件后缀
const lastDotIndex = fileName.lastIndexOf('.');
const extension = fileName.slice(lastDotIndex); // 包括点号
// 获取文件名(不包括后缀)
const nameWithoutExtension = fileName.slice(0, lastDotIndex);
// 缩短文件名
const shortenedName = nameWithoutExtension.slice(0, maxLength);
// 返回缩短后的文件名,加上后缀
return `${shortenedName}...${extension}`;
},
chooseImage(item, index) {
uni.chooseImage({
count: 1,
success: (res) => {
this.$nextTick(()=>{
this.$set(this.materialTemplateList[index], 'uploading', true);
this.$set(this.materialTemplateList[index], 'uploadProgress', 0);
})
const tempFilePath = res.tempFilePaths[0];
this.uploadFile(tempFilePath, 'image', item, index);
},
fail: () => {
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
}
});
},
chooseVideo(item,index) {
uni.chooseVideo({
count: 1,
maxDuration: 60,
success: (res) => {
this.$nextTick(()=>{
this.$set(this.materialTemplateList[index], 'uploading', true);
this.$set(this.materialTemplateList[index], 'uploadProgress', 0);
})
const tempFilePath = res.tempFilePath;
const fileSize = res.size;
if (fileSize > this.videoSize * 1024 * 1024) {
uni.showToast({
title: '视频大小不能超过' + this.videoSize + 'MB',
icon: 'none'
});
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
return;
}
this.uploadFile(tempFilePath, 'video', item, index);
},
fail: (err) => {
console.error('选择视频失败', err);
uni.showToast({
title: '选择视频失败',
icon: 'none'
});
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
},
complete: () => {
console.log("权限选择视频")
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
}
});
},
chooseAudio(item,index) {
// 注意H5不支持chooseFile需要单独处理
// #ifdef H5
uni.chooseFile({
count: 1,
type: 'all',
extension: this.audioType,
success: (res) => {
this.$nextTick(()=>{
this.$set(this.materialTemplateList[index], 'uploading', true);
this.$set(this.materialTemplateList[index], 'uploadProgress', 0);
})
const tempFilePath = res.tempFiles[0].path;
const fileSize = res.tempFiles[0].size;
const fileName = res.tempFiles[0].name;
if (fileSize > this.audioSize * 1024 * 1024) {
uni.showToast({
title: '音频大小不能超过' + this.audioSize + 'MB',
icon: 'none'
});
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
return;
}
this.uploadFile(tempFilePath, 'audio', item, index, fileName);
},
fail: (err) => {
console.error('选择音频失败', err);
uni.showToast({
title: '选择音频失败',
icon: 'none'
});
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
}
});
// #endif
// #ifndef H5
uni.chooseMessageFile({
count: 1,
type: 'file',
extension: this.audioH5Type,
success: (res) => {
this.$nextTick(()=>{
this.$set(this.materialTemplateList[index], 'uploading', true);
this.$set(this.materialTemplateList[index], 'uploadProgress', 0);
})
const tempFilePath = res.tempFiles[0].path;
const fileSize = res.tempFiles[0].size;
const fileName = res.tempFiles[0].name;
if (fileSize > this.audioSize * 1024 * 1024) {
uni.showToast({
title: '音频大小不能超过' + this.audioSize + 'MB',
icon: 'none'
});
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
return;
}
this.uploadFile(tempFilePath, 'audio', item, index, fileName);
},
fail: (err) => {
console.error('选择音频失败', err);
uni.showToast({
title: '选择音频失败',
icon: 'none'
});
this.materialTemplateList[index].uploading = false;
this.materialTemplateList[index].uploadProgress = 0;
}
});
// #endif
},
uploadFile(filePath, fileType, item, index, fileName = '') {
// 这里应该是您的实际上传接口
const uploadUrl = config.baseUrl + '/resource/oss/upload';
// 创建上传任务
const uploadTask = uni.uploadFile({
url: uploadUrl,
filePath: filePath,
name: 'file',
header: {
'Clientid': config.clientId,
'Authorization': 'Bearer ' + this.token
},
success: (uploadRes) => {
const data = JSON.parse(uploadRes.data);
console.log("data", data)
// 假设服务器返回的是文件的URL
this.materialTemplateList[index].attrValue = data.data.ossId;
this.materialTemplateList[index].fileUrl = data.data.url;
this.materialTemplateList[index].fileName = data.data.fileName;
uni.showToast({
title: '上传成功',
icon: 'success'
});
},
fail: (err) => {
console.error('上传失败', err);
uni.showToast({
title: '上传失败',
icon: 'none'
});
},
complete: () => {
console.log('上传结束');
this.materialTemplateList[index].uploading = false;
// 完成后将进度设为100然后延迟一会儿再设为0以显示完成效果
this.materialTemplateList[index].uploadProgress = 100;
setTimeout(() => {
this.materialTemplateList[index].uploadProgress = 0;
}, 500);
}
});
// 监听上传进度
uploadTask.onProgressUpdate((res) => {
console.log('上传进度', res.progress - 15);
console.log('已经上传的数据长度', res.totalBytesSent);
console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend);
let progress = (res.progress - 15 > 0)?(res.progress - 15) : res.progress;
this.materialTemplateList[index].uploadProgress = progress;
});
},
deleteFile(item,index) {
uni.showModal({
title: '确认删除',
content: '是否确认删除该文件?',
success: (res) => {
if (res.confirm) {
this.$api.orderApi.delOssFile(this.materialTemplateList[index].attrValue)
this.materialTemplateList[index].attrValue = '';
this.materialTemplateList[index].fileUrl = '';
this.materialTemplateList[index].fileName = '';
this.materialTemplateList[index].uploadProgress = 0;
uni.showToast({
title: '删除成功',
icon: 'success'
});
}
}
});
},
previewImage(url) {
uni.previewImage({
urls: [url],
current: 0
});
},
verifyForm(status){
console.log('提交的表单数据:', this.materialTemplateList);
if(!this.materialfrom.dictId && this.commitState === 'add'){
this.$refs.uToast.show({
title: '请选择素材模板',
type: 'error',
})
return;
}
if(this.materialTemplateList.length==0){
this.$refs.uToast.show({
title: '请选择有素材项的模板',
type: 'error',
})
return;
}
// 检查是否有正在上传的文件
const isUploading = this.materialTemplateList.some(item => item.uploading || (item.uploadProgress > 0 && item.uploadProgress < 100));
if (isUploading) {
this.$refs.uToast.show({
title: '请等待文件上传完成',
type: 'warning',
})
return;
}
let btnTitle = status==='draft' ?'暂存':'提交'
uni.showModal({
title: '操作确认',
content: '是否要'+ btnTitle +'素材?',
success: (res) => {
if (res.confirm) {
this.submitForm(status)
}
}
});
},
async submitForm(status) {
try {
this.buttonLoading = true;
// 这里添加实际的提交逻辑
let res = null;
if(this.commitState === 'add'){
res = await this.$api.orderApi.AddOrderMaterial({
orderId: this.orderId,
productId: this.productId,
orderItemId: this.orderItemId,
materialItems: this.materialTemplateList,
script: this.scriptContent
});
this.buttonLoading = false;
this.materialfrom.flowId = res.data.id;
this.getProductDetail();
}else{
res = await this.$api.orderApi.EditOrderMaterial({
orderId: this.orderId,
productId: this.productId,
orderItemId: this.orderItemId,
materialItems: this.materialTemplateList,
script: this.scriptContent,
id: this.materialfrom.flowId
});
this.buttonLoading = false;
}
if (status === 'draft') {
if (res.code === 200) {
this.$refs.uToast.show({
title: '暂存成功',
type: 'success',
})
}
uni.navigateBack({
delta: 1
})
} else {
this.buttonLoading = true;
// 提交,调用完成接口
let res1 = await this.$api.orderApi.mallMaterialCommit(this.orderItemId);
if (res1.code === 200) {
this.$refs.uToast.show({
title: '提交成功',
type: 'success',
})
}
this.buttonLoading = false;
uni.navigateBack({
delta: 1
})
}
} finally {
this.buttonLoading = false;
}
}
}
}
</script>
<style>
page{
background: #f5f5f5;
}
</style>
<style lang="scss">
.container {
padding: 20rpx;
padding-bottom: 120rpx;
}
.bg-gray{
background: #f8f8f8;
margin-bottom: 20rpx;
}
.select-box{
padding: 20rpx;
background: #fff;
border-radius: 20rpx;
margin-bottom: 20rpx;
.form-value{
padding: 10rpx;
border: 1px solid #c6c6c6;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
}
.comment-box{
background-color: rgb(254,242,242);
border: 1px solid rgb(254,226,226);
border-radius: 0.5rem;
padding: 1rem;
width: 100%;
color: red;
font-size: 36rpx;
}
.form-item {
margin-bottom: 20rpx;
padding: 20rpx;
background: #fff;
border-radius: 20rpx;
}
.form-label {
display: block;
margin-bottom: 10rpx;
font-weight: bold;
.form-hint{
font-size: 20rpx;
color: #999;
margin-left: 6rpx;
}
}
.upload-area {
// display: flex;
// flex-direction: column;
// align-items: flex-start;
margin-bottom: 10rpx;
}
.preview-wrapper {
margin: 0 auto;
position: relative;
width: 200rpx;
height: 200rpx;
background-color: #eeeeee;
margin-bottom: 10rpx;
.preview-image{
width: 100%;
height: 100%;
}
.delete-icon {
position: absolute;
top: -10rpx;
right: -10rpx;
background-color: #fa3534;
color: #fff;
font-size: 20rpx;
border-radius: 50%;
padding: 10rpx;
}
}
.preview-video {
width: 200rpx;
height: 200rpx;
margin-bottom: 10rpx;
}
.audio-preview {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10rpx;
position: relative;
border: 1px solid #999;
border-radius: 10rpx;
padding: 5rpx 10rpx;
.audio-name {
margin-right: 10rpx;
font-size: 24rpx;
color: #888;
}
.delete-icon {
color: #888;
font-size: 28rpx;
padding: 10rpx;
}
}
.progress-container {
margin: 10rpx 0;
width: 100%;
}
.upload-tip {
margin-top: 5rpx;
font-size: 24rpx;
color: #999;
}
.btn-box{
display: flex;
justify-content: space-around;
align-items: center;
height: 120rpx;
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
z-index: 999;
button{
width: 340rpx;
height: 85rpx;
border-radius: 10rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>