1041 lines
29 KiB
Vue
1041 lines
29 KiB
Vue
<template>
|
||
<view class="uni-container">
|
||
<view class="header">
|
||
<view class="back">
|
||
<view @click="navigateBack" style="margin-left: 15px;display: flex;align-items: center">
|
||
<uni-icons type="back" size="24"></uni-icons>
|
||
<text>返回</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<uni-forms ref="form" :label-width="90" :model="formData" validateTrigger="submit" err-show-type="toast">
|
||
<view class="edit-box">
|
||
<view class="title">
|
||
<textarea class="uni-input" v-model="formData.title" auto-height placeholder="文章标题"
|
||
@input="() => autoSaveContent && autoSaveContent()" />
|
||
</view>
|
||
<editor-component @textchange="onTextChange" @ready="onEditorReady"></editor-component>
|
||
<view class="settings">
|
||
<uni-forms-item name="thumbnail" label="封面" required>
|
||
<view class="thumb-mode">
|
||
<radio-group @change="thumbModeChange">
|
||
<radio value="1" class="mode" :checked="thumbMode === 1">单图</radio>
|
||
<radio value="3" class="mode" :checked="thumbMode === 3">三图</radio>
|
||
<radio value="0" class="mode" :checked="thumbMode === 0">无封面图</radio>
|
||
</radio-group>
|
||
</view>
|
||
<view class="thumbnail-list" v-if="thumbMode > 0">
|
||
<view class="thumbnail" v-for="(thumbnail, index) in formData.thumbnail"
|
||
:key="index">
|
||
|
||
<template v-if="thumbnail">
|
||
<view class="remove-thumbnail" @click="() => removeThumbnail(index)">
|
||
<uni-icons type="closeempty" size="16" color="#fff"></uni-icons>
|
||
</view>
|
||
<cloud-image :src="thumbnail"
|
||
width="150px"
|
||
height="150px"
|
||
mode="scaleToFill">
|
||
</cloud-image>
|
||
</template>
|
||
<template v-else>
|
||
<uni-icons @click="setImage(index)" class="placeholder"
|
||
type="plusempty" size="60" color="#e8e8e8"></uni-icons>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
<view v-if="thumbMode > 0" style="color: #999; font-size: 13px; margin-top: 10px;">
|
||
<text>为了保证最佳效果展示;请上传16:9的封面图片</text>
|
||
</view>
|
||
</uni-forms-item>
|
||
<uni-forms-item v-if="false" name="user_id" label="作者" required>
|
||
<uni-data-picker v-model="formData.user_id" style="width: 200px;" collection="uni-id-users"
|
||
where="role=='uni-cms-author'||role=='admin'"
|
||
field="nickname as text, _id as value"></uni-data-picker>
|
||
</uni-forms-item>
|
||
<uni-forms-item name="category_id" label="分类">
|
||
<uni-data-picker v-model="formData.category_id" style="width: 200px;"
|
||
collection="uni-cms-categories" field="name as text, _id as value"></uni-data-picker>
|
||
</uni-forms-item>
|
||
<!-- <view class="music">
|
||
<audio
|
||
:src="musicConfig.src"
|
||
:poster="musicConfig.poster"
|
||
:name="musicConfig.name"
|
||
:author="musicConfig.author"
|
||
controls
|
||
v-if="musicConfig.show"
|
||
/>
|
||
<view class="btn-area">
|
||
<button class="btn" @touchend.stop="chooseAudio">
|
||
选择音乐
|
||
</button>
|
||
|
||
</view>
|
||
</view>
|
||
|
||
<view class="temps">
|
||
<view class="title">背景模板</view>
|
||
<radio-group>
|
||
<label
|
||
v-for="(t, ti) in templateConfig"
|
||
:key="ti"
|
||
class="label"
|
||
@touchend.stop="templateChange(t.value)"
|
||
>
|
||
<view
|
||
:class="[
|
||
'img-area',
|
||
currentTemplate === t.value && 'radio-checked',
|
||
]"
|
||
>
|
||
<image
|
||
:src="t.src"
|
||
alt=""
|
||
class="img_item"
|
||
mode="widthFix"
|
||
/>
|
||
</view>
|
||
<view class="content">
|
||
<radio
|
||
:value="t.value"
|
||
:checked="t.checked"
|
||
class="radio"
|
||
activeBackgroundColor="red"
|
||
/>
|
||
默认模板
|
||
</view>
|
||
</label>
|
||
</radio-group>
|
||
</view> -->
|
||
<uni-forms-item name="p_type" label="兵种类型">
|
||
<uni-data-picker v-model="formData.p_type" style="width: 200px;" :localdata="pItems"
|
||
field="name as text, _id as value"></uni-data-picker>
|
||
</uni-forms-item>
|
||
|
||
<uni-forms-item name="category_id" label="模版">
|
||
<image :src="currentTemplateSrc" alt="" class="img_item" mode="widthFix"
|
||
@click="openTemplate" />
|
||
</uni-forms-item>
|
||
|
||
<uni-forms-item name="category_id" label="音乐">
|
||
<!-- <audio :src="currentMusic" :poster="musicConfig.poster" :name="musicConfig.name"
|
||
:author="musicConfig.author" controls v-if="musicConfig.show" @click="openMusic"/> -->
|
||
<view class="music-info" v-if="musicInfo.name" @click="toPlay" title="点击播放">
|
||
{{musicInfo.playing}}
|
||
<!-- <uni-icons type="circle-filled" size="24" v-if="musicInfo.playing" />
|
||
<uni-icons type="circle" size="24" v-else /> -->
|
||
<image src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png" mode=""
|
||
style="width: 50px;height: 50px;margin-right: 14px;"></image>
|
||
{{musicInfo.name}}
|
||
<text class="del" @click="musicInfo = {}">×</text>
|
||
</view>
|
||
<button class="btn" @click="chooseAudio" v-else>
|
||
选择音乐
|
||
</button>
|
||
</uni-forms-item>
|
||
|
||
</view>
|
||
<view class="uni-button-group m" style="padding-bottom: 50px">
|
||
<button v-if="formData.article_status === 0" class="uni-button"
|
||
style="width: 100px;margin-right: 10px;" @click="submit(0)">保存</button>
|
||
<button type="primary" class="uni-button" style="width: 100px;" @click="submit(1)">更新</button>
|
||
</view>
|
||
</view>
|
||
</uni-forms>
|
||
<view class="footer">
|
||
<view class="wrap">
|
||
<view class="left">
|
||
<text class="auto-save" v-if="autoSave">
|
||
{{ autoSave.status === 1 ? '自动保存中...' : '已自动保存' }}
|
||
</text>
|
||
<text class="word-count" v-if="wordCount !== null">共 {{ wordCount }} 字</text>
|
||
</view>
|
||
<view class="right">
|
||
<view class="uni-button-group">
|
||
<!-- #ifdef H5 -->
|
||
<button v-if="formData.article_status === 0" class="uni-button"
|
||
style="width: 100px;margin-right: 10px;" @click="previewArticle">预览</button>
|
||
<!-- #endif -->
|
||
<button v-if="formData.article_status === 0" class="uni-button"
|
||
style="width: 100px;margin-right: 10px;" @click="submit(0)">保存</button>
|
||
<button type="primary" class="uni-button" style="width: 100px;" @click="submit(1)">{{
|
||
formData.article_status === 0 ? '发布' : '更新' }}</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<uni-drawer class="insert-image-drawer" v-if="drawerWidth" ref="insertImageDrawer" mode="right"
|
||
:width="drawerWidth">
|
||
<uni-media-library mode="picker" :selected-count="1" :media-tabs="['image']"
|
||
@onInsert="onInsertCover"></uni-media-library>
|
||
</uni-drawer>
|
||
|
||
<!-- #ifdef H5 -->
|
||
<uni-popup ref="popup" type="dialog" v-if="formDataId">
|
||
<article-preview :id="formDataId" @close="() => $refs.popup.close()"></article-preview>
|
||
</uni-popup>
|
||
<!-- #endif -->
|
||
|
||
<uni-popup ref="templ" background-color="#fff">
|
||
<view class="temps-title">选择模版</view>
|
||
<view class="temps">
|
||
<radio-group class="grid">
|
||
<label v-for="(t, ti) in templateConfig" :key="ti" :id="t.value"
|
||
:class="['label', t.checked?'radio-checked':'']" @click="templateChange(t.value, t.src)">
|
||
|
||
{{ t.checked }}
|
||
<view :class="['img-area']">
|
||
<image :src="t.src" alt="" class="img_item" mode="widthFix" />
|
||
</view>
|
||
<view class="content">
|
||
<radio :value="t._id" :checked="t.checked" class="radio" activeBackgroundColor="red"
|
||
@click="templateChange(t.value, t.src)" />
|
||
{{ t.value }}
|
||
</view>
|
||
</label>
|
||
</radio-group>
|
||
</view>
|
||
<view class="temps-title">
|
||
<button type="primary" class="uni-button" style="width: 100%;" @click="submitTemp">确定</button>
|
||
</view>
|
||
</uni-popup>
|
||
|
||
<uni-popup ref="musicRef" background-color="#fff">
|
||
<view class="music">
|
||
<!-- <audio :src="musicConfig.src" :poster="musicConfig.poster" :name="musicConfig.name"
|
||
:author="musicConfig.author" controls v-if="musicConfig.show" /> -->
|
||
<view class="btn-area">
|
||
<button class="btn" @touchend.stop="chooseAudio">
|
||
选择音乐
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
// 引入编辑器组件
|
||
import EditorComponent from "@/uni_modules/uni-cms/components/editor/editor.vue"
|
||
// 引入Delta转换函数
|
||
import {
|
||
translateInputContent,
|
||
translateOutputContent
|
||
} from '@/uni_modules/uni-cms/common/translate-content'
|
||
// 引入表单验证器
|
||
import {
|
||
validator
|
||
} from '@/uni_modules/uni-cms/common/validator/uni-cms-articles.js'
|
||
// 自动保存mixin
|
||
import autoSaveMixin from '@/uni_modules/uni-cms/common/auto-save-mixin.js';
|
||
import {
|
||
parseImageUrl
|
||
} from "@/uni_modules/uni-cms/common/parse-image-url";
|
||
|
||
// 引入文章预览组件
|
||
// #ifdef H5
|
||
import ArticlePreview from "@/uni_modules/uni-cms/components/preview/preview.vue";
|
||
// #endif
|
||
|
||
// 引入数据库相关
|
||
const db = uniCloud.database();
|
||
const dbCollectionName = 'uni-cms-articles';
|
||
|
||
// 根据字段获取验证器
|
||
function getValidator(fields) {
|
||
let result = {}
|
||
for (let key in validator) {
|
||
if (fields.includes(key)) {
|
||
result[key] = validator[key]
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
export default {
|
||
components: {
|
||
EditorComponent,
|
||
// #ifdef H5
|
||
ArticlePreview
|
||
// #endif
|
||
},
|
||
mixins: [autoSaveMixin],
|
||
data() {
|
||
|
||
// 初始化表单数据
|
||
let formData = {
|
||
"user_id": "",
|
||
"category_id": "",
|
||
"title": "",
|
||
"content": null,
|
||
"excerpt": "",
|
||
"article_status": 0,
|
||
"is_sticky": null,
|
||
"is_essence": null,
|
||
"comment_status": null,
|
||
"thumbnail": [""],
|
||
"publish_date": null
|
||
}
|
||
return {
|
||
currentTemplate: "",
|
||
templateConfig: [],
|
||
musicConfig: {
|
||
poster: "https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png",
|
||
name: "音乐",
|
||
author: "暂无",
|
||
src: "",
|
||
show: false,
|
||
},
|
||
// 初始化表单数据的id
|
||
formDataId: '',
|
||
// 表单数据
|
||
formData,
|
||
// 表单选项
|
||
formOptions: {
|
||
"comment_status_localdata": [{
|
||
"value": 0,
|
||
"text": "关闭"
|
||
},
|
||
{
|
||
"value": 1,
|
||
"text": "开放"
|
||
}
|
||
]
|
||
},
|
||
// 表单验证规则
|
||
rules: {
|
||
...getValidator(Object.keys(formData))
|
||
},
|
||
// 编辑器格式
|
||
formats: {},
|
||
// 字数统计
|
||
wordCount: null,
|
||
// 插入图片抽屉宽度
|
||
drawerWidth: 0,
|
||
// 封面图展示方式
|
||
thumbMode: 1,
|
||
|
||
// 当前模板
|
||
currentTemplate: "1",
|
||
currentTemplateSrc: "",
|
||
// 模板列表
|
||
templateConfig: [
|
||
],
|
||
|
||
// 音乐
|
||
musicInfo: {},
|
||
currentMusic: "",
|
||
innerAudioContext: null,
|
||
|
||
pItems: [{
|
||
text: "空军",
|
||
value: "1"
|
||
},
|
||
{
|
||
text: "海军",
|
||
value: "2"
|
||
},
|
||
{
|
||
text: "陆军",
|
||
value: "3"
|
||
},
|
||
{
|
||
text: "地勤保障",
|
||
value: "4"
|
||
},
|
||
{
|
||
text: "武警",
|
||
value: "5"
|
||
},
|
||
]
|
||
}
|
||
},
|
||
// 当页面准备好时,设置表单验证规则
|
||
async onReady() {
|
||
|
||
},
|
||
// 当页面加载时,如果有id则获取表单数据
|
||
async onLoad(e) {
|
||
if (e.id) {
|
||
const id = e.id
|
||
this.formDataId = id
|
||
let res = await db.collection("cms-temp").get();
|
||
console.log(res.result.data)
|
||
let lst = [];
|
||
for (let i = 0 ; i < res.result.data.length ; i++ ) {
|
||
lst.push({
|
||
value:res.result.data[i].temptele_name,
|
||
_id: res.result.data[i]._id,
|
||
src: res.result.data[i].temptele_src,
|
||
checked: false
|
||
})
|
||
}
|
||
this.templateConfig = lst;
|
||
|
||
|
||
this.$refs.form.setRules(this.rules)
|
||
await this.getDetail(id)
|
||
console.log(this.templateConfig)
|
||
}
|
||
|
||
},
|
||
mounted() {
|
||
const sysinfo = uni.getSystemInfoSync()
|
||
this.drawerWidth = sysinfo.windowWidth * .8
|
||
},
|
||
methods: {
|
||
templateConfig_length() {
|
||
return this.templateConfig.length; // 返回数组长度
|
||
},
|
||
openTemplate() {
|
||
this.$refs.templ.open("bottom");
|
||
this.$nextTick(() => {
|
||
setTimeout(() => {
|
||
const dom = document.getElementById(this.currentTemplate)
|
||
if (dom) {
|
||
dom.scrollIntoView({
|
||
behavior: 'smooth',
|
||
block: 'start',
|
||
inline: 'start'
|
||
})
|
||
}
|
||
}, 10)
|
||
})
|
||
// this.closeToolSetting()
|
||
},
|
||
// 选择模板
|
||
templateChange(value, src) {
|
||
this.currentTemplate = value;
|
||
this.currentTemplateSrc = src;
|
||
for (let i = 0; i < this.templateConfig.length; i++) {
|
||
if (this.templateConfig[i].value === value) {
|
||
this.templateConfig[i].checked = true;
|
||
} else {
|
||
this.templateConfig[i].checked = false;
|
||
}
|
||
}
|
||
},
|
||
submitTemp() {
|
||
for (let i = 0; i < this.templateConfig.length; i++) {
|
||
if (this.templateConfig[i].checked === true) {
|
||
this.currentTemplateSrc = this.templateConfig[i].src;
|
||
this.currentTemplate = this.templateConfig[i]._id;
|
||
}
|
||
}
|
||
this.$refs.templ.close()
|
||
},
|
||
openMusic() {
|
||
this.$refs.musicRef.open("bottom");
|
||
},
|
||
// 选择音乐
|
||
chooseAudio() {
|
||
uni.chooseFile({
|
||
count: 1,
|
||
type: 'file',
|
||
extension: ['mp3', 'wav', 'aac'], // 限制音乐格式
|
||
success: (res) => {
|
||
console.log(res)
|
||
console.log(this.musicInfo)
|
||
this.musicInfo = res.tempFiles[0]
|
||
console.log(this.musicInfo)
|
||
console.log(this.musicInfo)
|
||
this.uploadMusic(res.tempFiles[0]);
|
||
}
|
||
});
|
||
},
|
||
toPlay() {
|
||
this.musicInfo.playing = !this.musicInfo.playing;
|
||
this.$forceUpdate()
|
||
if (!this.innerAudioContext) {
|
||
const tempFilePath = this.musicInfo.path;
|
||
this.innerAudioContext = uni.createInnerAudioContext();
|
||
this.innerAudioContext.autoplay = true;
|
||
console.log(tempFilePath);
|
||
this.innerAudioContext.src = tempFilePath;
|
||
this.innerAudioContext.onPlay(() => {
|
||
// console.log('开始播放');
|
||
});
|
||
this.innerAudioContext.onError((res) => {
|
||
console.log(res.errMsg);
|
||
console.log(res.errCode);
|
||
});
|
||
} else {
|
||
const tempFilePath = this.musicInfo.path;
|
||
this.innerAudioContext.src = tempFilePath;
|
||
}
|
||
if (this.musicInfo.playing) {
|
||
this.innerAudioContext.pause();
|
||
} else {
|
||
this.innerAudioContext.play();
|
||
}
|
||
console.log(this.musicInfo.playing)
|
||
},
|
||
async uploadMusic(filePath) {
|
||
try {
|
||
|
||
console.log(filePath);
|
||
const result = await uniCloud.uploadFile({
|
||
filePath: filePath.path,
|
||
cloudPath: `music/${Date.now()}_${filePath.name}`, // 云存储路径
|
||
onUploadProgress: (e) => {
|
||
console.log(`进度: ${Math.round(e.loaded / e.total * 100)}%`);
|
||
}
|
||
});
|
||
console.log('上传成功,文件地址:', result.fileID);
|
||
console.log(this.musicInfo);
|
||
this.musicInfo.music_url_id = result.fileID;
|
||
console.log(this.musicInfo);
|
||
// 可存储 fileID 或转为永久 URL
|
||
const url = await uniCloud.getTempFileURL({
|
||
fileList: [result.fileID]
|
||
});
|
||
console.log('可访问的 URL:', url.fileList[0].tempFileURL);
|
||
} catch (err) {
|
||
console.error('上传失败:', err);
|
||
}
|
||
},
|
||
templateChange(value) {
|
||
this.currentTemplate = value;
|
||
for (let i = 0; i < this.templateConfig.length; i++) {
|
||
if (this.templateConfig[i].value === value) {
|
||
this.templateConfig[i].checked = true;
|
||
} else {
|
||
this.templateConfig[i].checked = false;
|
||
}
|
||
}
|
||
},
|
||
// 封面图展示方式改变
|
||
thumbModeChange(e) {
|
||
const coverCount = Number(e.detail.value)
|
||
this.formData.thumbnail = Array.from(new Array(coverCount)).map((item, index) => {
|
||
if (this.formData.thumbnail[index]) {
|
||
return this.formData.thumbnail[index]
|
||
} else {
|
||
return ""
|
||
}
|
||
})
|
||
this.thumbMode = coverCount
|
||
},
|
||
/**
|
||
* 获取表单数据
|
||
* @param {String} id - 文章id
|
||
*/
|
||
async getDetail(id) {
|
||
// 显示加载中
|
||
uni.showLoading({
|
||
mask: true
|
||
})
|
||
// 从数据库中获取文章数据
|
||
let query = {
|
||
id: id
|
||
}
|
||
const res = await uniCloud.importObject("article_info").getDetail(query);
|
||
console.log(res)
|
||
if (res.data.length > 0) {
|
||
const data = res.data[0]
|
||
if (data) {
|
||
// 将获取到的数据赋值给formData
|
||
this.formData = data
|
||
if (this.formData.content.ops.length > 0) {
|
||
console.log(this.formData.content.ops.length)
|
||
for (let i = 0; i < this.formData.content.ops.length; i++) {
|
||
let item = this.formData.content.ops[i];
|
||
console.log(item.insert.mediaVideo);
|
||
if (item.insert.mediaVideo === true) {
|
||
const fileID = item.attributes.poster;
|
||
console.log(fileID)
|
||
const regex = /^cloud:/;
|
||
if (regex.test(fileID)) {
|
||
try {
|
||
const res = await uniCloud.getTempFileURL({
|
||
fileList: [fileID]
|
||
});
|
||
console.log(this.formData.content.ops[i].attributes.poster)
|
||
console.log(res.fileList[0].tempFileURL)
|
||
this.formData.content.ops[i].attributes.poster = res.fileList[0].tempFileURL;
|
||
} catch (e) {
|
||
return {
|
||
error: e
|
||
};
|
||
}
|
||
}
|
||
console.log(data)
|
||
}
|
||
}
|
||
}
|
||
if (data.music_url_id) {
|
||
|
||
const res = await uniCloud.getTempFileURL({
|
||
fileList: [data.music_url_id]
|
||
});
|
||
console.log(res)
|
||
this.musicInfo = data.music_url_id;
|
||
|
||
}
|
||
console.log(data.temp_id)
|
||
// if ( data.temp_id ) {
|
||
// this.currentTemplate = res.data[0].temp_id;
|
||
// for (let i = 0 ; i < this.templateConfig_length() ; i++ ) {
|
||
// if (this.currentTemplate === this.templateConfig[i]._id) {
|
||
// this.currentTemplateSrc = this.templateConfig[i].src;
|
||
// }
|
||
// }
|
||
// }
|
||
if (data.temp_id) {
|
||
console.log(this.templateConfig_length())
|
||
this.currentTemplate = data.temp_id;
|
||
for (let i = 0 ; i < this.templateConfig_length(); i ++ ) {
|
||
|
||
|
||
if (this.currentTemplate === this.templateConfig[i]._id) {
|
||
this.templateConfig[i].checked = true;
|
||
this.currentTemplateSrc = this.templateConfig[i].src;
|
||
}
|
||
console.log(this.templateConfig[i].checked)
|
||
}
|
||
|
||
}
|
||
// 如果有缩略图,则设置缩略图预览
|
||
const thumbnail = typeof this.formData.thumbnail === 'string' ? [this.formData.thumbnail] :
|
||
this.formData.thumbnail
|
||
|
||
// 更新封面图展示方式
|
||
this.thumbMode = this.formData.thumbnail && this.formData.thumbnail.length ? this.formData
|
||
.thumbnail.length : 0
|
||
// 设置编辑器内容
|
||
this.setContents()
|
||
|
||
// 处理封面图
|
||
// parseImageUrl(thumbnail).then(res => {
|
||
// this.formData.thumbnail = res
|
||
// })
|
||
}
|
||
}
|
||
uni.hideLoading()
|
||
// uni.showModal({
|
||
// content: err.message || '请求服务失败',
|
||
// showCancel: false
|
||
// })
|
||
},
|
||
/**
|
||
* 当编辑器准备好时,设置编辑器内容
|
||
* @param {Object} editorCtx - 编辑器上下文
|
||
*/
|
||
onEditorReady(editorCtx) {
|
||
// 如果编辑器上下文不存在,则返回
|
||
if (!editorCtx) return
|
||
|
||
// 将编辑器上下文赋值给组件实例的editorCtx属性
|
||
this.editorCtx = editorCtx
|
||
|
||
// 设置编辑器内容
|
||
this.setContents()
|
||
},
|
||
|
||
/**
|
||
* 设置编辑器内容
|
||
*/
|
||
setContents() {
|
||
// 检查编辑器上下文是否存在
|
||
if (this.editorCtx && this.formData.content) {
|
||
// #ifdef H5
|
||
// 如果是H5平台,则直接使用formData中的内容
|
||
const content = this.formData.content
|
||
// #endif
|
||
|
||
// #ifndef H5
|
||
// 如果不是H5平台,则需要将formData中的内容转换为编辑器所需的格式
|
||
const content = translateInputContent(this.formData.content)
|
||
// #endif
|
||
|
||
// 设置编辑器内容
|
||
this.editorCtx.setContents({
|
||
delta: content
|
||
})
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 验证表单并提交
|
||
* @param {Number} status - 文章状态
|
||
*/
|
||
submit(status) {
|
||
// 检查文章标题是否存在
|
||
if (!this.formData.title) {
|
||
// 隐藏加载中
|
||
uni.hideLoading()
|
||
// 显示文章标题必填的提示
|
||
return uni.showToast({
|
||
icon: 'none',
|
||
title: '文章标题必填',
|
||
})
|
||
}
|
||
|
||
if (this.formData.thumbnail) {
|
||
for (const thumbnail of this.formData.thumbnail) {
|
||
if (!thumbnail) {
|
||
// 如果封面图为空,提示用户
|
||
uni.hideLoading()
|
||
return uni.showToast({
|
||
icon: 'none',
|
||
title: '封面图必填',
|
||
})
|
||
}
|
||
}
|
||
}
|
||
return new Promise(resolve => {
|
||
// 验证表单
|
||
this.$refs.form.validate().then((res) => {
|
||
// 获取编辑器内容
|
||
console.log(this.currentTemplate)
|
||
this.editorCtx.getContents({
|
||
|
||
success: async (e) => {
|
||
// 提交表单
|
||
console.log(this.musicInfo)
|
||
await this.submitForm({
|
||
...res,
|
||
thumbnail: this.formData.thumbnail,
|
||
article_status: status,
|
||
title: this.formData.title,
|
||
content: translateOutputContent(e.delta),
|
||
publish_date: this.formData.publish_date ? this
|
||
.formData.publish_date : Date.now(),
|
||
|
||
temp_id: this.currentTemplate,
|
||
music_url_id: {
|
||
type: this.musicInfo.type,
|
||
name: this.musicInfo.name,
|
||
path:"",
|
||
music_url_id: this.musicInfo.music_url_id,
|
||
lastModified: this.musicInfo.lastModified,
|
||
size: this.musicInfo.size
|
||
|
||
}
|
||
})
|
||
|
||
// resolve()
|
||
}
|
||
})
|
||
}).catch((e) => {
|
||
console.error(e)
|
||
})
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 提交表单
|
||
* @param {Object} value - 表单数据
|
||
*/
|
||
submitForm(value) {
|
||
console.log(value)
|
||
uni.showLoading({
|
||
mask: true
|
||
})
|
||
// 使用 clientDB 提交数据
|
||
return db.collection(dbCollectionName).doc(this.formDataId).update(value).then(() => {
|
||
// 提交成功后,根据文章状态弹出不同的提示信息
|
||
uni.showToast({
|
||
icon: 'none',
|
||
title: value.article_status === 0 ? '保存成功' : this.formData.article_status === 0 ?
|
||
'发布成功' : '更新成功'
|
||
})
|
||
|
||
try {
|
||
// 触发父页面事件,刷新数据
|
||
this.getOpenerEventChannel().emit('refreshData')
|
||
} catch (e) {}
|
||
|
||
// 清除自动保存内容
|
||
this.clearAutoSaveStorage && this.clearAutoSaveStorage()
|
||
|
||
// 延迟 500ms 后,如果文章状态为已发布,返回上一页。
|
||
setTimeout(() => {
|
||
if (value.article_status === 1) {
|
||
uni.navigateBack()
|
||
}
|
||
}, 500)
|
||
}).catch((err) => {
|
||
uni.showModal({
|
||
content: err.message || '请求服务失败',
|
||
showCancel: false
|
||
})
|
||
}).finally(() => {
|
||
uni.hideLoading()
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 文本内容变化时更新字数统计
|
||
* @param {Object} e - 文本内容变化事件
|
||
*/
|
||
onTextChange(e) {
|
||
this.wordCount = e.detail
|
||
|
||
// 自动保存
|
||
this.autoSaveContent && this.autoSaveContent()
|
||
},
|
||
|
||
/**
|
||
* 返回上一页或跳转到文章列表页
|
||
*/
|
||
navigateBack() {
|
||
const pages = getCurrentPages()
|
||
|
||
if (pages.length > 1) {
|
||
uni.navigateBack(-1)
|
||
} else {
|
||
uni.redirectTo({
|
||
url: '/uni_modules/uni-cms/pages/article/list/list'
|
||
})
|
||
}
|
||
},
|
||
async setImage(index) {
|
||
this.coverIndex = index;
|
||
const that = this;
|
||
uni.chooseImage({
|
||
sourceType:["album","camera"],
|
||
count: 1,
|
||
success: async (res) => {
|
||
let t_res = res.tempFiles[0];
|
||
if (res.tempFilePaths.length > 0) {
|
||
let filePath = res.tempFilePaths[0];
|
||
let {
|
||
name,
|
||
extname
|
||
} = that.getFileInfo(filePath)
|
||
const uniCloudStorageExtCo = uniCloud.importObject("ext-storage-co");
|
||
console.log(`cms/thumbnail/${new Date().getFullYear()}-${(new Date().getMonth()+1).toString().padStart(2,'0')}-${new Date().getDate().toString().padStart(2,'0')}/${name}_${Math.random().toString(36).substr(2, 6)}`)
|
||
const uploadFileOptionsRes = await uniCloudStorageExtCo.getUploadFileOptions({
|
||
cloudPath: `cms/thumbnail/${new Date().getFullYear()}-${(new Date().getMonth()+1).toString().padStart(2,'0')}-${new Date().getDate().toString().padStart(2,'0')}/${name}_${Math.random().toString(36).substr(2, 6)}`
|
||
});
|
||
console.log(uploadFileOptionsRes)
|
||
const uploadRes = await uniCloud.uploadFile({
|
||
...uploadFileOptionsRes.uploadFileOptions,
|
||
filePath: filePath,
|
||
cloudPath: uploadFileOptionsRes.cloudPath
|
||
});
|
||
|
||
await uniCloud.uploadFile({
|
||
...uploadFileOptionsRes.uploadFileOptions,
|
||
filePath: filePath,
|
||
cloudPath: uploadFileOptionsRes.cloudPath,
|
||
success: async () => {
|
||
const res2 = {
|
||
cloudPath: uploadFileOptionsRes.cloudPath,
|
||
fileID: uploadFileOptionsRes.fileID,
|
||
fileURL: uploadFileOptionsRes.fileURL
|
||
};
|
||
console.log(t_res)
|
||
|
||
const selectedMedia = {
|
||
src: await this.getSrc(res2.fileID),
|
||
alt: name,
|
||
type: t_res.type,
|
||
size: t_res.size,
|
||
duration: 0
|
||
}
|
||
selectedMedia.cover = selectedMedia.src;
|
||
console.log(selectedMedia)
|
||
|
||
const coverIndex = that.coverIndex !== null ? that.coverIndex : 0
|
||
const newThumbnail = [...that.formData.thumbnail]
|
||
const parseImages = await selectedMedia.src
|
||
newThumbnail[coverIndex] = parseImages
|
||
this.formData.thumbnail = newThumbnail
|
||
|
||
console.log("上传成功", res2);
|
||
},
|
||
fail: (err) => {
|
||
console.log("上传失败", err);
|
||
}
|
||
});
|
||
|
||
} else {
|
||
console.log("未选中文件")
|
||
}
|
||
}
|
||
});
|
||
},
|
||
getFileInfo(path) {
|
||
const parts = path.split('/').pop();
|
||
const [filename, ...extParts] = parts.split('.');
|
||
const ext = extParts.length ? extParts.pop() : '';
|
||
return {
|
||
name: filename,
|
||
extname: ext
|
||
};
|
||
},
|
||
formatBytes(bytes) {
|
||
if (bytes === 0) return '0 Bytes';
|
||
const k = 1024;
|
||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||
|
||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||
|
||
if (i >= sizes.length) return '> 1 TB';
|
||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||
},
|
||
|
||
async getSrc(src) {
|
||
|
||
if (src&&src.substring(0, 8) == "cloud://") {
|
||
uniCloud.getTempFileURL({
|
||
fileList: [src]
|
||
}).then(res=>{
|
||
return res.fileList[0].tempFileURL;
|
||
})
|
||
} else if (src&&src.substring(0, 8) == "qiniu://") {
|
||
const uniCloudStorageExtCo = uniCloud.importObject("ext-storage-co");
|
||
const res = await uniCloudStorageExtCo.getTempFileURL({src: src});
|
||
return res.fileList[0].tempFileURL;
|
||
|
||
} else {
|
||
return src
|
||
}
|
||
},
|
||
openInsertImageDrawer(index) {
|
||
this.$refs.insertImageDrawer.open()
|
||
this.coverIndex = index
|
||
},
|
||
async onInsertCover(selectMediaItems) {
|
||
const coverIndex = this.coverIndex !== null ? this.coverIndex : 0
|
||
const image = selectMediaItems[0]
|
||
const newThumbnail = [...this.formData.thumbnail]
|
||
const parseImages = await parseImageUrl(image.src)
|
||
|
||
newThumbnail[coverIndex] = parseImages[0]
|
||
|
||
this.$refs.insertImageDrawer.close()
|
||
this.formData.thumbnail = newThumbnail
|
||
},
|
||
removeThumbnail(index) {
|
||
const newThumbnail = [...this.formData.thumbnail]
|
||
newThumbnail[index] = ""
|
||
|
||
this.formData.thumbnail = newThumbnail
|
||
this.autoGetCover = false
|
||
},
|
||
async previewArticle() {
|
||
if (this.formDataId) {
|
||
// 先保存文章
|
||
await this.submit(0)
|
||
this.$refs.popup.open()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
@import '@/uni_modules/uni-cms/common/style/article-detail.scss';
|
||
.edit-box {
|
||
padding-bottom: 100px !important;
|
||
}
|
||
|
||
.uni-button-group {
|
||
display: flex;
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100vw;
|
||
background: #fff;
|
||
padding: 20px 0;
|
||
z-index: 2;
|
||
}
|
||
|
||
.temps-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
text-align: center;
|
||
padding: 10px;
|
||
}
|
||
|
||
.temps {
|
||
height: 50vh;
|
||
overflow-y: auto;
|
||
padding: 16px 16px 50px 16px;
|
||
|
||
.img-area {
|
||
position: relative;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.radio-checked {
|
||
&::after {
|
||
content: "";
|
||
position: absolute;
|
||
width: calc(100% + 2px);
|
||
height: calc(100% + 2px);
|
||
left: -1px;
|
||
top: -1px;
|
||
background-color: red;
|
||
z-index: 1;
|
||
border-radius: 5px;
|
||
}
|
||
}
|
||
|
||
.content {
|
||
// margin: 10px auto 20px auto;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: center;
|
||
z-index: 2;
|
||
background: #fff;
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 0 0 5px 5px;
|
||
padding: 5px 0;
|
||
}
|
||
|
||
.radio {
|
||
zoom: 0.7;
|
||
}
|
||
}
|
||
|
||
.img_item {
|
||
vertical-align: middle;
|
||
width: 100%;
|
||
border-radius: 5px 5px 0 0;
|
||
z-index: 2;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr;
|
||
gap: 20px;
|
||
|
||
@media screen and (min-width:800px) {
|
||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||
}
|
||
}
|
||
|
||
.label {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
position: relative;
|
||
border-radius: 5px;
|
||
z-index: 2;
|
||
background-color: #fff;
|
||
}
|
||
|
||
.music-info {
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
border: 2px solid #e5e5e5;
|
||
border-radius: 5px;
|
||
padding: 5px 15px;
|
||
}
|
||
|
||
.del {
|
||
color: red;
|
||
margin-left: 20px;
|
||
cursor: pointer;
|
||
}
|
||
</style> |