将wiki升级为vue3版本

This commit is contained in:
暮光:城中城
2023-01-07 17:38:15 +08:00
parent 717d3f39f0
commit dec28158d2
27 changed files with 338 additions and 242 deletions

View File

@@ -12,30 +12,32 @@ const noValidate = {
'/zyplayer-doc-db/executor/execute': true, '/zyplayer-doc-db/executor/execute': true,
} }
service.interceptors.request.use( service.interceptors.request.use((config) => {
(config) => {
config.needValidateResult = true config.needValidateResult = true
// 增加不需要验证结果的标记 // 增加不需要验证结果的标记
if (noValidate[config.url]) { if (noValidate[config.url]) {
config.needValidateResult = false config.needValidateResult = false
} }
return config return config
}, }, (error) => {
(error) => {
console.log(error) console.log(error)
return Promise.reject(error) return Promise.reject(error)
} }
) )
let lastToastLoginTime = new Date().getTime();
service.interceptors.response.use( service.interceptors.response.use(
(response) => { (response) => {
if (!!response.message) { if (!!response.message) {
ElMessage.error('请求错误:' + response.message) ElMessage.error('请求错误:' + response.message)
} else { } else {
if (!response.config.needValidateResult || response.data.errCode == 200) { if (!response.config.needValidateResult || response.data.errCode === 200) {
return response.data return response.data
} else if (response.data.errCode == 400) { } else if (response.data.errCode === 400) {
ElMessage.error('请先登录') // 两秒钟只提示一次
if (new Date().getTime() - lastToastLoginTime > 2000) {
ElMessage.warning('请先登录');
lastToastLoginTime = new Date().getTime();
}
let href = encodeURIComponent(window.location.href) let href = encodeURIComponent(window.location.href)
window.location = import.meta.env.VITE_APP_BASE_API + '#/user/login?redirect=' + href window.location = import.meta.env.VITE_APP_BASE_API + '#/user/login?redirect=' + href
} else if (response.data.errCode !== 200) { } else if (response.data.errCode !== 200) {
@@ -43,8 +45,7 @@ service.interceptors.response.use(
} }
} }
return Promise.reject('请求错误') return Promise.reject('请求错误')
}, }, (error) => {
(error) => {
console.log('err' + error) console.log('err' + error)
ElMessage.info('请求错误:' + error.message) ElMessage.info('请求错误:' + error.message)
return Promise.reject(error) return Promise.reject(error)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -146,12 +146,13 @@ import {
import {onBeforeUnmount, toRefs, ref, reactive, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue'; import {onBeforeUnmount, toRefs, ref, reactive, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import userApi from '../../common/api/user' import userApi from '../../assets/api/user'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
import CreateSpace from '../space/CreateSpace' import CreateSpace from '../space/CreateSpace'
import RightResize from './RightResize.vue' import RightResize from './RightResize.vue'
import AboutDialog from '../../views/common/AboutDialog' import AboutDialog from '../../views/common/AboutDialog'
import {useStoreDisplay} from '@/store/wikiDisplay.js' import {useStoreDisplay} from '@/store/wikiDisplay.js'
import {useStoreUserData} from "@/store/userData";
let route = useRoute(); let route = useRoute();
let router = useRouter(); let router = useRouter();
@@ -406,9 +407,11 @@ const userSignOut = () => {
location.reload() location.reload()
}) })
} }
let storeUser = useStoreUserData();
const getSelfUserInfo = () => { const getSelfUserInfo = () => {
userApi.getSelfUserInfo().then((json) => { userApi.getSelfUserInfo().then((json) => {
userSelfInfo.value = json.data userSelfInfo.value = json.data;
storeUser.userInfo = json.data;
}) })
} }
const getSpaceInfo = (spaceId) => { const getSpaceInfo = (spaceId) => {

View File

@@ -49,7 +49,7 @@ import {
Document as ElIconDocument, Document as ElIconDocument,
Search as ElIconSearch, Search as ElIconSearch,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
import RightResize from './RightResize.vue' import RightResize from './RightResize.vue'
let leftCollapse = ref(true); let leftCollapse = ref(true);

View File

@@ -17,7 +17,7 @@
import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue'; import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
import PageTree from './PageTree' import PageTree from './PageTree'
import 'vant/es/icon/style/index'; import 'vant/es/icon/style/index';
import 'vant/es/popup/style/index'; import 'vant/es/popup/style/index';

View File

@@ -42,7 +42,7 @@
import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue'; import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
let editSpaceId = ref(''); let editSpaceId = ref('');
let newSpaceFormRules = ref({ let newSpaceFormRules = ref({

View File

@@ -3,8 +3,8 @@ import {defineStore} from 'pinia'
export const useStorePageData = defineStore('pageData', { export const useStorePageData = defineStore('pageData', {
state: () => { state: () => {
return { return {
pageLoadStatus: 0, pageInfo: {},
} }
}, },
}) });

View File

@@ -69,7 +69,7 @@
import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue'; import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import systemApi from '../../common/api/system' import systemApi from '../../assets/api/system'
onMounted(() => { onMounted(() => {
checkSystemUpgrade() checkSystemUpgrade()

View File

@@ -32,14 +32,19 @@ import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmi
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import {View as ElIconView} from '@element-plus/icons-vue' import {View as ElIconView} from '@element-plus/icons-vue'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
let totalCount = ref(0); let totalCount = ref(0);
let searchParam = ref({spaceId: '', newsType: 1, pageNum: 1, pageSize: 20,}); let searchParam = ref({spaceId: '', newsType: 1, pageNum: 1, pageSize: 20,});
let spacePageNews = ref([]); let spacePageNews = ref([]);
// 列表类型 // 列表类型
let newsTypesArr = ref([{key: 1, val: '最近更新'}, {key: 2, val: '最新创建'}, {key: 3, val: '查看最多'}, {key: 4, val: '点赞最多'}, {key: 5, val: '查看+点赞最多'},]); let newsTypesArr = ref([
{key: 1, val: '最近更新'},
{key: 2, val: '最新创建'},
{key: 3, val: '查看最多'},
{key: 4, val: '点赞最多'},
{key: 5, val: '查看+点赞最多'},
]);
let newsTypesMap = ref({}); let newsTypesMap = ref({});
onBeforeRouteUpdate((to) => { onBeforeRouteUpdate((to) => {

View File

@@ -60,7 +60,7 @@ import {
Check as ElIconCheck, Check as ElIconCheck,
Back as ElIconBack, Back as ElIconBack,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
import {mavonEditor} from 'mavon-editor' import {mavonEditor} from 'mavon-editor'
import 'mavon-editor/dist/markdown/github-markdown.min.css' import 'mavon-editor/dist/markdown/github-markdown.min.css'
import 'mavon-editor/dist/css/index.css' import 'mavon-editor/dist/css/index.css'

View File

@@ -47,7 +47,7 @@ import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmi
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import {View as ElIconView, Search as ElIconSearch} from '@element-plus/icons-vue' import {View as ElIconView, Search as ElIconSearch} from '@element-plus/icons-vue'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
let route = useRoute(); let route = useRoute();
let router = useRouter(); let router = useRouter();

View File

@@ -3,37 +3,29 @@
<el-row type="border-card" style="height: 100%"> <el-row type="border-card" style="height: 100%">
<el-col :span="actionTabVisible ? 18 : 24" style="padding: 20px;border-right: 1px solid #f1f1f1;height: 100%;overflow: auto;"> <el-col :span="actionTabVisible ? 18 : 24" style="padding: 20px;border-right: 1px solid #f1f1f1;height: 100%;overflow: auto;">
<el-row> <el-row>
<el-col <el-col :span="navigationList.length > 0 ? 18 : 24">
:xs="24"
:sm="navigationList.length > 0 ? 20 : 24"
:md="navigationList.length > 0 ? 20 : 24"
:lg="navigationList.length > 0 ? 18 : 24"
:xl="navigationList.length > 0 ? 18 : 24">
<div style="max-width: 1000px; margin: 0 auto; padding-left: 10px"> <div style="max-width: 1000px; margin: 0 auto; padding-left: 10px">
<div class="wiki-title" ref="wikiTitleRef">{{ wikiPage.name }}</div> <div class="wiki-title" ref="wikiTitleRef">{{ wikiPage.name }}</div>
<div class="wiki-author"> <div class="wiki-author">
<div> <el-row>
<span v-if="wikiPage.updateUserName">{{ wikiPage.updateUserName }}  {{wikiPage.updateTime}} 修改</span> <el-col :span="12">
<span v-else class="create-user-time">{{ wikiPage.createUserName }}  {{wikiPage.createTime}} 创建</span> <span v-if="wikiPage.updateUserName">{{ wikiPage.updateUserName }}  {{wikiPage.updateTime}} 修改</span>
<div style="float: right"> <span v-else class="create-user-time">{{ wikiPage.createUserName }}  {{wikiPage.createTime}} 创建</span>
</el-col>
<el-col :span="12" style="text-align: right;">
<el-link type="primary" :icon="ElIconChatLineRound" :underline="false" @click="showCommentWiki" style="margin-right: 15px">评论</el-link> <el-link type="primary" :icon="ElIconChatLineRound" :underline="false" @click="showCommentWiki" style="margin-right: 15px">评论</el-link>
<el-upload <el-upload v-if="wikiPageAuth.canUploadFile === 1"
v-if="wikiPageAuth.canUploadFile == 1" :on-success="uploadFileSuccess"
class="upload-page-file" :on-error="uploadFileError"
:action="uploadFileUrl" :action="uploadFileUrl"
:with-credentials="true" :data="uploadFormData"
:on-success="uploadFileSuccess" :with-credentials="true" class="upload-page-file" name="files"
:on-error="uploadFileError" show-file-list multiple :limit="999"
name="files" style="display: inline; margin-right: 15px;vertical-align: middle;">
show-file-list
multiple
:data="uploadFormData"
:limit="999"
style="display: inline; margin-right: 15px;vertical-align: middle;">
<el-link type="primary" :underline="false" :icon="ElIconUpload">上传附件</el-link> <el-link type="primary" :underline="false" :icon="ElIconUpload">上传附件</el-link>
</el-upload> </el-upload>
<el-link v-if="wikiPageAuth.canEdit == 1" type="primary" :underline="false" :icon="ElIconEdit" @click="editWiki" style="margin-right: 15px;">编辑</el-link> <el-link v-if="wikiPageAuth.canEdit === 1" type="primary" :underline="false" :icon="ElIconEdit" @click="editWiki" style="margin-right: 15px;">编辑</el-link>
<el-dropdown style="margin-right: 15px;vertical-align: middle;" @command="handleMoreCommand"> <el-dropdown style="margin-right: 15px;vertical-align: middle;" trigger="click" @command="handleMoreCommand">
<el-link type="primary" :underline="false"> <el-link type="primary" :underline="false">
更多 更多
<el-icon class="el-icon--right"><el-icon-arrow-down/></el-icon> <el-icon class="el-icon--right"><el-icon-arrow-down/></el-icon>
@@ -49,25 +41,27 @@
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
</div> </el-col>
</div> </el-row>
</div> </div>
<div class="wiki-files"> <div class="wiki-files">
<el-table v-show="pageFileList.length > 0" :data="pageFileList" border style="width: 100%; margin-bottom: 5px"> <el-table v-show="pageFileList.length > 0" :data="pageFileList" border style="width: 100%; margin-bottom: 5px">
<el-table-column label="文件名"> <el-table-column label="文件名" show-overflow-tooltip>
<template v-slot="scope"> <template v-slot="scope">
<a target="_blank" :href="scope.row.fileUrl">{{scope.row.fileName }}</a> <el-link target="_blank" :href="scope.row.fileUrl">{{scope.row.fileName }}</el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="createUserName" label="创建人"></el-table-column> <el-table-column prop="createUserName" label="创建人"></el-table-column>
<el-table-column label="文件大小"> <el-table-column label="文件大小" width="120px">
<template v-slot="scope">{{computeFileSize(scope.row.fileSize) }}</template> <template v-slot="scope">{{computeFileSize(scope.row.fileSize) }}</template>
</el-table-column> </el-table-column>
<el-table-column prop="createTime" label="创建时间" width="180px"></el-table-column> <el-table-column prop="createTime" label="创建时间" width="160px"></el-table-column>
<el-table-column prop="downloadNum" label="下载次数" width="80px"></el-table-column> <el-table-column prop="downloadNum" label="下载次数" width="100px">
<template v-slot="scope">{{scope.row.downloadNum || 0}}</template>
</el-table-column>
<el-table-column label="操作" width="100px" v-if="wikiPageAuth.canDeleteFile == 1"> <el-table-column label="操作" width="100px" v-if="wikiPageAuth.canDeleteFile == 1">
<template v-slot="scope"> <template v-slot="scope">
<el-button size="small" v-on:click="deletePageFile(scope.row)">删除</el-button> <el-button v-on:click="deletePageFile(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -97,7 +91,7 @@
</div> </div>
</div> </div>
</el-col> </el-col>
<el-col :xs="0" :sm="4" :md="4" :lg="6" :xl="6" v-if="navigationList.length > 0"> <el-col :span="navigationList.length > 0 ? 6 : 0" v-if="navigationList.length > 0">
<Navigation ref="navigationRef" :heading="navigationList"></Navigation> <Navigation ref="navigationRef" :heading="navigationList"></Navigation>
</el-col> </el-col>
</el-row> </el-row>
@@ -108,43 +102,9 @@
</el-icon> </el-icon>
<el-tabs v-model="actionTabActiveName" @tab-click="actionTabClick"> <el-tabs v-model="actionTabActiveName" @tab-click="actionTabClick">
<el-tab-pane label="评论" name="comment"> <el-tab-pane label="评论" name="comment">
<div class="action-tab-box" ref="actionTabCommentRef" style="padding-bottom: 130px;box-sizing: border-box;height: calc(100vh - 80px);"> <Comment/>
<div v-if="commentList.length <= 0" class="action-box-empty">
暂无评论
</div>
<el-timeline v-else>
<el-timeline-item :timestamp="comment.createTime" placement="top" v-for="comment in commentList">
<el-card class="box-card comment-card" :body-style="{ padding: '10px' }">
<div :style="'background-color: ' + comment.color" class="head">
{{ comment.createUserName.substr(0, 1) }}
</div>
<div class="comment-user-name">
{{ comment.createUserName }}
<el-popover placement="top" width="160" v-model="comment.visible" v-if="canDeleteComment(comment)">
<p>确定要除删此评论吗</p>
<div style="text-align: right; margin: 0">
<el-link size="small" @click="comment.visible = false">取消</el-link>
<el-button type="primary" size="small" @click="deleteComment(comment.id)">确定</el-button>
</div>
<template v-slot:reference>
<el-icon>
<el-icon-delete/>
</el-icon>
</template>
</el-popover>
</div>
<pre class="comment-content">{{ comment.content }}</pre>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
<div class="comment-input-box">
<textarea rows="5" placeholder="发表评论" v-model="commentTextInput"></textarea>
<el-button style="float: right; margin: 2px 5px" type="primary" size="small" v-on:click="submitPageComment">发送</el-button>
</div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="修改历史" name="history"> <el-tab-pane label="修改历史" name="history">
<!-- <div class="action-tab-box" v-infinite-scroll="getPageHistoryByScroll">-->
<div class="action-tab-box"> <div class="action-tab-box">
<div v-if="pageHistoryList.length <= 0" class="action-box-empty"> <div v-if="pageHistoryList.length <= 0" class="action-box-empty">
暂无修改历史记录 暂无修改历史记录
@@ -248,14 +208,16 @@ import {toRefs, ref, reactive, onMounted, watch, defineProps, defineEmits, defin
import {onBeforeRouteUpdate, useRoute, useRouter} from "vue-router"; import {onBeforeRouteUpdate, useRoute, useRouter} from "vue-router";
import { ElMessageBox, ElMessage, ElNotification } from 'element-plus'; import { ElMessageBox, ElMessage, ElNotification } from 'element-plus';
import QRCode from 'qrcode' import QRCode from 'qrcode'
import unitUtil from '../../common/lib/UnitUtil.js' import unitUtil from '../../assets/lib/UnitUtil.js'
import htmlUtil from '../../common/lib/HtmlUtil.js' import htmlUtil from '../../assets/lib/HtmlUtil.js'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
import userApi from '../../common/api/user' import userApi from '../../assets/api/user'
import Navigation from './components/Navigation.vue' import Navigation from './components/Navigation.vue'
import Comment from './show/Comment.vue'
import {mavonEditor} from 'mavon-editor' import {mavonEditor} from 'mavon-editor'
import 'mavon-editor/dist/markdown/github-markdown.min.css' import 'mavon-editor/dist/markdown/github-markdown.min.css'
import 'mavon-editor/dist/css/index.css' import 'mavon-editor/dist/css/index.css'
import {useStorePageData} from "@/store/pageData";
let page = { let page = {
colorArr: ['#67C23A', '#409EFF', '#E6A23C', '#F56C6C', '#909399', '#303133'], colorArr: ['#67C23A', '#409EFF', '#E6A23C', '#F56C6C', '#909399', '#303133'],
@@ -276,10 +238,6 @@ let parentPath = ref({});
// 手机扫码 // 手机扫码
let qrCodeUrl = ref(''); let qrCodeUrl = ref('');
let mobileScanDialogVisible = ref(false); let mobileScanDialogVisible = ref(false);
// 评论相关
let commentTextInput = ref('');
let commentList = ref([]);
let recommentInfo = ref({});
let uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/zyplayer-doc-wiki/page/file/upload'); let uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/zyplayer-doc-wiki/page/file/upload');
// 页面权限 // 页面权限
let pageAuthDialogVisible = ref(false); let pageAuthDialogVisible = ref(false);
@@ -308,6 +266,8 @@ let downloadFormParam = ref({url: 'zyplayer-doc-wiki/page/download', param: {},}
let route = useRoute(); let route = useRoute();
let router = useRouter(); let router = useRouter();
let storePage = useStorePageData();
const props = defineProps({ const props = defineProps({
spaceInfo: Object, spaceInfo: Object,
}); });
@@ -489,7 +449,6 @@ const closeActionTab = () => {
const showCommentWiki = () => { const showCommentWiki = () => {
actionTabVisible.value = true actionTabVisible.value = true
actionTabActiveName.value = 'comment' actionTabActiveName.value = 'comment'
scrollActionTabComment()
computeNavigationWidth() computeNavigationWidth()
} }
const showPageHistory = () => { const showPageHistory = () => {
@@ -611,9 +570,9 @@ const loadPageDetail = (pageId) => {
setTimeout(() => { setTimeout(() => {
previewPageImage() previewPageImage()
createNavigationHeading() createNavigationHeading()
}, 500) }, 500);
storePage.pageInfo = wikiPageRes;
}) })
loadCommentList(pageId)
getPageHistory(pageId, 1) getPageHistory(pageId, 1)
} }
let wikiTitleRef = ref(); let wikiTitleRef = ref();
@@ -659,33 +618,6 @@ const initImageViewerMask = () => {
} }
}) })
} }
const loadCommentList = (pageId) => {
cancelCommentUser()
pageApi.pageCommentList({pageId: pageId}).then((json) => {
let commentList = json.data || []
for (let i = 0; i < commentList.length; i++) {
commentList[i].color = getUserHeadBgColor(
commentList[i].createUserId
)
let subCommentList = commentList[i].commentList || []
for (let j = 0; j < subCommentList.length; j++) {
let subItem = subCommentList[j]
subItem.color = getUserHeadBgColor.value(subItem.createUserId)
}
commentList[i].commentList = subCommentList
commentList[i].visible = false
}
commentList.value = commentList
scrollActionTabComment()
})
}
let actionTabCommentRef = ref();
const scrollActionTabComment = () => {
setTimeout(() => {
let actionTabComment = actionTabCommentRef.value
actionTabComment.scrollTop = actionTabComment.scrollHeight
}, 0)
}
const zanPage = (yn) => { const zanPage = (yn) => {
let param = {yn: yn, pageId: wikiPage.value.id} let param = {yn: yn, pageId: wikiPage.value.id}
pageApi.updatePageZan(param).then(() => { pageApi.updatePageZan(param).then(() => {
@@ -701,45 +633,6 @@ const showZanPageUser = () => {
zanUserList.value = json.data zanUserList.value = json.data
}) })
} }
const recommentUser = (id, index) => {
recommentInfo.value = {
id: id,
index: index,
placeholder: '回复' + (index + 1) + '楼',
}
}
const canDeleteComment = (row) => {
return (
selfUserId.value == row.createUserId ||
wikiPage.value.createUserId == selfUserId.value
)
}
const deleteComment = (id) => {
pageApi.deletePageComment({id: id}).then(() => {
// ElMessage.success("删除成功!");
loadCommentList(parentPath.value.pageId)
})
}
const cancelCommentUser = () => {
recommentInfo.value = {}
}
const submitPageComment = () => {
if (commentTextInput.value.length <= 0) {
ElMessage.error('请输入评论内容')
return
}
let param = {
pageId: wikiPage.value.id,
content: commentTextInput.value,
parentId: recommentInfo.value.id,
}
pageApi.updatePageComment(param).then((json) => {
let data = json.data
data.color = getUserHeadBgColor(data.createUserId)
commentTextInput.value = ''
loadCommentList(parentPath.value.pageId)
})
}
const uploadFileError = (err) => { const uploadFileError = (err) => {
ElMessage.error('上传失败,' + err) ElMessage.error('上传失败,' + err)
} }
@@ -787,7 +680,7 @@ const initQueryParam = (to) => {
</script> </script>
<style> <style>
@import '../../common/lib/wangEditor.css'; @import '../../assets/lib/wangEditor.css';
.page-show-vue { .page-show-vue {
height: 100%; height: 100%;
@@ -907,56 +800,6 @@ const initQueryParam = (to) => {
padding-inline-start: 0; padding-inline-start: 0;
} }
.page-show-vue .comment-user-name {
margin-bottom: 10px;
}
.page-show-vue .comment-content {
padding: 0;
color: #666;
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
line-height: 20px;
}
.page-show-vue .comment-input-box {
position: absolute;
bottom: 0;
width: 100%;
background: #fff;
border-top: 1px solid #f1f1f1;
}
.page-show-vue .comment-input-box textarea {
resize: none;
width: 100%;
box-sizing: border-box;
border: 0;
outline: none !important;
padding: 10px;
}
.page-show-vue .comment-card .comment-user-name .el-icon-delete {
color: #888;
font-size: 13px;
cursor: pointer;
float: right;
display: none;
}
.page-show-vue .comment-card .comment-user-name .el-icon-delete {
color: #888;
font-size: 13px;
cursor: pointer;
float: right;
display: none;
}
.page-show-vue .comment-card:hover .comment-user-name .el-icon-delete {
display: inline-block;
}
.mobile-qr { .mobile-qr {
width: 250px; width: 250px;
height: 250px; height: 250px;

View File

@@ -36,12 +36,9 @@ onMounted(() => {
} }
setTimeout(() => computeNavigationWidth(), 100) setTimeout(() => computeNavigationWidth(), 100)
}) })
watch( watch(() => storeDisplay.viewMenuWidth, (newVal) => {
() => storeDisplay.viewMenuWidth, computeNavigationWidth()
(newVal) => { })
computeNavigationWidth()
}
)
let navigationRef = ref(); let navigationRef = ref();
const computeNavigationWidth = () => { const computeNavigationWidth = () => {
navigationWidth.value = window.getComputedStyle( navigationWidth.value = window.getComputedStyle(

View File

@@ -38,7 +38,7 @@
import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue'; import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import pageApi from '../../../../common/api/page' import pageApi from '../../../../assets/api/page'
import {mavonEditor} from 'mavon-editor' import {mavonEditor} from 'mavon-editor'
import {ImagePreview} from 'vant' import {ImagePreview} from 'vant'
import 'mavon-editor/dist/markdown/github-markdown.min.css' import 'mavon-editor/dist/markdown/github-markdown.min.css'
@@ -130,7 +130,7 @@ const previewPageImage = () => {
</script> </script>
<style> <style>
@import '../../../../common/lib/wangEditor.css'; @import '../../../../assets/lib/wangEditor.css';
.page-share-view-vue { .page-share-view-vue {
} }

View File

@@ -37,7 +37,7 @@ import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmi
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import {View as ElIconView} from '@element-plus/icons-vue' import {View as ElIconView} from '@element-plus/icons-vue'
import pageApi from '../../../../common/api/page' import pageApi from '../../../../assets/api/page'
let totalCount = ref(0); let totalCount = ref(0);
let searchParam = ref({spaceId: '', newsType: 1, pageNum: 1, pageSize: 20,}); let searchParam = ref({spaceId: '', newsType: 1, pageNum: 1, pageSize: 20,});

View File

@@ -48,10 +48,10 @@
import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue'; import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import pageApi from '../../../../common/api/page' import pageApi from '../../../../assets/api/page'
import {mavonEditor} from 'mavon-editor' import {mavonEditor} from 'mavon-editor'
import unitUtil from '../../../../common/lib/UnitUtil.js' import unitUtil from '../../../../assets/lib/UnitUtil.js'
import htmlUtil from '../../../../common/lib/HtmlUtil.js' import htmlUtil from '../../../../assets/lib/HtmlUtil.js'
import Navigation from '../../components/Navigation.vue' import Navigation from '../../components/Navigation.vue'
import 'mavon-editor/dist/markdown/github-markdown.min.css' import 'mavon-editor/dist/markdown/github-markdown.min.css'
import 'mavon-editor/dist/css/index.css' import 'mavon-editor/dist/css/index.css'
@@ -167,7 +167,7 @@ const initImageViewerMask = () => {
</script> </script>
<style> <style>
@import '../../../../common/lib/wangEditor.css'; @import '../../../../assets/lib/wangEditor.css';
.page-share-view-vue .wiki-title { .page-share-view-vue .wiki-title {
font-size: 20px; font-size: 20px;

View File

@@ -0,0 +1,202 @@
<template>
<div class="comment-box" ref="actionTabCommentRef">
<div v-if="commentList.length <= 0" class="action-box-empty">
暂无评论
</div>
<div v-else class="comment-list">
<el-timeline>
<el-timeline-item :timestamp="comment.createTime" placement="top" v-for="comment in commentList">
<el-card class="box-card comment-card" :body-style="{ padding: '10px' }">
<div :style="'background-color: ' + comment.color" class="head">
{{ comment.createUserName.substr(0, 1) }}
</div>
<div class="comment-user-name">
{{ comment.createUserName }}
<el-popconfirm v-if="canDeleteComment(comment)"
placement="top" width="160" trigger="click"
confirm-button-text="删除"
cancel-button-text="取消"
@confirm="deleteComment(comment.id)"
title="确定要删除此评论吗?">
<template #reference>
<el-icon class="icon-delete"><ElIconDelete /></el-icon>
</template>
</el-popconfirm>
</div>
<pre class="comment-content">{{ comment.content }}</pre>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
</div>
<div class="comment-input-box">
<textarea rows="5" placeholder="发表评论" v-model="commentTextInput"></textarea>
<el-button style="float: right; margin: 2px 5px" type="primary" size="small" v-on:click="submitPageComment">发送</el-button>
</div>
</template>
<script setup>
import {
Delete as ElIconDelete,
Loading as ElIconLoading,
} from '@element-plus/icons-vue'
import {toRefs, ref, reactive, onMounted, watch, defineProps, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRoute, useRouter} from "vue-router";
import { ElMessageBox, ElMessage, ElNotification } from 'element-plus';
import pageApi from '@/assets/api/page'
import {useStorePageData} from "@/store/pageData";
import {useStoreUserData} from "@/store/userData";
let page = {
colorArr: ['#67C23A', '#409EFF', '#E6A23C', '#F56C6C', '#909399', '#303133'],
userHeadColor: {},
}
// 评论相关
let commentTextInput = ref('');
let commentList = ref([]);
let recommentInfo = ref({});
let route = useRoute();
let router = useRouter();
let storePage = useStorePageData();
let storeUser = useStoreUserData();
watch(() => storePage.pageInfo, (newVal) => {
loadCommentList();
})
onMounted(() => {
loadCommentList();
});
let actionTabCommentRef = ref();
const scrollActionTabComment = () => {
setTimeout(() => {
let actionTabComment = actionTabCommentRef.value
actionTabComment.scrollTop = actionTabComment.scrollHeight
}, 0)
}
const loadCommentList = () => {
if (!storePage.pageInfo || !storePage.pageInfo.id) {
return;
}
cancelCommentUser()
pageApi.pageCommentList({pageId: storePage.pageInfo.id}).then((json) => {
let commentListRes = json.data || []
for (let i = 0; i < commentListRes.length; i++) {
commentListRes[i].color = getUserHeadBgColor(commentListRes[i].createUserId)
let subCommentList = commentListRes[i].commentList || []
for (let j = 0; j < subCommentList.length; j++) {
let subItem = subCommentList[j]
subItem.color = getUserHeadBgColor.value(subItem.createUserId)
}
commentListRes[i].commentList = subCommentList
commentListRes[i].visible = false
}
commentList.value = commentListRes
scrollActionTabComment()
})
}
const recommentUser = (id, index) => {
recommentInfo.value = {
id: id,
index: index,
placeholder: '回复' + (index + 1) + '楼',
}
}
let canDeleteComment = (row) => {
return (
storeUser.userInfo.id === row.createUserId || storeUser.userInfo.id === storePage.pageInfo.createUserId
)
}
const deleteComment = (id) => {
pageApi.deletePageComment({id: id}).then(() => {
// ElMessage.success("删除成功!");
loadCommentList()
})
}
const cancelCommentUser = () => {
recommentInfo.value = {}
}
const submitPageComment = () => {
if (commentTextInput.value.length <= 0) {
ElMessage.error('请输入评论内容')
return
}
let param = {
pageId: storePage.pageInfo.id,
content: commentTextInput.value,
parentId: recommentInfo.value.id,
}
pageApi.updatePageComment(param).then((json) => {
let data = json.data
data.color = getUserHeadBgColor(data.createUserId)
commentTextInput.value = ''
loadCommentList()
})
}
const getUserHeadBgColor = (userId) => {
let color = page.userHeadColor[userId]
if (!color) {
color = page.colorArr[Math.ceil(Math.random() * page.colorArr.length) - 1]
page.userHeadColor[userId] = color
}
return color
}
</script>
<style lang="scss">
.comment-box {
padding: 8px;
height: calc(100vh - 100px);
overflow: auto;
.comment-list {
padding-bottom: 130px;
}
.comment-card {
.comment-user-name {
margin-bottom: 10px;
.icon-delete {
color: #888;
font-size: 13px;
cursor: pointer;
float: right;
display: none;
}
}
.comment-content {
padding: 0;
color: #666;
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
line-height: 20px;
}
}
.comment-card:hover {
.icon-delete {
display: inline-block;
}
}
}
.comment-input-box {
position: absolute;
bottom: 0;
width: 100%;
background: #fff;
border-top: 1px solid #f1f1f1;
textarea {
resize: none;
width: 100%;
box-sizing: border-box;
border: 0;
outline: none !important;
padding: 10px;
}
}
</style>

View File

@@ -0,0 +1,49 @@
<template>
<div class="action-tab-box">
<div v-if="pageHistoryList.length <= 0" class="action-box-empty">
暂无修改历史记录
</div>
<el-timeline v-else>
<el-timeline-item v-for="history in pageHistoryList">
<el-tag :type="pageHistoryChoice.id === history.id ? history.loading === 3 ? 'danger' : 'success' : 'info'" class="history-item" @click="historyClick(history)">
<div>{{ history.createUserName }}</div>
<div>{{ history.createTime }}</div>
</el-tag>
<el-icon class="history-loading-status" v-show="history.loading===1"><el-icon-loading/></el-icon>
<el-icon class="history-loading-status" v-show="history.loading===2"><el-icon-circle-check/></el-icon>
<el-icon class="history-loading-status" v-show="history.loading===3"><el-icon-circle-close/></el-icon>
</el-timeline-item>
</el-timeline>
</div>
</template>
<script setup>
import {
Delete as ElIconDelete,
Loading as ElIconLoading,
} from '@element-plus/icons-vue'
import {toRefs, ref, reactive, onMounted, watch, defineProps, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRoute, useRouter} from "vue-router";
import { ElMessageBox, ElMessage, ElNotification } from 'element-plus';
import pageApi from '@/assets/api/page'
import {useStorePageData} from "@/store/pageData";
import {useStoreUserData} from "@/store/userData";
let route = useRoute();
let router = useRouter();
let storePage = useStorePageData();
let storeUser = useStoreUserData();
let pageHistoryDetail = ref('');
let pageHistoryChoice = ref({});
let pageHistoryList = ref([]);
let pageHistoryPageNum = ref(1);
watch(() => storePage.pageInfo, (newVal) => {
})
onMounted(() => {
});
</script>
<style lang="scss">
</style>

View File

@@ -96,8 +96,8 @@ import {
Refresh as ElIconRefresh, Refresh as ElIconRefresh,
Plus as ElIconPlus, Plus as ElIconPlus,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import pageApi from '../../common/api/page' import pageApi from '../../assets/api/page'
import userApi from '../../common/api/user' import userApi from '../../assets/api/user'
import CreateSpace from '../../components/space/CreateSpace' import CreateSpace from '../../components/space/CreateSpace'
let spaceListLoading = ref(false); let spaceListLoading = ref(false);
@@ -105,16 +105,12 @@ let spaceOptions = ref([]);
let spaceList = ref([]); let spaceList = ref([]);
let choiceSpace = ref(''); let choiceSpace = ref('');
let nowSpaceShow = ref({}); let nowSpaceShow = ref({});
let newSpaceDialogVisible = ref(false);
let manageSpaceDialogVisible = ref(false);
let newSpaceForm = ref({id: '', name: '', spaceExplain: '', treeLazyLoad: 0, openDoc: 0, uuid: '', type: 1,}); let newSpaceForm = ref({id: '', name: '', spaceExplain: '', treeLazyLoad: 0, openDoc: 0, uuid: '', type: 1,});
let newSpaceFormRules = ref({name: [{required: true, message: '请输入空间名', trigger: 'blur'}, {min: 2, max: 25, message: '长度在 2 到 25 个字符', trigger: 'blur',},],});
let userSelfInfo = ref({}); let userSelfInfo = ref({});
// 空间授权 // 空间授权
let editSpaceId = ref(''); let editSpaceId = ref('');
let spaceAuthDialogVisible = ref(false); let spaceAuthDialogVisible = ref(false);
let spaceAuthNewGroupId = ref(''); let spaceAuthNewGroupId = ref('');
let spaceAuthGroupLoading = ref(false);
let searchGroupList = ref([]); let searchGroupList = ref([]);
let searchGroupMap = ref({}); let searchGroupMap = ref({});
let spaceAuthGroupList = ref([]); let spaceAuthGroupList = ref([]);
@@ -125,7 +121,7 @@ let route = useRoute();
let router = useRouter(); let router = useRouter();
let emit = defineEmits('loadSpace'); let emit = defineEmits('loadSpace');
onMounted(()=>{ onMounted(() => {
loadSpaceList() loadSpaceList()
getSelfUserInfo() getSelfUserInfo()
getSpaceSettingList() getSpaceSettingList()

View File

@@ -22,7 +22,7 @@
import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue'; import {onBeforeUnmount, ref, onMounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router"; import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage} from 'element-plus' import {ElMessageBox, ElMessage} from 'element-plus'
import userApi from '../../common/api/user' import userApi from '../../assets/api/user'
let userInfo = ref({}); let userInfo = ref({});
onMounted(() => { onMounted(() => {