粒子研究院后台前端
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.
 
 
 
 

1495 lines
54 KiB

<template>
<div class="page">
<p class="page-name mb">文章详情</p>
<el-form :model="form" :rules="rules" class="input-form model" label-width="140px">
<el-form-item v-if="!isPublication && !isMedia" class="lg" prop="articleTemplate" label="独立文章模板">
<el-popover placement="top-start" trigger="hover" content="默认使用栏目中设置的文章样式,如果需要为该篇文章指定专门的模板样式,可以设置此项">
<img slot="reference" class="info" src="@/assets/images/ques.png" alt="">
</el-popover>
<div style="width: 940px;text-align: right;">
<el-switch v-model="form.templateStatus" :active-value="1" :inactive-value="0">
</el-switch>
</div>
<ul v-if="form.templateStatus" class="styles">
<template v-for="(item, i) in detailStyle">
<li v-if="item.id !== column.detailStyle" :key="i" @click="styleChange(item.id)">
<div class="review">
<img :class="{ 'is-link': item.id == 24 }" :src="require('@/assets/images/style/' + item.id + '.png')"
alt="">
</div>
<el-radio v-model="form.articleTemplate" :label="item.id">{{ item.style }}</el-radio>
</li>
</template>
</ul>
</el-form-item>
<el-form-item prop="title" label="标题">
<el-input id="articleTitle" style="width: 940px" placeholder="请输入标题" v-model="form.title" clearable
maxlength="300" @change="nameChange"></el-input>
</el-form-item>
<div class="item-line">
<el-form-item prop="columnId" label="所属栏目">
<el-cascader ref="column" v-model="form.columnId" :options="columns" :props="columnProps"
@change="columnChange"></el-cascader>
</el-form-item>
<el-form-item v-if="!isPeople" 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>
<!-- 专利 -->
<template v-if="isPatent">
<div class="item-line">
<el-form-item prop="patentClassId" label="专利类别">
<el-select v-model="form.patentClassId" clearable>
<template v-for="item in patentClasses">
<el-option :key="item.id" :label="item.name" :value="item.id">
</el-option>
</template>
</el-select>
</el-form-item>
<el-form-item prop="applicationNumber" label="申请号">
<el-input placeholder="请输入申请号" v-model.trim="form.applicationNumber" clearable maxlength="50"
class="inline-input"></el-input>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="applicationDate" label="申请日期">
<el-date-picker v-model="form.applicationDate" type="date" placeholder="选择日期" format="yyyy-MM-dd"
:clearable="false" value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
<el-form-item prop="dateOfAuthorization" label="授权日期">
<el-date-picker v-model="form.dateOfAuthorization" type="date" placeholder="选择日期" format="yyyy-MM-dd"
:clearable="false" value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</div>
<el-form-item prop="inventor" label="发明人">
<el-input style="width: 940px" type="textarea" v-model="form.inventor" :rows="3"></el-input>
</el-form-item>
</template>
<!-- 专著 -->
<template v-if="isMonograph">
<div class="item-line">
<el-form-item prop="publishingHouse" label="出版社">
<el-input placeholder="请输入出版社" v-model.trim="form.publishingHouse" clearable maxlength="50"
class="inline-input"></el-input>
</el-form-item>
<el-form-item prop="writersAndEditors" label="编写人员">
<el-input placeholder="请输入编写人员" v-model.trim="form.writersAndEditors" clearable maxlength="50"
class="inline-input"></el-input>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="publicationYear" label="出版时间">
<el-date-picker style="width: 300px" v-model="form.publicationYear" type="year" placeholder="请选择出版时间"
format="yyyy" value-format="yyyy">
</el-date-picker>
</el-form-item>
</div>
</template>
<!-- 期刊详情 or 论文 -->
<template v-if="isJournal || isThesis">
<div class="item-line">
<el-form-item prop="doi" label="DOI">
<el-input placeholder="请输入DOI" v-model.trim="form.doi" clearable maxlength="50"
class="inline-input"></el-input>
</el-form-item>
<el-form-item prop="publicationYear" :label="isThesis ? '发表年度' : '出版年份'">
<el-date-picker style="width: 300px" v-model="form.publicationYear" type="year"
:placeholder="'请选择' + (isThesis ? '发表年度' : '出版年份')" format="yyyy" value-format="yyyy">
</el-date-picker>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="periodicalName" :label="isThesis ? '期刊名称' : '刊物名称'">
<el-input :placeholder="'请输入' + (isThesis ? '期刊名称' : '刊物名称')" v-model="form.periodicalName" clearable
maxlength="50" class="inline-input"></el-input>
</el-form-item>
<div style="display: inline-flex;">
<el-form-item prop="reel" label="卷" style="margin-right: 0;">
<el-input placeholder="请输入" v-model="form.reel" clearable maxlength="50" style="width: 110px"></el-input>
</el-form-item>
<el-form-item prop="documentNumber" label="文献号" label-width="80px">
<el-input placeholder="请输入" v-model="form.documentNumber" clearable maxlength="50"
style="width: 110px"></el-input>
</el-form-item>
</div>
</div>
<el-form-item prop="author" label="作者">
<el-input style="width: 940px" type="textarea" v-model="form.author" :rows="3"></el-input>
</el-form-item>
</template>
<div v-if="!isPeople && !isMedia" 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 v-if="form.articleTemplate === 25" prop="activityStartTime" label="起止时间">
<el-input placeholder="请输入时间,例:2023-10-31 08:00" v-model="form.activityStartTime" clearable maxlength="50"
class="inline-input"></el-input>
<!-- <el-date-picker style="width: 300px"
v-model="form.time"
type="datetimerange"
range-separator="~"
:clearable="false"
start-placeholder="开始日期"
end-placeholder="结束日期"> -->
</el-date-picker>
</el-form-item>
<el-form-item v-else-if="!isJournal && !isThesis" prop="author" label="作者">
<el-input placeholder="请输入作者" v-model.trim="form.author" clearable maxlength="200"
class="inline-input"></el-input>
</el-form-item>
</div>
<template v-if="!isPublication && !isMedia">
<div v-if="form.articleTemplate === 25" class="item-line">
<el-form-item prop="lectureSeries" label="演讲系列">
<el-input placeholder="请输入演讲系列" v-model.trim="form.lectureSeries" clearable maxlength="50"
class="inline-input"></el-input>
</el-form-item>
<el-form-item prop="onlineLocation" label="线上地点">
<el-input placeholder="请输入线上地点" v-model.trim="form.onlineLocation" clearable maxlength="50"
class="inline-input"></el-input>
</el-form-item>
</div>
<div v-if="form.articleTemplate === 22 || form.articleTemplate === 23 || isOrg" 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>
<template v-if="form.articleTemplate === 25">
<div class="item-line">
<el-form-item prop="classificationId" label="所属分类">
<el-select style="width: 234px;" v-model="getModelData" clearable>
<!-- <el-select style="width: 234px;" v-model="form.classificationId" :value="classificationName.find(i=>i.id === form.classificationId ? form.classificationId : '')" clearable> -->
<template v-for="item in classifications">
<el-option v-if="item.classificationName" :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="offlineLocation" label="线下地点">
<el-input placeholder="请输入线下地点" v-model="form.offlineLocation" clearable maxlength="100"></el-input>
</el-form-item>
</div>
<el-form-item prop="keynoteSpeaker" label="主讲人">
<el-input style="width: 940px" placeholder="请输入主讲人" v-model="form.keynoteSpeaker" clearable
maxlength="100"></el-input>
</el-form-item>
<el-form-item prop="eventProfile" label="活动简介">
<el-input style="width: 940px" placeholder="请输入活动简介" v-model="form.eventProfile" type="textarea"
clearable></el-input>
</el-form-item>
</template>
<div v-if="form.articleTemplate === 22 || form.articleTemplate === 23 || isOrg" class="item-line">
<el-form-item prop="source" label="所属分类">
<el-select style="width: 234px;" v-model="getModelData" clearable>
<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 v-if="form.articleTemplate === 22 || form.articleTemplate === 23 || isPeople || isOrg"
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="titleImg" :label="form.articleTemplate === 25 ? '标题图' : '封面图'">
<el-upload class="avatar-uploader" accept=".jpg,.png,.jpeg,.gif" :on-change="file => changeFile(file, 0)"
:show-file-list="false" :action="this.api.upload" :auto-upload="false">
<img v-if="form.titleImg" :src="form.titleImg" class="avatar">
<div class="uploader-default" v-else>
<img class="plus" src="@/assets/images/plus.png" alt="">
<p>点击上传</p>
</div>
</el-upload>
</el-form-item>
<el-form-item v-if="form.articleTemplate === 22 || form.articleTemplate === 25 || form.articleTemplate === 69"
prop="bannerImg" label="Banner图(选填)" style="flex: 1;">
<el-upload class="avatar-uploader avatar-uploader-lg" accept=".jpg,.png,.jpeg,.gif"
:on-change="file => changeFile(file, 1)" :show-file-list="false" :action="this.api.upload"
:auto-upload="false">
<img v-if="form.bannerImg" :src="form.bannerImg" class="avatar-lg">
<div class="uploader-default" v-else>
<img class="plus" src="@/assets/images/plus.png" alt="">
<p>点击上传</p>
</div>
</el-upload>
</el-form-item>
</template>
<!-- 人物详情 -->
<template v-if="isPeople">
<div class="item-line">
<el-form-item prop="post" label="岗位">
<el-input placeholder="请输入岗位" v-model="form.post" clearable class="inline-input"></el-input>
</el-form-item>
<el-form-item prop="major" label="专业">
<el-input placeholder="请输入专业" v-model="form.major" clearable class="inline-input"></el-input>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="hobby" label="爱好">
<el-input placeholder="请输入爱好" v-model="form.hobby" clearable class="inline-input"></el-input>
</el-form-item>
<el-form-item prop="honor" label="荣誉">
<el-input placeholder="请输入荣誉" v-model="form.honor" clearable class="inline-input"></el-input>
</el-form-item>
</div>
</template>
<el-form-item v-if="form.articleTemplate !== 24 && form.articleTemplate !== 26 && !isPublication && !isMedia"
prop="mainBody" label="正文">
<Editor api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda' v-model="form.mainBody"
:init="editorConfig" />
</el-form-item>
<template v-if="isJournal || isPublication">
<el-form-item prop="publicationTypeId" label="出版物类型">
<el-select style="width: 234px;" v-model="form.publicationTypeId">
<template v-for="item in publicationTypes">
<el-option :key="item.id" :label="item.name" :value="item.id">
</el-option>
</template>
</el-select>
</el-form-item>
<el-form-item prop="quote" label="引用">
<el-input style="width: 940px" type="textarea" v-model="form.quote" :rows="3"></el-input>
</el-form-item>
<el-form-item prop="articleKeyWord" label="关键字">
<el-input style="width: 940px" v-model="form.articleKeyWord"></el-input>
</el-form-item>
<el-form-item prop="mainBody" label="摘要">
<Editor api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda' v-model="form.mainBody"
:init="editorConfig" />
</el-form-item>
</template>
<template v-if="form.articleTemplate === 24">
<el-form-item prop="connectionType" label="连接类型">
<el-radio-group v-model="form.connectionType">
<el-radio :label="1">站内链接</el-radio>
<el-radio :label="2">站外链接</el-radio>
<el-radio :label="3">其他站点链接</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="form.connectionType === 1">
<el-form-item label="站内链接">
<el-cascader v-model="links" :options="columns" :props="columnProps" clearable
@change="getArticle"></el-cascader>
</el-form-item>
<el-form-item label="文章">
<el-select v-model="article" clearable>
<el-option v-for="item in articles" :key="item.id" :label="item.title" :value="item.id">
</el-option>
</el-select>
</el-form-item>
</template>
<el-form-item v-show="form.connectionType === 2" prop="linkAddress" label="站外链接">
<el-input placeholder="请输入站外链接" v-model.trim="form.linkAddress" clearable></el-input>
</el-form-item>
<template v-if="form.connectionType === 3">
<el-form-item prop="siteSelection" label="站点选择">
<el-select v-model="form.siteSelection" @change="getOtherColumn">
<el-option v-for="item in sites" :key="item.id" :label="item.siteName" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="栏目">
<el-cascader v-model="otherLink" :options="otherColumns" :props="columnProps" clearable
@change="getArticle"></el-cascader>
</el-form-item>
<el-form-item label="文章">
<el-select v-model="otherArticle" clearable>
<el-option v-for="item in otherArticles" :key="item.id" :label="item.title" :value="item.id">
</el-option>
</el-select>
</el-form-item>
</template>
<el-form-item prop="isOpen" label="新窗口打开">
<el-switch v-model="form.isOpen" :active-value="1" :inactive-value="0">
</el-switch>
</el-form-item>
</template>
<el-form-item v-if="form.articleTemplate !== 24 && form.articleTemplate !== 26 && !isPeople" prop="file"
label="文件上传">
<el-upload v-if="isMedia"
accept=".jpg,.png,.jpeg,.gif,.mp4,.3gp,.mov,.m4v,.avi,.dat,.mkv,.flv,.vob,.rmvb,.rm,.qlv"
:before-upload="file => fileBeforeUpload(file, 1)" :on-remove="handleRemove" :on-success="uploadSuccessFile"
:on-error="uploadError" :action="this.api.upload" :file-list="form.fileList" :limit="1"
:on-exceed="handleExceed" :headers="headers" :data="{
quote: form.title,
site: site.siteName,
uploader: userName
}">
<el-button>上传</el-button>
</el-upload>
<el-upload v-else :before-upload="file => fileBeforeUpload(file, 0)" :on-remove="handleRemove"
:on-success="uploadSuccessFile" :action="this.api.upload" :file-list="form.fileList" :headers="headers" :data="{
quote: form.title,
site: site.siteName,
uploader: userName
}">
<el-button>上传</el-button>
</el-upload>
</el-form-item>
</el-form>
<div class="btns">
<el-button type="primary" @click="submit(1)">发布</el-button>
<el-button v-if="$route.query.id" @click="preview">预览</el-button>
<el-button @click="submit(0)">保存草稿</el-button>
<el-button @click="back">取消</el-button>
</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 'tinymce-paragraphspacing'
import editorConfig from './editor'
import Cropper from '@/components/img-upload/Cropper'
import Axios from 'axios'
import ColumnConst from '@/const/column'
export default {
data () {
return {
site: this.$store.state.content.site,
userId: this.$store.state.user.userId,
publicationTypes: ColumnConst.publicationTypes,
patentClasses: ColumnConst.patentClasses,
headers: {
token: Util.local.get(Setting.tokenKey)
},
nameRepeat: false,
sites: [],
detailStyle: [],
columns: [],
articles: [],
otherArticles: [],
columnProps: {
checkStrictly: true,
value: 'id',
label: 'columnName'
},
links: [],
article: '',
otherColumns: [],
otherLink: [],
otherArticle: '',
form: {
siteId: this.$store.state.content.site.id,
id: this.$route.query.id || '',
founderId: this.$store.state.user.userId,
editorId: this.$store.state.user.userId,
templateStatus: 0,
articleTemplate: '',
doi: '',
quote: '',
articleKeyWord: '',
publicationTypeId: '',
publicationYear: '',
periodicalName: '',
reel: '',
documentNumber: '',
activityEndTime: '',
activityStartTime: '',
time: '',
lectureSeries: '',
onlineLocation: '',
offlineLocation: '',
keynoteSpeaker: '',
eventProfile: '',
author: '',
edit: '',
audit: '',
bannerImg: '',
lableId: [],
classificationId: '',
columnId: +this.$route.query.columnId,
file: '',
isRelease: 0,
mainBody: '',
releaseTime: new Date(),
source: '',
summary: '',
title: '',
titleImg: '',
connectionType: 1,
linkAddress: '',
siteSelection: '',
fileList: [],
isOpen: 1,
patentClassId: '',
patentName: '',
writersAndEditors: '',
inventor: '',
famousWorks: '',
applicationNumber: '',
applicationDate: '',
dateOfAuthorization: '',
publishingHouse: '',
major: '',
post: '',
honor: '',
hobby: '',
},
rules: {
title: [
{ required: true, message: '请输入标题', trigger: 'blur' }
],
columnId: [
{ required: true, message: '请选择所属栏目', trigger: 'change' }
],
// time: [
// { required: true, message: '请选择起始时间', trigger: 'change' }
// ],
activityStartTime: [
{ required: true, message: '请输入起始时间', trigger: 'blur' }
],
classificationId: [
{ required: false, message: '请选择所属分类', trigger: 'change' }
],
eventProfile: [
{ required: true, message: '请输入活动简介', trigger: 'blur' }
],
releaseTime: [
{ required: true, message: '请选择发布日期', trigger: 'change' }
],
publicationYear: [
{ required: true, message: '请选择出版年份', trigger: 'change' }
],
mainBody: [
{ required: true, message: '请输入正文', trigger: 'blur' }
],
connectionType: [
{ required: true, message: '请选择连接类型', trigger: 'blur' }
],
file: [
{ required: false, message: '请上传文件', trigger: 'change' }
],
},
columnInfo: {},
editorConfig,
submiting: false, // 新增编辑防抖标识
pass: false,
uploading: 0,
updateTime: 0,
cropperModel: false,
isUpload: false,
fixedNumber: [1.76, 1],
file: {}, // 当前被选择的图片文件
isBanner: 0,
classifications: [],
classVisible: false,
labels: [],
labelVisible: false,
originalName: '',
originColumnId: '',
repeatMsg: '',
};
},
computed: {
...mapState('user', [
'userName'
]),
...mapState('content', [
'column'
]),
// 栏目的栏目模板是出版物
isPublication () {
return this.columnInfo.templateId === 11
},
// 论文
isThesis () {
return this.columnInfo.listStyleId === 46
},
// 专利
isPatent () {
return this.columnInfo.listStyleId === 44
},
// 专著
isMonograph () {
return this.columnInfo.listStyleId === 45
},
// 媒体库
isMedia () {
return this.columnInfo.listStyleId === 74
},
// 期刊详情
isJournal () {
return this.form.articleTemplate === 26
},
// 人物详情
isPeople () {
return this.form.articleTemplate === 72
},
// 组织架构
isOrg () {
return this.form.articleTemplate === 69
},
getModelData: {
get () {
const data = this.classifications.find(item => item.id === this.form.classificationId)
return data ? data.id : ''
},
set (newVal) {
this.form.classificationId = newVal
}
},
},
components: {
Editor,
Cropper,
},
watch: {
// 监听信息是否有更改,有的话页面离开的时候要询问是否要保存
form: {
handler (val) {
this.updateTime++
},
deep: true
}
},
// 页面离开的时候如果没有保存则提示
beforeRouteLeave (to, from, next) {
if (this.submiting) {
next()
} else if (!this.pass) {
// 更改了信息才需要提示
if (this.updateTime > 1) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.submit(this.form.isRelease, next)
}).catch(() => {
next()
})
} else {
next()
}
} else {
next()
}
},
mounted () {
this.$store.commit('user/setCrumbs', [
{
name: '站点管理',
route: '/site'
},
{
name: '内容管理'
},
{
name: '文章管理',
route: '/article'
},
{
name: this.$route.query.columnName,
route: '/article'
},
{
name: this.$route.query.id ? '编辑' : '新增'
}
])
this.getList()
this.getSite()
this.getLabel()
this.getTemplate()
},
methods: {
ready (editorInstance) {
console.log(`编辑器实例${editorInstance.key}: `, editorInstance)
},
// 获取栏目
getList () {
this.$post(this.api.listWithTree, Util.rsa({
siteId: this.site.id,
columnName: '',
templateId: '',
typeId: '',
isSort: 1
})).then(({ data }) => {
this.columns = data
let { columnId } = this.$route.query
// 如果是新增文章,则要默认选中栏目,因为从外面带进来的是单个id,要取到父id来选中到里面的层级
if (columnId && data.length) {
columnId = +columnId
let ids = []
// 递归获取完整id
const getId = (list, parentId) => {
for (const i in list) {
const e = list[i]
if (e.id === columnId) {
ids = [...parentId, list[i].id]
break
} else {
getId(e.children, [...parentId, e.id])
}
}
}
getId(data, [])
if (!ids.length) ids = [data[0].id] // 如果因为切换站点而没有匹配的栏目id,则取第一个栏目
this.form.columnId = ids
}
this.form.id ? this.getData() : this.getColumn()
}).catch(err => { })
},
// 文章列表
getArticle () {
// 站内链接/其他站点链接
const inner = this.form.connectionType === 1
const id = inner ? this.links[this.links.length - 1] : this.otherLink[this.otherLink.length - 1]
this[inner ? 'article' : 'otherArticle'] = ''
this.$post(this.api.queryArticle, Util.rsa({
siteId: inner ? this.site.id : this.form.siteSelection,
columnIds: [id],
pageNum: 1,
pageSize: 1000,
title: '',
isDisable: 0
})).then(({ data }) => {
this[inner ? 'articles' : 'otherArticles'] = data.records.filter(e => e.isRelease) // 只显示已发布的文章
}).catch(err => { })
},
// 获取文章详情
getData () {
this.$post(this.api.findArticle, Util.rsa(this.form.id)).then(({ data }) => {
data.lableId = data.lableId ? data.lableId.split(',').map(e => +e) : []
// if (data.activityStartTime && data.activityEndTime) data.time = [data.activityStartTime, data.activityEndTime]
// 文件上传回显
if (data.fileList) {
data.fileList.map(e => {
e.name = e.fileName
})
}
// 链接回显
if (data.articleTemplate === 24 && data.connectionType !== 2 && data.linkAddress) {
const columnArticle = data.linkAddress.split('-')
const column = columnArticle[0].split(',').map(e => +e)
const article = columnArticle[1] || '' // 获取文章id(文章id是附在linkAddress最后面的-后面的数字)
const { connectionType } = data
// 获取文章
this.$post(this.api.queryArticle, Util.rsa({
siteId: connectionType === 1 ? this.site.id : data.siteSelection,
columnIds: [column[column.length - 1]], // 截取走最后面的文章id,最后一个id就是栏目id
pageNum: 1,
pageSize: 1000,
title: '',
isDisable: 0
})).then(res => {
this[connectionType === 1 ? 'articles' : 'otherArticles'] = res.data.records
// 站内链接/其他站点链接
if (connectionType === 1) {
this.links = column
this.form.linkAddress = ''
if (article) this.article = +article
} else if (connectionType === 3) {
this.otherLink = column
this.form.linkAddress = ''
if (article) this.otherArticle = +article
}
}).catch(err => { })
}
this.originalName = data.title
this.originColumnId = data.columnId
let lableData = []
data.lableId.forEach(item => {
this.labels.forEach(options => {
if (item == options.id) {
lableData.push(item)
}
})
})
data.lableId = lableData
this.form = data
data.siteSelection && this.getOtherColumn()
this.getColumn()
}).catch(err => { })
},
// 获取栏目详情
getColumn () {
this.$post(this.api.findColumn, Util.rsa(this.$route.query.columnId)).then(({ data }) => {
this.columnInfo = data
const { form } = this
// 如果独立文章模板未启用,并且该栏目的类型为常规/子级优先,则把栏目所选的详情样式赋值到文章模板;如果栏目类型为长页或者链接,则文章模板默认为文章(23)
if (!form.templateStatus) {
form.articleTemplate = (data.typeId === 1 || data.typeId === 4) ? data.detailStyleId : 23
}
this.getClassification()
this.handleRules()
this.$nextTick(() => {
this.updateTime = 0
})
}).catch(err => { })
},
// 处理表单验证
handleRules () {
const { articleTemplate } = this.form
// 会议活动
console.log("🚀 ~ file: index.vue:1157 ~ handleRules ~ this.columnInfo:", this.rules, this.form, this.columnInfo)
// if (articleTemplate === 25) {
// this.rules.titleImg[0].required = false
// } else {
// this.rules.titleImg[0].required = true
// }
if (this.columnInfo.listStyleId === 74) this.rules.file[0].required = true
if (this.columnInfo.templateId === 11) {
this.rules.mainBody[0].required = false
}
},
// 独立文章模板选择回调
styleChange (id) {
this.form.articleTemplate = id
this.handleRules()
},
// 所属栏目选择回调
columnChange (val) {
const checked = this.$refs.column.getCheckedNodes()
if (checked && checked.length) {
// 所属栏目改变后重新查询所属分类
this.columnInfo = checked[checked.length - 1].data
this.getClassification()
}
},
// 每个层级加上父级id的集合
getId (list, ids) {
list.forEach(e => {
e.ids = ids ? [...ids, e.id] : [e.id]
e.children.length ? this.getId(e.children, e.ids) : delete e.children
})
},
// 获取站点列表
getSite () {
this.$post(this.api.site, {
page: 1,
limit: 1000,
siteName: ''
}).then(({ data }) => {
data.records.splice(data.records.findIndex(e => e.id == this.site.id), 1) // 不显示当前站点
this.sites = data.records
}).catch(e => { })
},
// 获取指定站点的栏目列表
getOtherColumn (val) {
this.$post(this.api.listWithTree, Util.rsa({
siteId: this.form.siteSelection,
columnName: '',
templateId: '',
typeId: '',
isSort: 1
})).then(({ data }) => {
if (val) {
this.otherArticles = []
this.otherArticle = ''
this.otherLink = ''
}
this.otherColumns = data
}).catch(err => { })
},
// 获取所有模板
getTemplate () {
this.$post(this.api.individualTemplateDetailsStyle).then(({ data }) => {
const result = []
data.map(e => {
result.find(n => n.style === e.style) || result.push(e)
})
this.detailStyle = result
}).catch(err => { })
},
// 获取所属分类
getClassification () {
this.$post(this.api.queryClassif, Util.rsa({
siteId: this.site.id,
templateId: this.columnInfo.templateId
})).then(({ data }) => {
this.classifications = data
}).catch(err => { })
},
// 显示所属分类弹框
setClass () {
this.classVisible = true
},
// 新增所属分类
addClass () {
this.classifications.push({
edit: true,
id: '',
classificationName: ''
})
},
// 编辑所属分类
editClass (row) {
this.$set(row, 'edit', 1)
},
// 删除所属分类
delClass (row, i) {
if (row.id) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(this.api.delClassif, Util.rsa(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.checkClassif, Util.rsa({
classificationName: encodeURI(row.classificationName),
siteId: this.site.id,
classificationId: row.id
})).then(res => {
this.$post(this.api[row.id ? 'updateClassif' : 'saveClassif'], Util.rsa({
classificationName: encodeURI(row.classificationName),
templateId: this.columnInfo.templateId,
id: row.id,
siteId: this.site.id,
editorId: this.userId,
founderId: this.userId
})).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'
}).then(() => {
list.map(e => {
e.edit && e.classificationName && this.submitClass(e, 0)
})
this.classVisible = false
}).catch(() => {
this.classVisible = false
})
} else {
this.classVisible = false
}
},
// 获取标签
getLabel () {
this.$post(this.api.queryLabel, Util.rsa(this.site.id)).then(({ data }) => {
this.labels = data
}).catch(err => { })
},
// 显示标签弹框
setLabel () {
this.labelVisible = true
},
// 新增标签
addLabel () {
this.labels.push({
edit: true,
id: '',
labelName: ''
})
},
// 编辑标签
editLabel (row) {
this.$set(row, 'edit', 1)
},
// 删除标签
delLabel (row, i) {
if (row.id) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(this.api.delLabel, Util.rsa(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.checkLabel, Util.rsa({
labelName: encodeURI(row.labelName),
siteId: this.site.id,
labelId: row.id,
})).then(res => {
this.$post(this.api[row.id ? 'updateLabel' : 'saveLabel'], Util.rsa({
labelName: encodeURI(row.labelName),
id: row.id,
siteId: this.site.id,
editorId: this.userId,
founderId: this.userId
})).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'
}).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, {
siteId: this.site.id,
title,
id: id || ''
}).then(res => {
this.repeatMsg = ''
this.nameRepeat = false
}).catch(res => {
if (res.msg) this.repeatMsg = res.msg
this.nameRepeat = true
})
} else {
this.repeatMsg = ''
this.nameRepeat = false
}
},
// 图片裁剪上传事件
customUpload (data) {
const formData = new FormData()
formData.append('file', data, this.file.name)
formData.append('quote', this.form.title)
formData.append('site', this.site.siteName)
formData.append('uploader', this.userName)
this.imgUpload(formData)
},
// base64转成bolb对象
dataURItoBlob (base64Data) {
let byteString
if (base64Data.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(base64Data.split(',')[1])
} else {
byteString = unescape(base64Data.split(',')[1])
}
const mimeString = base64Data
.split(',')[0]
.split(':')[1]
.split(';')[0]
const ia = new Uint8Array(byteString.length)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ia], {
type: mimeString
})
},
// 图片上传到服务器
imgUpload (formData) {
this.isUpload = true
Axios({
method: 'post',
url: this.api.upload,
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
token: Util.local.get(Setting.tokenKey)
},
}).then(({ data }) => {
if (data.code === 401) {
Util.errorMsg(data.msg)
setTimeout(() => {
this.$store.dispatch('user/logout')
}, 1000)
return false
}
let url = this.form[this.isBanner ? 'bannerImg' : 'titleImg']
// url && this.$del(this.api.delFile, Util.rsa([url.split('/').pop()])).then(res => { }).catch(e => { }) // 删除替换掉的图片
this.form[this.isBanner ? 'bannerImg' : 'titleImg'] = data.url
}).catch(res => {
})
this.$refs.cropper.isDisabled = false
this.isUpload = false
this.cropperModel = false
},
// 图片改变钩子
changeFile (file, isBanner) {
// 封面图跟banner的截取比例不一样,期刊详情模板的也不一样
this.fixedNumber = isBanner ?
[1, 0.26] :
this.isPeople ?
[1, 1] :
this.isJournal ?
[1, 1.5] :
[1.76, 1]
this.isBanner = isBanner
const { size, name } = file
const ext = name.substring(name.lastIndexOf('.') + 1)
if (!Util.isImg(ext)) {
this.$message.error('请上传图片!')
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) {
e.id ? this.$post(`${this.api.delContentFile}?id=${e.id}`).then(res => {
this.form.fileList = fileList
}).catch(res => { }) : (this.form.fileList = fileList)
},
// banner上传成功
uploadSuccessBanner (res) {
let url = this.form.bannerImg
// url && this.$del(this.api.delFile, Util.rsa([url.split('/').pop()])).then(res => { }).catch(e => { })
this.form.bannerImg = res.url
},
handleExceed (files, fileList) {
this.$message.warning(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`);
},
// 附件上传之前的钩子
fileBeforeUpload (file, type) {
if (type) {
const { size, name } = file
const ext = name.substring(name.lastIndexOf('.') + 1)
if (!Util.isImg(ext) && !Util.isVideo(ext)) {
this.$message.error('请上传图片或者视频!')
return false
}
if (size / 1024 / 1024 > 100) {
this.$message.error('请上传100M以内的图片!')
return false
}
} else {
const { name } = file
const ext = name.substring(name.lastIndexOf('.') + 1)
if (!Util.isImg(ext) && !Util.isVideo(ext) && !Util.isDoc(ext) && !Util.isAudio(ext) && ext !== 'pdf') {
this.$message.error('请上传合规文件!')
return false
}
}
this.uploading++
},
// 上传失败
uploadError (err, file, fileList) {
this.uploading--
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
})
},
// 附件上传成功
uploadSuccessFile (res) {
this.uploading--
this.form.id ?
this.$post(this.api.saveContentFile, {
contentId: this.form.id,
editorId: this.userId,
founderId: this.userId,
id: '',
fileName: res.original,
filePath: res.url
}).then(({ data }) => {
this.form.fileList.push({
name: res.original,
url: res.url,
id: data
})
}).catch(res => { }) :
this.form.fileList.push({
name: res.original,
url: res.url
})
},
// 预览
preview () {
localStorage.setItem('article', JSON.stringify(this.form))
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}&preview=1`)
},
// 返回
back () {
this.pass = true
const { updateTime } = this
// 更改了信息才需要提示
if (updateTime > 1) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.submit(this.form.isRelease)
}).catch(() => {
this.$router.back()
})
} else {
this.$router.back()
}
},
// 更新附件的状态为发布
updateFile (files, form, quoteId) {
files.map(e => {
this.$post(this.api.updateFile, {
id: e,
isRelease: form.isRelease,
quote: form.title,
quoteId
}).then(res => { }).catch(err => { })
})
},
// 提交
submit (isRelease, next) {
if (this.submiting) return false
const form = JSON.parse(JSON.stringify(this.form))
if (!form.title) return Util.errorMsg('请填写标题')
if (this.nameRepeat) return Util.errorMsg('该标题已重复!')
if (typeof form.fatherId === 'object') form.fatherId = form.fatherId[form.fatherId.length - 1]
const tId = form.articleTemplate
// 如果是发布
if (isRelease) {
// 媒体库只需要校验标题和附件
if (this.isMedia) {
if (!form.fileList.length) return Util.errorMsg('请上传文件')
} else {
// 每个模板需要展示的字段不一样,因此要根据模板id来判断必填
if (tId !== 25) {
if (!form.releaseTime) return Util.errorMsg('请选择发布日期')
}
// 非出版物类型的栏目才需要判断下列必填
if (!this.isPublication) {
// if (tId === 22 || tId === 23 || tId === 24) {
// if (!form.titleImg) return Util.errorMsg('请上传封面')
// }
if (tId === 25) {
if ((!form.activityStartTime) && isRelease) return Util.errorMsg('请输入起止时间')
// if ((!form.time || !form.time.length) && isRelease) return Util.errorMsg('请选择起止时间')
// form.activityStartTime = form.time[0]
// form.activityEndTime = form.time[1]
}
if (tId === 24 && form.connectionType !== 2) {
if (form.connectionType === 1) {
if (!this.links.length) return Util.errorMsg('请选择站内链接')
}
if (!this.otherLink.length && form.connectionType === 3) {
if (!this.otherLink.length) return Util.errorMsg('请选择栏目')
}
}
if ((tId === 22 || tId === 23 || tId === 25) && !form.mainBody) return Util.errorMsg('请输入正文')
}
}
}
if (this.uploading) return Util.errorMsg('文件正在上传,请上传完成后再发布')
if (form.connectionType === 1) {
form.linkAddress = this.links.join()
if (this.article) form.linkAddress += '-' + this.article
} else if (form.connectionType === 3) {
form.linkAddress = this.otherLink.join()
if (this.otherArticle) form.linkAddress += '-' + this.otherArticle
}
const { columnId, bannerImg, fileList, titleImg } = form
const fileId = []
if (typeof columnId === 'object') form.columnId = columnId[columnId.length - 1] // 如果更换了栏目id,值会变成数组,需要手动获取最后一个
// 获取几个附件的id,url后面的数字串即是附件id
if (bannerImg) fileId.push(bannerImg.substr(bannerImg.lastIndexOf('/') + 1))
if (titleImg) fileId.push(titleImg.substr(titleImg.lastIndexOf('/') + 1))
fileList && fileList.map(e => {
fileId.push(e[e.url ? 'url' : 'filePath'].substr(e[e.url ? 'url' : 'filePath'].lastIndexOf('/') + 1))
})
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
form.editorId = +this.$store.state.user.userId
this.$post(this.api.updateArticle, form).then(res => {
this.updateFile(fileId, form, form.id)
Util.successMsg('修改成功')
next ? next() : this.$router.push(`list?columnId=` + form.columnId + (form.columnId != this.originColumnId ? '&last=1' : '')) // 更改了所属栏目,则给列表传递一个last参数,跳转到最后一页
}).catch(err => {
this.submiting = false
})
} else {
this.$post(this.api.saveArticle, form).then(({ data }) => {
this.updateFile(fileId, form, data)
// 新增文章完后需要把上传的附件添加到文章附件表
form.fileList.map(e => {
this.$post(this.api.saveContentFile, {
contentId: data,
editorId: this.userId,
founderId: this.userId,
id: '',
fileName: e.name,
filePath: e.url
}).then(res => { }).catch(err => { })
})
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: #2962ff;
}
}
.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: #2962ff;
text-align: right;
cursor: pointer;
}
.set-btn {
margin-left: 10px !important;
}
.manage-dia {
.edit,
.del {
font-size: 14px;
cursor: pointer;
}
.edit {
margin-right: 10px;
}
}
.editor {
line-height: normal;
}
</style>