Files
laws-sinotruk-client/src/views/businessSupport/questionAnswerLibrary/page/AnswerPage.vue
T

453 lines
14 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>
<internal-detail-page :title="pageTitle" :loading="loading">
<div class="detail-page-title">{{ model.title }}</div>
<div class="detail-page-second-title">
<!-- todo: 发帖人部门没有返回 -->
{{ $t('businessSupport.questionAnswer.poster') + ':' + model.orgCode_dictText + ' ' + model.userId_dictText }}
</div>
<div class="detail-page-part">
<div class="detail-page-part-form">
<!-- 标准号/标准名称 -->
<div class="detail-page-part-form-item-large">
<label>{{ $t('standardNumOrName') }}</label>
<span>{{ model.standardNumber && model.standardName ? model.standardNumber + ' ' + model.standardName : global.emptyLine }}</span>
</div>
<!-- 项目 -->
<div class="detail-page-part-form-item-large">
<label>{{ $t('project') }}</label>
<span>{{ model.project_dictText || global.emptyLine }}</span>
</div>
<!-- 附件 -->
<div class="detail-page-part-form-item-large-file">
<label>{{ $t('businessSupport.questionAnswer.attach') }}</label>
<template v-if="fileList && fileList.length > 0">
<div class="file-box">
<div class="file-list-file" v-for="file in fileList" :key="file.id">
<div class="file-list-file-info">
<a-icon type="link" />
<div class="file-list-file-name" @click="handlePreview(file)">{{ file.fileName }}</div>
</div>
<!-- 下载-->
<a-button type="link" icon="download" class="file-btn" @click="handleDownload(file)">
{{ $t('download') }}
</a-button>
<!-- 无水印下载-->
<!--<a-button type="link" v-has="btnPermission.unwatermarkedDownload" class="file-btn">-->
<!-- <i class="iconfont icon-water-drop-slash"></i>-->
<!-- {{ $t('unwatermarkedDownload') }}-->
<!--</a-button>-->
</div>
</div>
</template>
<span v-else>{{ global.emptyLine }}</span>
</div>
</div>
</div>
<!-- 问题描述部分 -->
<div class="question-desc-wrapper">
<p class="question-desc">{{ model.problemDescription }}</p>
<p class="right-bottom-p">
<span class="time-span">{{ model.quizTime }}</span>
<span class="right-bottom-p-span">{{ answerArr.length + $t('businessSupport.questionAnswer.answerNum')}}</span>
</p>
</div>
<!-- 历史回答数据 -->
<template v-if="answerArr && answerArr.length > 0">
<div v-for="(item, index) in answerArr" :key="index" class="answer-wrapper">
<div class="left-user-info">
<a-avatar shape="square" :size="56" :src="getAvatarView(item.avatar)" icon="user"/>
<p class="left-user-name">{{ item.name }}</p>
<p>{{ item.departName }}</p>
</div>
<div class="right-answer-wrapper">
<!-- 是否是置顶 -->
<p v-if="item.isTop" class="top-p">{{ $t('businessSupport.questionAnswer.top') }}</p>
<!-- 回答描述 -->
<p :class="!item.isTop ? 'no-top-desc' : ''">{{ item.answerDescription }}</p>
<p class="right-bottom-p">
<span>{{ item.createTime }}</span>
<!-- 置顶评论的操作按钮 -->
<template v-if="item.isTop">
<!-- 取消置顶 -->
<a class="right-bottom-p-a" @click="setOrCancelTop(item.id)" v-has="'quiz:detail:topOrCancel'">{{ $t('businessSupport.questionAnswer.cancelTop') }}</a>
<!-- 删除 : 发帖人、评论人、有置顶权限的用户可以删除 ?? -->
<a v-if="userInfo.id === model.userId || userInfo.id === item.userId" v-has="'quiz:detail:deleteAnswer'" class="right-bottom-p-a" @click="deleteAnswer(item.id)">{{ $t('delete') }}</a>
</template>
<!-- 非置顶评论 -->
<template v-else>
<!-- 设置为置顶 -->
<a class="right-bottom-p-a" @click="setOrCancelTop(item.id)" v-has="'quiz:detail:topOrCancel'">{{ $t('businessSupport.questionAnswer.setTop') }}</a>
<!-- 删除 : 发帖人、评论人、有置顶权限的用户可以删除,置顶的评论不允许删除,取消置顶后允许删除 ?? -->
<a v-if="userInfo.id === model.userId || userInfo.id === item.userId" v-has="'quiz:detail:deleteAnswer'" class="right-bottom-p-a" @click="deleteAnswer(item.id)">{{ $t('delete') }}</a>
</template>
</p>
</div>
</div>
</template>
<!-- 回答区域 -->
<div v-if="canAnswer === 1" class="answer-wrapper">
<div class="left-user-info">
<a-avatar shape="square" :size="56" :src="getAvatarView(currentUser.avatar)" icon="user"/>
<p class="left-user-name">{{ currentUser.realname }}</p>
<p>{{ currentUser.orgCodeTxt }}</p>
</div>
<div class="right-answer-form-wrapper">
<p>{{ $t('businessSupport.questionAnswer.answerQuestion') }}</p>
<a-textarea v-model="answerDesc" :autoSize="{minRows: 4}" :maxLength="2000"></a-textarea>
<p class="answer-desc-num">{{ answerDesc.length }}/2000{{ $t('businessSupport.questionAnswer.word') }}</p>
<a-button class="submit-btn" type="primary" @click="submit" v-has="'quiz:detail:answerSubmit'">{{ $t('submit') }}</a-button>
</div>
</div>
<!-- 图片预览容器 -->
<div id="images">
<div class="image" v-viewer="{movable: false}">
<img v-show="image" :src="imageUrl">
</div>
</div>
</internal-detail-page>
</template>
<script>
import { USER_INFO, ACCESS_TOKEN } from '@/store/mutation-types'
import Vue from 'vue'
import { getFileAccessHttpUrl, downloadFile } from '@/api/manage'
import { getQuizById, answerQuiz, setOrCancelTop, deleteAnswer } from '@/api/businessSupport'
import { getFileInfo } from '@/api/api'
import { previewPdf } from '@/utils/previewPdf'
import InternalDetailPage from '@/components/InternalDetailPage'
import { kkFilePreview } from '@/utils/kkFilePreview'
// 支持预览的文件后缀
const CAN_PREVIEW_FILE_SUFFIX = ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
const FILE_TYPE_IMGS = ['jpg', 'jpeg', 'png', 'raw']
const FILE_TYPE_PDF = 'pdf'
const Base64 = require('js-base64').Base64
export default {
name: 'AnswerPage',
components: { InternalDetailPage },
data () {
return {
loading: false,
pageTitle: '',
model: {},
answerArr: [],
fileList: [],
currentUser: {
avatar: '',
realname: '',
orgCodeTxt: ''
},
answerDesc: '',
canAnswer: false,
userInfo: {},
image: false,
imageUrl: ''
}
},
mounted () {
this.initData(this.$route.query.id)
const userInfo = Vue.ls.get(USER_INFO)
this.userInfo = userInfo
this.currentUser = Object.assign({}, userInfo)
this.canAnswer = Number(this.$route.query.canAnswer)
if (this.canAnswer === 1) {
this.pageTitle = this.$t('businessSupport.questionAnswer.answerQuestionTitle')
} else {
this.pageTitle = this.$t('businessSupport.questionAnswer.questionDetail')
}
},
methods: {
// 初始化获取数据信息
initData (id) {
this.loading = true
getQuizById({ id: id }).then(res => {
if (res.success) {
this.model = Object.assign({}, res.result)
if (this.model.file) {
const fileList = this.model.file.split(',')
const fileInfoList = []
fileList.forEach(async id => {
const fileInfo = await this.getFileInfo(id)
if (fileInfo) {
fileInfoList.push(fileInfo)
}
})
this.fileList = fileInfoList
}
this.answerArr = this.model.answerList
}
}).finally(() => {
this.loading = false
})
},
// 获取头像
getAvatarView (avatar) {
return getFileAccessHttpUrl(avatar)
},
getFileInfo (fileId) {
return new Promise(resolve => {
let fileInfo
getFileInfo({ id: fileId }).then(res => {
if (res.success) {
fileInfo = res.result
}
}).finally(() => {
resolve(fileInfo)
})
})
},
handlePreview (file) {
if (!file || !file.url) {
return
}
// 截取文件后缀名
const fileSuffix = file.fileName ? file.fileName.split('.')[file.fileName.split('.').length - 1] : ''
const canPreview = CAN_PREVIEW_FILE_SUFFIX.some(tt => fileSuffix.toLowerCase() === tt)
// 判断是否为可预览格式的文件
if (!canPreview) {
this.$message.loading('该文件类型不支持预览,正在为您准备下载...').then(() => {
this.handleDownload(file)
})
return
}
const fileFullUrl = `${window._CONFIG.domianWebSocketURL}/sys/common/view/${file.id}?token=${Vue.ls.get(ACCESS_TOKEN)}&fullfilename=${file.fileName}`
// 图片预览,使用自己添加的组件
if (canPreview && FILE_TYPE_IMGS.includes(fileSuffix.toLowerCase())) {
this.imageUrl = getFileAccessHttpUrl(file.id)
// 获取viewer实例
const viewer = this.$el.querySelector('.image').$viewer
// 调用show方法进行显示预览图
viewer.show()
// this.$refs.imagePreviewModal.open(file)
return
}
// pdf预览
if (canPreview && FILE_TYPE_PDF.includes(fileSuffix)) {
const url = previewPdf(file.id)
console.log(url)
window.open(url)
return
}
// 其余可预览文件仍使用KKFile进行预览
kkFilePreview(fileFullUrl)
},
handleDownload (file) {
// 下载文件
downloadFile(`/laws/standard/common/downloadWithWaterMark/${file.id}`, file.fileName)
},
submit () {
if (!this.answerDesc) {
this.$message.warning(this.$t('businessSupport.questionAnswer.pleaseEnterAnswerDesc'))
return
}
const param = {}
param.problemId = this.model.id
param.answerDescription = this.answerDesc
answerQuiz(param).then(res => {
if (res.success) {
this.$message.success(res.message)
this.initData(this.model.id)
this.answerDesc = ''
} else {
this.$message.warning(res.message)
}
})
},
// 设置或取消置顶
setOrCancelTop (answerId) {
setOrCancelTop({ id: answerId }).then(res => {
if (res.success) {
this.$message.success(res.message)
this.initData(this.model.id)
} else {
this.$message.warning(res.message)
}
})
},
// 删除回答
deleteAnswer (answerId) {
deleteAnswer({ id: answerId }).then(res => {
if (res.success) {
this.$message.success(res.message)
this.initData(this.model.id)
} else {
this.$message.warning(res.message)
}
})
}
}
}
</script>
<style scoped lang="less">
// 二级标题
.detail-page-second-title {
font-size: 16px;
text-align: center;
font-weight: 550;
margin-bottom: 20px;
}
.detail-page-part-form-item-large {
width: 100%;
display: flex;
margin: 0 16px 16px 0;
label {
width: 10em;
font-size: 16px;
font-family: PingFang SC-Regular, PingFang SC, sans-serif;
font-weight: 400;
color: #86909C;
}
span {
white-space: pre-wrap;
word-break: break-all;
font-size: 16px;
font-family: PingFang SC-Regular, PingFang SC, sans-serif;
color: #1D2129;
}
}
.detail-page-part-form-item-large-file {
width: 100%;
display: flex;
margin: 0 16px 16px 0;
label {
width: 10em;
font-size: 16px;
font-family: PingFang SC-Regular, PingFang SC, sans-serif;
font-weight: 400;
color: #86909C;
}
a {
white-space: pre-wrap;
word-break: break-all;
font-size: 16px;
font-family: PingFang SC-Regular, PingFang SC, sans-serif;
}
}
// 问题描述部分
.question-desc-wrapper {
border-radius: 8px;
border: 1px solid #E5E6EB;
margin-bottom: 20px;
padding: 20px;
.question-desc {
font-size: 16px;
}
}
// 历史回答数据
.answer-wrapper {
border-radius: 8px;
border: 1px solid #E5E6EB;
margin-bottom: 20px;
display: flex;
.left-user-info {
width: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgb(247, 248, 250);
padding: 20px 0 5px 0;
}
.left-user-name {
margin-top: 18px;
margin-bottom: 8px;
}
.right-answer-wrapper {
width: 100%;
padding: 20px 10px 20px 10px;
box-sizing: border-box;
}
.right-answer-form-wrapper {
padding: 20px 10px;
width: 100%;
box-sizing: border-box;
.submit-btn {
margin-top: 20px;
}
}
.answer-desc-num {
text-align: right;
margin-top: 5px;
margin-bottom: 0;
}
.top-p {
color: @primary-color;
}
.no-top-desc {
margin-top: 20px;
}
}
// 右下角的时间和按钮区域
.right-bottom-p {
height: 20px;
text-align: right;
padding-right: 8px;
margin-bottom: 0;
.time-span {
color: #86909C;
}
.right-bottom-p-span {
margin-left: 8px;
}
.right-bottom-p-a {
margin-left: 8px;
}
}
.file-box {
flex: 1;
width: 0;
}
.file-list {
&-file {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
&-file:last-child {
margin-bottom: 0;
}
&-file-info {
display: flex;
align-items: center;
color: @primary-color;
cursor: pointer;
flex: 1;
width: 0;
}
&-file-info > .anticon {
margin-right: 8px;
}
&-file-name {
white-space: nowrap;
overflow: hidden;
flex: 1;
width: 0;
text-overflow: ellipsis;
}
&-file-operate {
.ant-btn > .anticon + span, .ant-btn > .iconfont + span {
margin-left: 10px;
}
.ant-btn:first-child {
margin-left: 15px;
}
}
}
</style>