[update] 问答库联调

This commit is contained in:
lideqin
2023-09-28 17:00:31 +08:00
parent d2bfae1c78
commit 279b120d7b
7 changed files with 315 additions and 119 deletions
@@ -2,7 +2,8 @@
<div class="detail-page">
<div class="detail-page-title">{{ model.title }}</div>
<div class="detail-page-second-title">
{{ $t('businessSupport.questionAnswer.poster') + ':' + model.orgCodeTxt + ' ' + model.poster }}
<!-- todo: 发帖人部门没有返回 -->
{{ $t('businessSupport.questionAnswer.poster') + ':' + model.orgCode_dictText + ' ' + model.userId_dictText }}
</div>
<div class="detail-page-part">
<div class="detail-page-part-form">
@@ -14,59 +15,81 @@
<!-- 项目 -->
<div class="detail-page-part-form-item-large">
<label>{{ $t('project') }}</label>
<span>{{ model.project || global.emptyLine }}</span>
<span>{{ model.project_dictText || global.emptyLine }}</span>
</div>
<!-- 附件 -->
<!-- 附件 -->
<div class="detail-page-part-form-item-large-file">
<label>{{ $t('businessSupport.questionAnswer.attach') }}</label>
<span>{{ model.attach || global.emptyLine }}</span>
<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.questionDesc }}</p>
<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>
<!-- 历史回答数据 -->
<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>{{ item.realname }}</p>
<p>{{ item.orgCodeTxt }}</p>
<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)">{{ $t('businessSupport.questionAnswer.cancelTop') }}</a>
<!-- 删除 : 发帖人、评论人、有置顶权限的用户可以删除 ?? -->
<a v-if="userInfo.id === model.userId || userInfo.id === item.userId" 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)">{{ $t('businessSupport.questionAnswer.setTop') }}</a>
<!-- 删除 : 发帖人、评论人、有置顶权限的用户可以删除,置顶的评论不允许删除,取消置顶后允许删除 ?? -->
<a v-if="userInfo.id === model.userId || userInfo.id === item.userId" class="right-bottom-p-a" @click="deleteAnswer(item.id)">{{ $t('delete') }}</a>
</template>
</p>
</div>
</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.answerDesc }}</p>
<p class="right-bottom-p">
<span>{{ item.answerTime }}</span>
<!-- 置顶评论的操作按钮 -->
<template v-if="item.isTop">
<!-- 取消置顶 -->
<a class="right-bottom-p-a">{{ $t('businessSupport.questionAnswer.cancelTop') }}</a>
<!-- 删除 : 发帖人、评论人、有置顶权限的用户可以删除 ?? -->
<a class="right-bottom-p-a">{{ $t('delete') }}</a>
</template>
<!-- 非置顶评论 -->
<template v-else>
<!-- 设置为置顶 -->
<a class="right-bottom-p-a">{{ $t('businessSupport.questionAnswer.setTop') }}</a>
<!-- 删除 : 发帖人、评论人、有置顶权限的用户可以删除,置顶的评论不允许删除,取消置顶后允许删除 ?? -->
<a class="right-bottom-p-a">{{ $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>{{ currentUser.realname }}</p>
<p class="left-user-name">{{ currentUser.realname }}</p>
<p>{{ currentUser.orgCodeTxt }}</p>
</div>
<div class="right-answer-form-wrapper">
@@ -76,71 +99,169 @@
<a-button class="submit-btn" type="primary" @click="submit">{{ $t('submit') }}</a-button>
</div>
</div>
<!-- 图片预览容器 -->
<div id="images">
<div class="image" v-viewer="{movable: false}">
<img v-show="image" :src="imageUrl">
</div>
</div>
</div>
</template>
<script>
import { USER_INFO } from '@/store/mutation-types'
import { USER_INFO, ACCESS_TOKEN } from '@/store/mutation-types'
import Vue from 'vue'
import { getFileAccessHttpUrl } from '@/api/manage'
import { getQuizById, answerQuiz, setOrCancelTop, deleteAnswer } from '@/api/businessSupport'
import { getFileInfo } from '@/api/api'
import { previewPdf } from '@/utils/previewPdf'
const FILE_TYPE_IMGS = ['jpg', 'jpeg', 'png', 'raw']
const FILE_TYPE_PDF = 'pdf'
const Base64 = require('js-base64').Base64
export default {
name: 'AnswerPage',
data () {
return {
model: {
title: '问题问题',
orgCodeTxt: '车型技术部',
poster: '超级管理员',
standardNumber: 'GB 7528-2020',
standardName: '机动车运行安全',
project: '机动车运行安全',
attach: '机动车运行安全.jpg',
questionDesc: '问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述' +
'问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述问题描述' +
'问题描述问题描述问题描述问题描述',
quizTime: '2023-07-04 14:39',
answerNum: 2
},
answerArr: [
{
avatar: '',
realname: '李某某',
orgCodeTxt: '标准法规部',
isTop: true,
answerDesc: '回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述' +
'回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述' +
'回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述',
answerTime: '2023-07-04 16:38'
},
{
avatar: '',
realname: '李某某',
orgCodeTxt: '标准法规部',
isTop: false,
answerDesc: '回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述' +
'回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述' +
'回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述回答描述',
answerTime: '2023-07-04 16:38'
}
],
model: {},
answerArr: [],
fileList: [],
currentUser: {
avatar: '',
realname: '',
orgCodeTxt: ''
},
answerDesc: '',
canAnswer: false
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)
},
methods: {
// 初始化获取数据信息
initData (id) {
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
}
})
},
// 获取头像
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 = FILE_TYPE_IMGS.some(tt => fileSuffix.toLowerCase() === tt) || fileSuffix.toLowerCase() === FILE_TYPE_PDF
// 判断是否为可预览格式的文件
if (!canPreview) {
this.$message.loading('该文件类型不支持预览,正在为您准备下载...').then(() => {
this.handleDownload(file)
})
return
}
const fileFullUrl = `${window._CONFIG.domianWebSocketURL}/sys/common/download/${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进行预览
const url = `${window._CONFIG.onlinePreviewDomainURL}?url=${encodeURIComponent(Base64.encode(fileFullUrl))}`
window.open(url)
},
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)
}
})
}
}
}
@@ -221,6 +342,10 @@ export default {
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;
@@ -262,4 +387,52 @@ export default {
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>