You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

893 lines
27 KiB

<template>
<div>
<el-card shadow="hover"
class="mgb20">
<div class="flex-between">
<div class="per_title"
v-preventReClick
@click="back">
<i class="el-icon-arrow-left"></i>
<span class="per_back">返回</span>
<span class="per_school"
v-text="form.id ? '编辑文章' : '新建文章'"></span>
</div>
</div>
</el-card>
<div class="page">
<el-form :model="form"
:rules="rules"
class="input-form model"
label-width="140px">
<el-form-item prop="title"
label="标题">
<el-input id="focus-el"
style="width: 940px"
placeholder="请输入标题"
v-model="form.title"
clearable
maxlength="100"
@change="nameChange"></el-input>
</el-form-item>
<div class="item-line">
<el-form-item prop="releaseTime"
label="发布日期">
<el-date-picker v-model="form.releaseTime"
type="date"
placeholder="选择日期"
format="yyyy-MM-dd"
:clearable="false"
value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="source"
label="来源">
<el-input placeholder="请输入来源"
v-model.trim="form.source"
clearable
maxlength="50"
class="inline-input"></el-input>
</el-form-item>
<el-form-item prop="author"
label="作者">
<el-input v-model="form.author"
clearable
maxlength="50"
class="inline-input"></el-input>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="edit"
label="编辑">
<el-input placeholder="请输入编辑"
v-model.trim="form.edit"
clearable
maxlength="50"
class="inline-input"></el-input>
</el-form-item>
<el-form-item prop="audit"
label="审核">
<el-input placeholder="请输入审核"
v-model.trim="form.audit"
clearable
maxlength="50"
class="inline-input"></el-input>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="classificationId"
label="所属分类">
<el-select style="width: 234px;"
v-model="form.classificationId">
<template v-for="item in classifications">
<el-option v-if="item.id"
:key="item.id"
:label="item.classificationName"
:value="item.id">
</el-option>
</template>
</el-select>
<el-button class="set-btn"
type="primary"
@click="setClass">设置</el-button>
</el-form-item>
<el-form-item prop="author"
label="主题标签">
<el-select style="width: 234px;"
v-model="form.lableId"
multiple>
<template v-for="item in labels">
<el-option v-if="item.id"
:key="item.id"
:label="item.labelName"
:value="item.id">
</el-option>
</template>
</el-select>
<el-button class="set-btn"
type="primary"
@click="setLabel">设置</el-button>
</el-form-item>
</div>
<el-form-item prop="summary"
label="摘要">
<el-input style="width: 940px"
type="textarea"
v-model.trim="form.summary"
:rows="3"
clearable></el-input>
</el-form-item>
<el-form-item prop="bannerImg"
label="封面图">
<el-upload class="avatar-uploader"
accept=".jpg,.png,.jpeg,.gif"
:on-change="changeFile"
:show-file-list="false"
action=""
:auto-upload="false">
<img v-if="form.bannerImg"
:src="form.bannerImg"
class="avatar">
<div class="uploader-default"
v-else>
<img class="plus"
src="@/assets/img/plus.png"
alt="">
<p>点击上传</p>
</div>
</el-upload>
</el-form-item>
<el-form-item prop="mainBody"
label="正文">
<Editor api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda'
v-model="form.mainBody"
:init="editorConfig" />
</el-form-item>
<el-form-item prop="file"
label="文件上传">
<Upload :limit="20"
:changeFileList="false"
:file-list.sync="form.fileList"
:on-remove="handleRemove"
@onSuccess="uploadSuccessFile" />
</el-form-item>
</el-form>
<div class="btns">
<el-button type="primary"
@click="submit(1)">发布</el-button>
<el-button @click="submit(0)">保存草稿</el-button>
<el-button @click="back">取消</el-button>
</div>
</div>
<!-- 剪裁组件弹窗 -->
<el-dialog title="图片裁剪"
append-to-body
:visible.sync="cropperModel"
width="1100px"
:close-on-click-modal="false">
<Cropper ref="cropper"
:img-file.sync="file"
:is-upload="isUpload"
:fixed="true"
:fixedNumber.sync="fixedNumber"
@upload="customUpload" />
</el-dialog>
<el-dialog title="所属分类设置"
:visible.sync="classVisible"
width="500px"
:close-on-click-modal="false"
class="manage-dia"
:before-close="closeClass">
<div class="plus">
<i class="el-icon-circle-plus-outline"
@click="addClass"></i>
</div>
<el-table :data="classifications"
ref="table"
header-align="center"
row-key="id">
<el-table-column type="index"
width="60"
label="序号"
align="center"></el-table-column>
<el-table-column prop="classificationName"
label="分类名称"
align="center"
min-width="130">
<template slot-scope="scope">
<el-input v-if="scope.row.edit"
placeholder="请输入分类名称"
v-model="scope.row.classificationName"
clearable
maxlength="30"></el-input>
<span v-else>{{ scope.row.classificationName }}</span>
</template>
</el-table-column>
<el-table-column prop="updateTime1"
label="是否引用"
align="center"
min-width="60">否</el-table-column>
<el-table-column label="操作"
align="center"
min-width="60">
<template slot-scope="scope">
<i v-if="scope.row.edit"
class="el-icon-check edit"
@click="submitClass(scope.row)"></i>
<i v-else
class="el-icon-edit edit"
@click="editClass(scope.row)"></i>
<i class="el-icon-delete del"
@click="delClass(scope.row, scope.$index)"></i>
</template>
</el-table-column>
</el-table>
<span slot="footer">
<el-button @click="closeClass">返回</el-button>
</span>
</el-dialog>
<el-dialog title="主题标签设置"
:visible.sync="labelVisible"
width="500px"
:close-on-click-modal="false"
class="manage-dia"
:before-close="closeLabel">
<div class="plus">
<i class="el-icon-circle-plus-outline"
@click="addLabel"></i>
</div>
<el-table :data="labels"
ref="table"
header-align="center"
row-key="id">
<el-table-column type="index"
width="60"
label="序号"
align="center"></el-table-column>
<el-table-column prop="labelName"
label="主题名称"
align="center"
min-width="130">
<template slot-scope="scope">
<el-input v-if="scope.row.edit"
placeholder="请输入主题名称"
v-model="scope.row.labelName"
clearable
maxlength="30"></el-input>
<span v-else>{{ scope.row.labelName }}</span>
</template>
</el-table-column>
<el-table-column prop="updateTime1"
label="是否引用"
align="center"
min-width="60">否</el-table-column>
<el-table-column label="操作"
align="center"
min-width="60">
<template slot-scope="scope">
<i v-if="scope.row.edit"
class="el-icon-check edit"
@click="submitLabel(scope.row)"></i>
<i v-else
class="el-icon-edit edit"
@click="editLabel(scope.row)"></i>
<i class="el-icon-delete del"
@click="delLabel(scope.row, scope.$index)"></i>
</template>
</el-table-column>
</el-table>
<span slot="footer">
<el-button @click="closeLabel">返回</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Setting from '@/setting'
import Util from '@/libs/util'
import { mapState } from 'vuex'
import Editor from '@tinymce/tinymce-vue'
import editorConfig from '@/utils/editor'
import Cropper from '@/components/img-upload/Cropper'
import Axios from 'axios'
import Upload from '@/components/upload';
import Oss from '@/components/upload/upload.js'
export default {
data () {
return {
typeId: +this.$route.query.type,
headers: {
token: sessionStorage.getItem('token')
},
nameRepeat: false,
form: {
id: this.$route.query.id || '',
author: '',
edit: '',
audit: '',
bannerImg: '',
lableId: [],
classificationId: '',
file: '',
isRelease: 0,
mainBody: '',
releaseTime: new Date(),
summary: '',
title: '',
fileList: [],
typeId: +this.$route.query.type
},
rules: {
title: [
{ required: true, message: '请输入标题', trigger: 'blur' }
],
classificationId: [
{ required: true, message: '请选择所属分类', trigger: 'change' }
],
releaseTime: [
{ required: true, message: '请选择发布日期', trigger: 'change' }
],
bannerImg: [
{ required: true, message: '请上传封面图', trigger: 'change' }
],
mainBody: [
{ required: true, message: '请输入正文', trigger: 'blur' }
],
},
editorConfig,
submiting: false, // 新增编辑防抖标识
pass: false,
uploading: 0,
updateTime: 0,
cropperModel: false,
isUpload: false,
fixedNumber: [1.76, 1],
file: {}, // 当前被选择的图片文件
classifications: [],
classVisible: false,
labels: [],
labelVisible: false
};
},
components: {
Editor,
Cropper,
Upload
},
watch: {
// 监听信息是否有更改,有的话页面离开的时候要询问是否要保存
form: {
handler (val) {
this.updateTime++
},
deep: true
}
},
// 页面离开的时候如果没有保存则提示
beforeRouteLeave (to, from, next) {
if (this.submiting) {
next()
} else if (!this.pass) {
// 更改了信息才需要提示
if (this.updateTime) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning',
closeOnClickModal: false
}).then(() => {
this.submit(this.form.isRelease, next)
}).catch(() => {
next()
})
} else {
next()
}
} else {
next()
}
},
mounted () {
this.getArticle()
this.getLabel()
},
methods: {
// 文章详情
getArticle () {
const { id } = this.form
id ? this.$post(`${this.api.findByIdParnerArticle}?id=${id}`).then(({ data }) => {
data.lableId = data.lableId ? data.lableId.split(',').map(e => +e) : []
data.fileList.forEach(e => e.name = e.fileName)
this.form = data
this.getClassification(1)
}).catch(err => { }) : this.getClassification(1)
},
// 获取所属分类
getClassification (detail) {
this.$post(`${this.api.queryClassificationByType}?typeId=${this.typeId}`).then(({ data }) => {
this.classifications = data
// 如果所选分类被删除,则清空分类id
if (detail) {
const id = this.form.classificationId
if (!data.find(e => e.id == id)) this.form.classificationId = ''
setTimeout(() => {
this.updateTime = 0
}, 500)
}
}).catch(err => { })
},
// 显示所属分类弹框
setClass () {
this.classVisible = true
},
// 新增所属分类
addClass () {
this.classifications.find(e => e.edit) ?
Util.errorMsg('请先保存分类!') :
this.classifications.push({
edit: true,
id: '',
classificationName: ''
})
},
// 编辑所属分类
editClass (row) {
this.classifications.find(e => e.edit) ?
Util.errorMsg('请先保存分类!') :
this.$set(row, 'edit', 1)
},
// 删除所属分类
delClass (row, i) {
if (row.id) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(`${this.api.batchDeletionParnerClass}?ids=${row.id}`).then(res => {
Util.successMsg('删除成功')
this.getClassification()
}).catch(res => { })
}).catch(() => { })
} else {
this.classifications.splice(i, 1)
}
},
// 提交所属分类
submitClass (row, showMsg = 1) {
if (!row.classificationName) return Util.errorMsg('请输入分类名称')
this.$post(`${this.api.checkForHeavyParnerClass}?classificationName=${row.classificationName}&typeId=${this.typeId}&classificationId=${row.id}`).then(res => {
this.$post(this.api[row.id ? 'updateParnerClass' : 'saveParnerClass'], {
classificationName: row.classificationName,
typeId: this.typeId, // 类型(1.学习2.资讯)
id: row.id,
}).then(res => {
showMsg && Util.successMsg((row.id ? '修改' : '新增') + '成功')
this.getClassification()
}).catch(res => { })
}).catch(res => { })
},
// 关闭所属分类
closeClass () {
const list = this.classifications
if (list.find(e => e.edit && e.classificationName)) {
this.$confirm('所填写内容暂未保存,是否保存?', '提示', {
type: 'warning',
closeOnClickModal: false
}).then(() => {
list.map(e => {
e.edit && e.classificationName && this.submitClass(e, 0)
})
this.classVisible = false
}).catch(() => {
this.classVisible = false
})
} else {
this.classVisible = false
}
// 所选的分类被删了后,要清空所选的分类id
if (!list.find(e => e.id == this.form.classificationId)) this.form.classificationId = ''
},
// 获取标签
getLabel () {
this.$post(this.api.queryAllArticleSubjectTags).then(({ data }) => {
this.labels = data
}).catch(err => { })
},
// 显示标签弹框
setLabel () {
this.labelVisible = true
},
// 新增标签
addLabel () {
this.labels.find(e => e.edit) ?
Util.errorMsg('请先保存主题!') :
this.labels.push({
edit: true,
id: '',
labelName: ''
})
},
// 编辑标签
editLabel (row) {
this.labels.find(e => e.edit) ?
Util.errorMsg('请先保存主题!') :
this.$set(row, 'edit', 1)
},
// 删除标签
delLabel (row, i) {
if (row.id) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(`${this.api.batchDeletionParnerLabel}?ids=${row.id}`).then(res => {
Util.successMsg('删除成功')
this.getLabel()
}).catch(res => { })
}).catch(() => { })
} else {
this.labels.splice(i, 1)
}
},
// 提交标签
submitLabel (row, showMsg = 1) {
if (!row.labelName) return Util.errorMsg('请输入主题名称')
this.$post(`${this.api.checkForHeavyParnerLabel}?labelName=${row.labelName}&labelId=${row.id}`).then(res => {
this.$post(this.api[row.id ? 'updateParnerLabel' : 'saveParnerLabel'], {
labelName: row.labelName,
id: row.id,
}).then(res => {
showMsg && Util.successMsg((row.id ? '修改' : '新增') + '成功')
this.getLabel()
}).catch(res => { })
}).catch(res => { })
},
// 关闭标签
closeLabel () {
const list = this.labels
if (list.find(e => e.edit && e.labelName)) {
this.$confirm('所填写内容暂未保存,是否保存?', '提示', {
type: 'warning',
closeOnClickModal: false
}).then(() => {
list.map(e => {
e.edit && e.labelName && this.submitLabel(e, 0)
})
this.labelVisible = false
}).catch(() => {
this.labelVisible = false
})
} else {
this.labelVisible = false
}
},
// 文章名称判重
nameChange () {
const { title, id } = this.form
if (title && title !== this.originalName) {
this.$post(this.api.checkIfTheTitleIsRepeat, {
typeId: this.typeId,
title,
id: id || ''
}).then(res => {
this.nameRepeat = false
}).catch(res => {
this.nameRepeat = true
})
} else {
this.nameRepeat = false
}
},
// 图片裁剪上传事件
customUpload (data) {
data.name = this.file.name
this.imgUpload(data)
},
// 图片上传到服务器
imgUpload (formData) {
this.isUpload = true
Oss.upload(formData).then(res => {
this.form.bannerImg && Oss.del(this.form.bannerImg)
this.form.bannerImg = res.url
})
this.$refs.cropper.isDisabled = false
this.isUpload = false
this.cropperModel = false
},
// 图片改变钩子
changeFile (file) {
const { size, name } = file
const ext = name.substring(name.lastIndexOf('.') + 1)
if (!Util.isImg(ext)) {
this.$message.error('请上传图片!')
return false
}
// if (size / 1024 / 1024 > 5) {
// this.$message.error('请上传5M以内的图片!')
// return false
// }
this.file = file
this.cropperModel = true
this.$nextTick(() => {
this.$refs.cropper.updateImg({
url: window.URL.createObjectURL(file.raw),
size: file.size
})
})
},
// 附件删除
handleRemove (e, fileList) {
Oss.del(e.filePath)
e.id ? this.$post(`${this.api.batchDeletionParnerFile}?ids=${e.id}`).then(res => {
this.form.fileList = fileList
}).catch(res => { }) : (this.form.fileList = fileList)
},
// 附件上传之前的钩子
fileBeforeUpload (file) {
this.uploading++
},
// 附件上传成功
uploadSuccessFile (file) {
const { name, url } = file
this.uploading--
this.form.id ?
this.$post(this.api.saveParnerFile, {
contentId: this.form.id,
id: '',
fileName: name,
filePath: url
}).then(({ data }) => {
this.form.fileList.push({
fileName: name,
filePath: url,
name: name,
url,
id: data
})
}).catch(res => { }) :
this.form.fileList.push({
fileName: name,
filePath: url,
name: name,
url
})
},
// 预览
preview () {
window.open((Setting.isDev ? `http://${location.hostname}:8095` : this.$store.state.content.site.domainName) + `#/article?articleId=${this.form.id}&siteId=${this.form.siteId}&id=${this.form.columnId}`)
},
// 返回
back () {
this.pass = true
// 更改了信息才需要提示
if (this.updateTime) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning',
closeOnClickModal: false
}).then(() => {
this.submit(this.form.isRelease)
}).catch(() => {
this.$router.back()
})
} else {
this.$router.back()
}
},
// 提交
submit (isRelease, next) {
if (this.submiting) return false
const form = JSON.parse(JSON.stringify(this.form))
console.log('form=>', form)
if (!form.title) return Util.errorMsg('请填写标题')
if (this.nameRepeat) return Util.errorMsg('该标题已重复!')
// 如果是发布
if (isRelease) {
if (!form.releaseTime) return Util.errorMsg('请选择发布日期')
if (!form.classificationId) return Util.errorMsg('请选择所属分类')
if (!form.bannerImg) return Util.errorMsg('请上传封面')
if (!form.mainBody) return Util.errorMsg('请输入正文')
}
// if (this.uploading) return Util.errorMsg('文件正在上传,请上传完成后再发布')
form.lableId = form.lableId.join(',')
form.releaseTime = Util.formatDate('yyyy-MM-dd', new Date(form.releaseTime)) // 发布日期转化为年月日格式
form.isRelease = isRelease
this.submiting = true
if (form.id) {
delete form.children
this.$post(this.api.updateParnerArticle, form).then(res => {
Util.successMsg('修改成功')
next ? next() : this.$router.back()
}).catch(err => {
this.submiting = false
})
} else {
this.$post(this.api.saveParnerArticle, form).then(({ data }) => {
Util.successMsg('创建成功')
next ? next() : this.$router.back()
}).catch(err => {
this.submiting = false
})
}
}
}
};
</script>
<style lang="scss" scoped>
$upload-width: 220px;
$upload-height: 102px;
$upload-lg-height: 102px;
/deep/ .avatar-uploader {
.el-upload {
position: relative;
width: $upload-width;
height: $upload-height;
border: 1px solid #dcdee0;
border-radius: 2px;
cursor: pointer;
overflow: hidden;
.uploader-default {
display: flex;
height: $upload-height;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
background: #fafafa;
p {
margin-top: 10px;
font-size: 14px;
color: #333;
line-height: 20px;
}
}
}
&.avatar-uploader-lg {
.el-upload {
width: 100%;
max-width: 820px;
height: $upload-lg-height;
.uploader-default {
height: $upload-lg-height;
}
}
}
.avatar {
display: block;
width: $upload-width;
height: $upload-height;
}
.avatar-lg {
display: block;
width: 100%;
height: $upload-lg-height;
}
.el-upload__tip {
margin-top: 0;
p {
font-size: 12px;
color: #333;
}
}
}
.style-wrap {
display: flex;
margin-top: 10px;
.label {
margin-right: 30px;
}
}
.styles {
display: flex;
flex-wrap: wrap;
width: 955px;
// height: 320px;
margin-top: 20px;
overflow: auto;
li {
margin: 0 20px 10px 0;
text-align: center;
cursor: pointer;
&:hover .review {
border-color: #9278ff;
}
}
.review {
display: flex;
justify-content: center;
align-items: center;
width: 170px;
height: 112px;
margin-bottom: 10px;
border: 1px solid #dcdee0;
border-radius: 2px;
img {
width: 80px;
}
.is-link {
width: 50px;
}
}
}
.info {
position: absolute;
top: 8px;
left: -32px;
cursor: pointer;
}
.plus {
margin-bottom: 10px;
font-size: 18px;
color: #9278ff;
text-align: right;
cursor: pointer;
}
.set-btn {
margin-left: 10px !important;
}
.manage-dia {
.edit,
.del {
font-size: 14px;
cursor: pointer;
}
.edit {
margin-right: 10px;
}
}
.input-form {
&.model {
height: calc(100vh - 340px);
padding-right: 20px;
overflow: auto;
.el-form-item__label {
padding-right: 20px;
}
.lg .el-form-item__label {
padding-right: 43px;
}
}
.item-line {
display: flex;
.el-form-item:not(:last-child) {
margin-right: 200px;
}
}
.line {
margin-bottom: 24px;
border-bottom: 1px dashed #c2c2c2;
}
.el-form-item--small.el-form-item {
margin-bottom: 24px;
}
.el-input,
.el-select {
width: 300px;
}
.el-select .el-input {
width: auto;
}
.el-textarea {
width: 550px;
}
.auto,
.auto .el-input {
width: auto;
}
.el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label:before {
font-size: 18px;
vertical-align: -4px;
color: #f5222d;
}
}
.btns {
text-align: center;
}
</style>