界面优化,markdown渲染优化

This commit is contained in:
sswiki
2024-12-09 22:14:51 +08:00
parent 4ad463845e
commit d6bcfc5492
68 changed files with 1885 additions and 1203 deletions

View File

@@ -1,80 +0,0 @@
<template>
<div class="wiki-file">
<el-upload v-if="storePage.pageAuth.canUploadFile === 1"
:on-success="uploadFileSuccess"
:on-error="uploadFileError"
:before-upload="beforeUpload"
:action="uploadFileUrl"
:data="uploadFormData"
:with-credentials="true" class="action-btn upload-page-file" name="files"
show-file-list multiple :limit="999">
<el-button type="primary" :underline="false" :icon="ElIconUpload" style="margin: 10px;width: 100%"> 上传附件</el-button>
</el-upload>
<el-table v-show="storePage.fileList.length > 0" :data="storePage.fileList" border
style="width: 100%; margin-bottom: 5px">
<el-table-column label="文件名" show-overflow-tooltip>
<template v-slot="scope">
<el-link target="_blank" :href="scope.row.fileUrl" type="primary">{{scope.row.fileName }}
</el-link>
</template>
</el-table-column>
<el-table-column prop="createUserName" label="创建人" width="110px"
show-overflow-tooltip></el-table-column>
<el-table-column label="文件大小" width="120px">
<template v-slot="scope">{{computeFileSize(scope.row.fileSize) }}</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="160px"></el-table-column>
<el-table-column prop="downloadNum" label="下载次数" width="90px">
<template v-slot="scope">{{scope.row.downloadNum || 0}}</template>
</el-table-column>
<el-table-column label="操作" width="90px" v-if="storePage.pageAuth.canDeleteFile == 1">
<template v-slot="scope">
<el-button @click="deletePageFile(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import {Upload as ElIconUpload} from '@element-plus/icons-vue'
import {useStorePageData} from "@/store/pageData";
let storePage = useStorePageData();
import {ref} from 'vue';
import {ElMessageBox, ElMessage} from 'element-plus';
import pageApi from "@/assets/api/page";
import unitUtil from "@/assets/lib/UnitUtil";
let uploadFormData = ref({pageId: 0});
let uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/zyplayer-doc-wiki/page/file/upload');
const beforeUpload = () => {
uploadFormData.value.pageId = storePage.pageInfo.id;
}
const uploadFileError = (err) => {
ElMessage.error('上传失败,' + err);
}
const uploadFileSuccess = (response) => {
if (response.errCode === 200) {
storePage.fileList.push(response.data);
ElMessage.success('上传成功!');
} else {
ElMessage('上传失败:' + (response.errMsg || '未知错误'));
}
}
const deletePageFile = (row) => {
ElMessageBox.confirm('确定要删除此文件吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
let param = {id: row.id};
pageApi.deletePageFile(param).then(() => {
storePage.fileList = storePage.fileList.filter(item => item.id !== row.id);
});
})
}
const computeFileSize = (fileSize) => {
return unitUtil.computeFileSize(fileSize)
}
</script>

View File

@@ -45,7 +45,7 @@ import {
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 pageApi from '@/assets/api/page';
import {useStorePageData} from "@/store/pageData";
import {useStoreUserData} from "@/store/userData";
@@ -67,55 +67,55 @@ watch(() => storePage.pageInfo, (newVal) => {
if (storePage.pageInfo.editorType !== 0){
loadCommentList();
}
})
});
onMounted(() => {
loadCommentList();
});
let actionTabCommentRef = ref();
const scrollActionTabComment = () => {
setTimeout(() => {
let actionTabComment = actionTabCommentRef.value
actionTabComment.scrollTop = actionTabComment.scrollHeight
}, 0)
let actionTabComment = actionTabCommentRef.value;
actionTabComment.scrollTop = actionTabComment.scrollHeight;
}, 0);
}
const loadCommentList = () => {
if (!storePage.pageInfo || !storePage.pageInfo.id) {
return;
}
cancelCommentUser()
cancelCommentUser();
pageApi.pageCommentList({pageId: storePage.pageInfo.id}).then((json) => {
let commentListRes = json.data || []
let commentListRes = json.data || [];
for (let i = 0; i < commentListRes.length; i++) {
commentListRes[i].color = getUserHeadBgColor(commentListRes[i].createUserId)
let subCommentList = commentListRes[i].commentList || []
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(subItem.createUserId)
let subItem = subCommentList[j];
subItem.color = getUserHeadBgColor(subItem.createUserId);
}
commentListRes[i].commentList = subCommentList
commentListRes[i].visible = false
commentListRes[i].commentList = subCommentList;
commentListRes[i].visible = false;
}
commentList.value = commentListRes
scrollActionTabComment()
})
commentList.value = commentListRes;
scrollActionTabComment();
});
}
let canDeleteComment = (row) => {
return storeUser.userInfo.id === row.createUserId
|| storeUser.userInfo.id === storePage.pageInfo.createUserId
|| storeUser.userInfo.id === storePage.pageInfo.createUserId;
}
const deleteComment = (id) => {
pageApi.deletePageComment({id: id}).then(() => {
// ElMessage.success("删除成功!");
loadCommentList()
})
loadCommentList();
});
}
const cancelCommentUser = () => {
recommentInfo.value = {}
recommentInfo.value = {};
}
const submitPageComment = () => {
if (commentTextInput.value.length <= 0) {
ElMessage.error('请输入评论内容')
return
ElMessage.error('请输入评论内容');
return;
}
let param = {
pageId: storePage.pageInfo.id,
@@ -123,26 +123,26 @@ const submitPageComment = () => {
parentId: recommentInfo.value.id,
}
pageApi.updatePageComment(param).then((json) => {
let data = json.data
data.color = getUserHeadBgColor(data.createUserId)
commentTextInput.value = ''
loadCommentList()
})
let data = json.data;
data.color = getUserHeadBgColor(data.createUserId);
commentTextInput.value = '';
loadCommentList();
});
}
const getUserHeadBgColor = (userId) => {
let color = page.userHeadColor[userId]
let color = page.userHeadColor[userId];
if (!color) {
color = page.colorArr[Math.ceil(Math.random() * page.colorArr.length) - 1]
page.userHeadColor[userId] = color
color = page.colorArr[Math.ceil(Math.random() * page.colorArr.length) - 1];
page.userHeadColor[userId] = color;
}
return color
return color;
}
</script>
<style lang="scss">
.comment-box {
padding: 8px;
height: calc(100vh - 315px);
height: calc(100vh - 275px);
overflow: auto;
.comment-card {

View File

@@ -0,0 +1,196 @@
<template>
<div class="files-box">
<div class="upload-file-box">
<el-upload class="upload-page-file" :action="uploadFileUrl" ref="uploadFileRef"
:with-credentials="true" :before-upload="beforeUploadFile"
:on-success="uploadFileSuccess" :on-error="uploadFileError"
name="files" show-file-list multiple :data="uploadFormData" :limit="999"
style="display: inline;vertical-align: sub;">
<a-button :icon="h(UploadOutlined)" type="primary" style="width: 260px;">上传附件</a-button>
</el-upload>
</div>
<div v-if="storePage.fileList.length <= 0" class="action-box-empty">
<el-empty description="暂无附件" />
</div>
<div v-else class="files-list">
<template v-for="file in storePage.fileList">
<a-card class="box-card files-card" :body-style="{ padding: '10px' }">
<div class="head">{{file.createUserName}}</div>
<div class="files-user-name">
<span>{{file.createUserName}}</span>
<el-tooltip :content="file.createTime" placement="top-start" :show-after="1000">
<span class="time">{{ file.createTime }}</span>
</el-tooltip>
<el-icon v-if="storePage.pageAuth.canDeleteFile === 1" @click="deleteFile(file)" class="icon-delete"><ElIconDelete /></el-icon>
</div>
<div class="files-name">
<a target="_blank" :href="file.fileUrl">{{file.fileName || '--'}}</a>
</div>
<div class="files-size">
<IconParkMemoryOne/><span class="value">{{computeFileSize(file.fileSize)}}</span>
<IconParkDownload style="margin-left: 15px;"/> <span class="value">{{file.downloadNum || 0}}</span>
</div>
</a-card>
</template>
</div>
</div>
</template>
<script setup>
import {Delete as ElIconDelete,} from '@element-plus/icons-vue'
import {UploadOutlined} from '@ant-design/icons-vue';
import {toRefs, ref, reactive, onMounted, watch, h, defineEmits, computed} from 'vue';
import {useRouter, useRoute} from "vue-router";
import { message, Modal } from 'ant-design-vue';
import pageApi from "@/assets/api/page";
import {useStorePageData} from "@/store/pageData";
import unitUtil from "@/assets/lib/UnitUtil";
import {
MemoryOne as IconParkMemoryOne,
Download as IconParkDownload,
} from '@icon-park/vue-next'
let storePage = useStorePageData();
let uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/zyplayer-doc-wiki/page/file/upload');
const deleteFile = (file) => {
Modal.confirm({
maskClosable: true,
title: '提示',
content: '确定要删除此文件吗?',
okText: '删除',
cancelText: '确定',
onOk: () => {
pageApi.deletePageFile({id: file.id}).then(() => {
storePage.fileList = storePage.fileList.filter(item => item !== file);
});
}
});
}
let uploadFileRef = ref();
let uploadFormData = computed(() => {
return {pageId: storePage.pageInfo.id};
});
const beforeUploadFile = (file) => {
}
const uploadFileError = (err) => {
message.error('上传失败,' + err);
}
let uploadOverStatus = ['success', 'fail'];
const uploadFileSuccess = (response, file, fileList) => {
if (response.errCode !== 200) {
message('上传失败:' + (response.errMsg || '未知错误'));
} else {
storePage.fileList.push(response.data);
}
// 是否全部上传完成
if (fileList.every(file => uploadOverStatus.includes(file.status))) {
message.success('上传成功!');
uploadFileRef.value.clearFiles();
}
}
const computeFileSize = (fileSize) => {
return unitUtil.computeFileSize(fileSize);
}
</script>
<style lang="scss">
.files-box {
.upload-page-file {
.el-upload-list {
display: none;
}
}
}
</style>
<style scoped lang="scss">
.files-box {
padding: 50px 8px 8px;
height: calc(100vh - 130px);
overflow: auto;
box-sizing: border-box;
position: relative;
.upload-file-box {
position: absolute;
top: 0;
left: 0;
text-align: center;
background: #fff;
width: 100%;
z-index: 1;
padding-bottom: 5px;
}
ul {
padding-left: 0;
}
.files-card {
margin-bottom: 10px;
}
.files-user-name {
margin-bottom: 6px;
font-size: 13px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
position: relative;
}
.files-card .files-user-name .icon-delete {
color: #888;
font-size: 13px;
cursor: pointer;
float: right;
display: none;
}
.files-card .files-user-name .icon-delete {
color: #888;
font-size: 13px;
cursor: pointer;
display: none;
position: absolute;
right: 0;
top: 2px;
background: #fff;
}
.files-card:hover .files-user-name .icon-delete {
display: inline-block;
}
.head {
float: left;
margin-right: 10px;
line-height: 40px;
}
.files-user-name .time {
color: #888;
margin-left: 8px;
}
.files-name {
padding: 0;
color: #666;
margin: 0;
line-height: 20px;
font-size: 14px;
}
.files-size {
margin-left: 50px;
margin-top: 5px;
font-size: 14px;
.value {
margin-left: 4px;
vertical-align: middle;
}
}
}
</style>

View File

@@ -15,14 +15,25 @@
import {
Search as ElIconSearch,
} from '@element-plus/icons-vue'
import {markRaw} from 'vue'
import {toRefs, ref, reactive, onMounted, onBeforeUnmount, defineProps, watch, defineEmits, computed, defineExpose} from 'vue';
import {markRaw} from 'vue';
import {
toRefs,
ref,
reactive,
onMounted,
onBeforeUnmount,
defineProps,
watch,
defineEmits,
computed,
defineExpose
} from 'vue';
import {useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage, ElLoading, ElNotification} from 'element-plus'
import {ElMessageBox, ElMessage, ElLoading, ElNotification} from 'element-plus';
import pageApi from "@/assets/api/page";
import {useStorePageData} from "@/store/pageData";
import userApi from "@/assets/api/user";
import QRCode from 'qrcode'
import QRCode from 'qrcode';
import {useStoreSpaceData} from "@/store/spaceData";
let storePage = useStorePageData();
@@ -59,18 +70,13 @@ const initMobileQrScan = () => {
});
let hostPath = window.location.href.split('#')[0];
setTimeout(() => {
qrCodeUrl.value = hostPath + routeUrl.href
qrCodeUrl.value = hostPath + routeUrl.href;
QRCode.toCanvas(qrCodeDivRef.value, qrCodeUrl.value, {
scale: 5, height: 250, wight: 250,
}, (error) => {
if (error) console.error(error);
}
)
);
}, 0);
}
</script>
<style lang="scss">
.page-auth-dialog {
}
</style>

View File

@@ -1,8 +1,13 @@
<template>
<div class="navigation-box">
<div class="navigation-content-box">
<div></div>
<div class="nav-heading" :style="{ width: navigationWidth }">
<div :style="navigationStyle" class="navigation-box">
<div v-if="navigationMin">
<a-button @click="navigationToMax" class="navigation-max-btn" size="large" type="text" shape="circle">
<IconParkViewList :size="18"/>
</a-button>
</div>
<div v-else :style="navigationStyle" @mouseover="navigationMouseover" @mouseleave="navigationMouseleave"
:class="navigationShow?'':'box-shadow'" class="navigation-content-box">
<div class="nav-heading">
<div v-for="item in heading" :class="'heading-item heading-' + item.level" @click="headingItemClick(item)">
{{ item.text }}
</div>
@@ -12,14 +17,10 @@
</template>
<script setup>
import {toRefs, ref, reactive, onMounted, watch, defineEmits, defineProps, defineExpose,} from 'vue'
import {useStoreDisplay} from '@/store/wikiDisplay.js'
import {useStorePageData} from "@/store/pageData";
import {ViewList as IconParkViewList} from '@icon-park/vue-next'
import {toRefs, ref, reactive, onMounted, watch, defineEmits, defineProps, defineExpose,} from 'vue';
import {useResizeEvent} from "@/composable/windowsScroll";
let storePage = useStorePageData();
const storeDisplay = useStoreDisplay();
let navigationWidth = ref('100px');
const props = defineProps({
heading: {type: Array, default: []},
});
@@ -29,8 +30,44 @@ onMounted(() => {
useResizeEvent(() => {
computeNavigationWidth();
});
let isLeave = false;
let leaveTimer = undefined;
const navigationMouseover = () => {
isLeave = false;
if (leaveTimer) {
clearTimeout(leaveTimer);
leaveTimer = undefined;
}
}
const navigationMouseleave = () => {
if (isLeave) return;
isLeave = true;
leaveTimer = setTimeout(() => {
isLeave = false;
navigationMin.value = !navigationShow.value;
}, 500);
}
const navigationToMax = () => {
navigationMin.value = false;
}
let navigationMin = ref(false);
let navigationShow = ref(true);
let navigationStyle = ref({width: '200px'});
const computeNavigationWidth = () => {
let pageViewContent = document.getElementById('pageContentBox');
let pageContentScrollBox = document.getElementById('pageContentScrollBox');
// pageContentScrollBox的宽度减去pageViewContent的宽度除以2
if (pageViewContent && pageContentScrollBox) {
let outerWidth = pageContentScrollBox.clientWidth - pageViewContent.clientWidth;
if (outerWidth > 160) {
navigationShow.value = true;
navigationStyle.value.width = (outerWidth / 2 - 50) + 'px';
} else {
navigationStyle.value.width = '200px';
navigationShow.value = false;
}
navigationMin.value = !navigationShow.value;
}
}
const headingItemClick = (item) => {
// 滚动到指定节点
@@ -40,29 +77,43 @@ const headingItemClick = (item) => {
inline: 'nearest',
});
// 距离顶部高度
//console.log(item.node.offsetTop - item.node.scrollHeight)
//console.log(item.node.offsetTop - item.node.scrollHeight);
}
</script>
<style lang="scss">
.navigation-box {
width: 100px;
position: absolute;
top: 150px;
top: 60px;
right: 10px;
z-index: 4;
.navigation-max-btn {
position: fixed;
margin-left: 160px;
opacity: 0.7;
box-shadow: var(--el-box-shadow-light);
&:hover {
opacity: 1;
background: #fff;
}
}
.navigation-content-box {
position: fixed;
background: #fff;
border-radius: 8px;
padding: 16px;
margin-left: -40px;
box-shadow: var(--el-box-shadow-lighter);
margin-left: -30px;
&.box-shadow {
box-shadow: var(--el-box-shadow-lighter);
}
}
.nav-heading {
max-height: calc(100vh - 250px);
max-height: calc(100vh - 200px);
overflow-y: auto;
.heading-item {

View File

@@ -2,7 +2,7 @@
<!--人员权限弹窗-->
<el-dialog title="页面权限" v-model="dataItemEditVisible" width="800px" class="page-auth-dialog">
<el-row>
<el-select v-model="pageAuthNewUser" filterable remote reserve-keyword autoComplete="new-password" placeholder="请输入名字、邮箱、账号搜索用户" :remote-method="getSearchUserList" :loading="pageAuthUserLoading" style="width: 690px; margin-right: 10px">
<el-select v-model="pageAuthNewUser" filterable remote reserve-keyword autoComplete="new-password" placeholder="请输入名字、邮箱、账号搜索用户" :remote-method="getSearchUserList" :loading="pageAuthUserLoading" style="width: 690px; margin-right: 10px;">
<el-option v-for="item in searchUserList" :key="item.id" :label="item.userName" :value="item.id"></el-option>
</el-select>
<el-button @click="addPageAuthUser">添加</el-button>
@@ -35,10 +35,10 @@
import {
Search as ElIconSearch,
} from '@element-plus/icons-vue'
import {markRaw} from 'vue'
import {markRaw} from 'vue';
import {toRefs, ref, reactive, onMounted, onBeforeUnmount, defineProps, watch, defineEmits, computed, defineExpose} from 'vue';
import {useRouter, useRoute} from "vue-router";
import {ElMessageBox, ElMessage, ElLoading, ElNotification} from 'element-plus'
import {ElMessageBox, ElMessage, ElLoading, ElNotification} from 'element-plus';
import pageApi from "@/assets/api/page";
import {useStorePageData} from "@/store/pageData";
import userApi from "@/assets/api/user";
@@ -106,7 +106,7 @@ const addPageAuthUser = () => {
pageFileUpload: 0,
pageFileDelete: 0,
pageAuthManage: 0,
})
});
pageAuthNewUser.value = '';
}
const getSearchUserList = (query) => {

View File

@@ -1,22 +1,22 @@
<template>
<div class="action-tab-box">
<div v-if="props.pageHistoryList.length <= 0" class="action-box-empty">
<div v-if="history.length <= 0" class="action-box-empty">
暂无修改历史记录
</div>
<el-timeline v-else>
<el-timeline-item v-for="history in props.pageHistoryList">
<el-tag :type="props.pageHistoryChoice.id === history.id ? history.loading === 3 ? 'danger' : 'success' : 'info'"
<el-timeline-item v-for="history in history">
<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 class="history-loading-status" v-if="history.loading===1">
<el-icon-loading/>
</el-icon>
<el-icon class="history-loading-status" v-show="history.loading===2">
<el-icon class="history-loading-status" v-else-if="history.loading===2">
<el-icon-circle-check/>
</el-icon>
<el-icon class="history-loading-status" v-show="history.loading===3">
<el-icon class="history-loading-status" v-else-if="history.loading===3">
<el-icon-circle-close/>
</el-icon>
</el-timeline-item>
@@ -31,50 +31,40 @@ import {
Loading as ElIconLoading,
} from '@element-plus/icons-vue'
import pageApi from '@/assets/api/page'
import pageApi from '@/assets/api/page';
import {mavonEditor} from "mavon-editor";
import {ref, defineProps, defineEmits} from 'vue';
import {useStorePageData} from "@/store/pageData";
let storePage = useStorePageData();
let props= defineProps({
pageHistoryList:Array,
pageHistoryChoice:Object,
pageHistoryDetail:String,
})
let emit = defineEmits(['historyClickHandle','previewPageImage','createNavigationHeading'])
let props = defineProps({
history: Array,
});
let emit = defineEmits(['choice']);
let pageHistoryChoice = ref({});
const historyClick = (history) => {
if (props.pageHistoryChoice.id === history.id && !!props.pageHistoryDetail.value) {
if (pageHistoryChoice.value.id === history.id && !!pageHistoryChoice.value.content) {
return;
}
pageHistoryChoice.value.loading = 0;
pageHistoryChoice.value = history;
// 缓存一下,但如果历史页面多了而且很大就占内存,也可以每次去拉取,先这样吧
if (history.content) {
history.loading = 2;
emit('historyClickHandle',history)
setTimeout(() => {
emit('previewPageImage',history)
emit('createNavigationHeading',history)
}, 500)
emit('choice', history);
} else {
history.loading = 1
history.loading = 1;
pageApi.pageHistoryDetail({id: history.id}).then((json) => {
history.loading = 2;
history.content = json.data || '--';
if (storePage.pageInfo.editorType === 2) {
history.content = mavonEditor.getMarkdownIt().render(history.content);
}
emit('historyClickHandle',history)
setTimeout(() => {
emit('previewPageImage',history)
emit('createNavigationHeading',history)
}, 500);
emit('choice', history);
}).catch(() => {
history.loading = 3;
});
}
}
</script>
<style lang="scss">
</style>

View File

@@ -1,25 +1,29 @@
<template>
<div style="margin-top: 40px; font-size: 14px">
<span style="vertical-align: top" class="is-link">
<span v-show="storePage.pageInfo.selfZan == 0" @click="zanPage(1)"><img src="../../../assets/img/zan.png" style="vertical-align: middle"/> </span>
<span v-show="storePage.pageInfo.selfZan == 1" @click="zanPage(0)"><img src="../../../assets/img/zan.png" style="vertical-align: middle; transform: rotateX(180deg)"/> </span>
</span>
<span style="margin-left: 10px; vertical-align: top">
<span v-if="storePage.pageInfo.selfZan == 0 && storePage.pageInfo.zanNum <= 0">成为第一个赞同者</span>
<span v-else-if="storePage.pageInfo.selfZan == 0 && storePage.pageInfo.zanNum > 0">
<span class="is-link" @click="showZanPageUser">{{ storePage.pageInfo.zanNum }}</span>赞了它
</span>
<span v-else-if="storePage.pageInfo.selfZan == 1 && storePage.pageInfo.zanNum <= 1">我赞了它</span>
<span v-else-if="storePage.pageInfo.selfZan == 1 && storePage.pageInfo.zanNum > 1">
<span class="is-link" @click="showZanPageUser">我和{{ storePage.pageInfo.zanNum - 1 }}个其他人</span>赞了它
</span>
</span>
<span style="margin-left: 10px">
<el-icon style="font-size: 16px; color: #666;vertical-align: middle;"><el-icon-view/></el-icon> {{ storePage.pageInfo.viewNum }}次阅读
</span>
<div class="zan-box">
<div class="zan-btn-box">
<VueStarPlus v-model="starActive" animate="animated tada">
<template #icon>
<a-button @click="zanPage()" :type="starActive?'primary':'default'" shape="circle" class="zan-btn">
<IconParkThumbsUp :size="30"/>
</a-button>
</template>
</VueStarPlus>
</div>
<template v-if="storePage.pageInfo.zanNum <= 0">
<el-divider>为它点赞</el-divider>
</template>
<template v-else-if="storePage.pageInfo.zanNum > 0">
<template v-if="storePage.pageInfo.selfZan === 1">
<template v-if="storePage.pageInfo.zanNum === 1">
<el-divider>我赞了它</el-divider>
</template>
<el-divider v-else>我和<a @click="showZanPageUser">{{storePage.pageInfo.zanNum - 1}} </a> 赞了它</el-divider>
</template>
<el-divider v-else><a @click="showZanPageUser">{{storePage.pageInfo.zanNum}} </a> 赞了它</el-divider>
</template>
</div>
<el-dialog title="赞了它的人" v-model="zanUserDialogVisible" width="600px">
<el-table :data="zanUserList" border :show-header="false" style="width: 100%; margin-bottom: 5px">
<el-table :data="zanUserList" border :show-header="false" style="width: 100%; margin-bottom: 5px;">
<el-table-column prop="createUserName" label="用户"></el-table-column>
<el-table-column prop="createTime" label="时间"></el-table-column>
</el-table>
@@ -27,29 +31,69 @@
</template>
<script setup>
import pageApi from '../../../assets/api/page'
import {ref} from 'vue';
import {ThumbsUp as IconParkThumbsUp} from '@icon-park/vue-next'
import pageApi from '../../../assets/api/page';
import {ref, watch, onMounted} from 'vue';
import {useStorePageData} from "@/store/pageData";
import {
View as ElIconView,
} from '@element-plus/icons-vue'
let zanUserList = ref([]);
let zanUserDialogVisible = ref(false);
import VueStarPlus from 'vue-star-plus'
import 'vue-star-plus/style.css'
let storePage = useStorePageData();
const zanPage = (yn) => {
let param = {yn: yn, pageId: storePage.pageInfo.id}
let zanUserList = ref([]);
let zanUserDialogVisible = ref(false);
let starActive = ref(false);
watch(() => storePage.pageInfo, () => {
starActive.value = (storePage.pageInfo.selfZan === 1);
});
onMounted(() => {
starActive.value = (storePage.pageInfo.selfZan === 1);
});
const zanPage = () => {
let yn = storePage.pageInfo.selfZan === 1 ? 0 : 1;
let param = {yn: yn, pageId: storePage.pageInfo.id};
pageApi.updatePageZan(param).then(() => {
storePage.pageInfo.selfZan = yn
storePage.pageInfo.zanNum = storePage.pageInfo.zanNum + (yn == 1 ? 1 : -1)
})
starActive.value = (yn === 1);
storePage.pageInfo.selfZan = yn;
storePage.pageInfo.zanNum = storePage.pageInfo.zanNum + (yn === 1 ? 1 : -1);
});
}
const showZanPageUser = () => {
zanUserDialogVisible.value = true
zanUserList.value = []
let param = {pageId: storePage.pageInfo.id}
zanUserDialogVisible.value = true;
zanUserList.value = [];
let param = {pageId: storePage.pageInfo.id};
pageApi.pageZanList(param).then((json) => {
zanUserList.value = json.data
})
zanUserList.value = json.data || [];
});
}
</script>
<style lang="scss">
.zan-box {
margin-top: 50px;
text-align: center;
.zan-btn-box {
position: relative;
.vue-star-plus {
width: 100%;
position: unset;
.vue-star-plus__ground {
margin: 0 auto;
}
}
.zan-btn {
height: 60px;
width: 60px;
}
}
.el-divider {
width: 300px;
margin: 20px auto;
}
}
</style>