查看页面展示开发
This commit is contained in:
3381
zyplayer-doc-ui/wiki-ui/package-lock.json
generated
3381
zyplayer-doc-ui/wiki-ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -34,17 +34,16 @@
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^5.0.8",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.1.3",
|
||||
"node-sass": "^9.0.0",
|
||||
"sass-loader": "^13.3.2",
|
||||
"vue-template-compiler": "^2.7.14",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vue/cli-plugin-babel": "^5.0.8",
|
||||
"@vue/compiler-sfc": "^3.3.4",
|
||||
"less": "^4.3.0",
|
||||
"less-loader": "^12.3.0",
|
||||
"sass": "^1.89.0",
|
||||
"unplugin-auto-import": "^0.5.11",
|
||||
"unplugin-vue-components": "^0.25.1",
|
||||
"vite": "^4.4.9",
|
||||
"vite-plugin-style-import": "^2.0.0"
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vue-template-compiler": "^2.7.14"
|
||||
}
|
||||
}
|
||||
|
||||
13
zyplayer-doc-ui/wiki-ui/src/assets/js/applyOnce.js
Normal file
13
zyplayer-doc-ui/wiki-ui/src/assets/js/applyOnce.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export default function applyOnce(fn, timeout) {
|
||||
let inCall = false;
|
||||
let lastParam = null;
|
||||
return function (param) {
|
||||
lastParam = param;
|
||||
if (inCall) return;
|
||||
inCall = true;
|
||||
setTimeout(() => {
|
||||
inCall = false;
|
||||
fn(lastParam);
|
||||
}, timeout);
|
||||
}
|
||||
};
|
||||
@@ -1,3 +1,23 @@
|
||||
|
||||
.i-icon {
|
||||
vertical-align: middle;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
font-style: normal;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
vertical-align: -0.125em;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
.i-icon + span {
|
||||
margin-inline-start: 8px;
|
||||
}
|
||||
|
||||
span + .i-icon {
|
||||
margin-inline-start: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<div style="height: 100%" class="page-edit-vue">
|
||||
<div style="height: 100%;" class="page-edit-vue">
|
||||
<el-row class="fake-header">
|
||||
<el-col style="flex: 0 0 45px;" class="collapse-box">
|
||||
<el-button @click="turnLeftCollapse" v-if="storeDisplay.showMenu" text :icon="ElIconFold" class="fold-btn"></el-button>
|
||||
<el-button @click="turnLeftCollapse" v-else text :icon="ElIconExpand" class="fold-btn"></el-button>
|
||||
<a-button @click="turnLeftCollapse" v-if="storeDisplay.showMenu" type="text" :icon="h(MenuFoldOutlined)"></a-button>
|
||||
<a-button @click="turnLeftCollapse" v-else type="text" :icon="h(MenuUnfoldOutlined)"></a-button>
|
||||
</el-col>
|
||||
<el-col style="flex: 1 1 auto;">
|
||||
<el-input v-model="pageTitleEdit" :maxlength="40" placeholder="请输入标题" class="page-title-input" ></el-input>
|
||||
</el-col>
|
||||
<el-col style="flex: 0 0 180px;text-align: right;">
|
||||
<el-button type="primary" @click="createWikiSave(1)" :icon="ElIconDocumentChecked">保存</el-button>
|
||||
<el-button @click="createWikiCancel" :icon="ElIconBack" style="margin-right: 5px;">取消</el-button>
|
||||
<el-col style="flex: 0 0 190px;text-align: right;">
|
||||
<a-button @click="createWikiSave(1)" :icon="h(SaveOutlined)" :loading="saveContentLoading" type="primary">保存</a-button>
|
||||
<a-button @click="createWikiCancel" :icon="h(IconParkBack)" style="margin-left: 10px;">取消</a-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div style="box-sizing: border-box;background: #f5f5f5;overflow: hidden">
|
||||
@@ -27,7 +27,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onBeforeUnmount, ref, onMounted, onUnmounted, watch, defineProps, nextTick, defineEmits, defineExpose, computed} from 'vue';
|
||||
import {Back as IconParkBack} from '@icon-park/vue-next'
|
||||
import {MenuFoldOutlined, MenuUnfoldOutlined, SaveOutlined} from '@ant-design/icons-vue';
|
||||
import {onBeforeUnmount, ref, onMounted, onUnmounted, watch, defineProps, h, nextTick, defineEmits, defineExpose, computed} from 'vue';
|
||||
import {onBeforeRouteUpdate, useRouter, useRoute} from "vue-router";
|
||||
import {ElMessageBox, ElMessage} from 'element-plus';
|
||||
import {
|
||||
@@ -133,7 +135,7 @@ const createWikiSave = (saveAfter) => {
|
||||
preview = wangEditorRef.value.getPreview();
|
||||
} else if (wikiPage.value.editorType === 2) {
|
||||
content = markdownContent.value;
|
||||
const showContentSelector = mavonEditorRef.value.querySelectorAll('.v-show-content');
|
||||
const showContentSelector = mavonEditorRef.value.$el.querySelectorAll('.v-show-content');
|
||||
if (showContentSelector && showContentSelector.length > 0) {
|
||||
preview = showContentSelector[0].textContent;
|
||||
}
|
||||
@@ -221,6 +223,9 @@ const addMarkdownImage = (pos, file) => {
|
||||
color: #333;
|
||||
height: 50px !important;
|
||||
line-height: 50px !important;
|
||||
padding: 0 8px 0 8px;
|
||||
font-size: 14px;
|
||||
background: #fff;
|
||||
|
||||
.fold-btn {
|
||||
font-size: 18px;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<PageZan></PageZan>
|
||||
</div>
|
||||
<Navigation :heading="navigationList"></Navigation>
|
||||
<Navigation v-if="navigationList.length > 0" :heading="navigationList"></Navigation>
|
||||
</a-col>
|
||||
<a-col v-if="storeDisplay.commentShow" flex="280px">
|
||||
<a-tabs v-model:activeKey="actionTabActiveName" class="action-tabs-box">
|
||||
|
||||
@@ -27,24 +27,20 @@
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
<div class="space-folder-box" v-if="!props.readOnly">
|
||||
<el-row justify="space-between">
|
||||
<el-col :span="16">
|
||||
<div class="page-group-tag">
|
||||
<el-tooltip :content="spaceTreeIsClose?'点击展开目录':'点击收起目录'" placement="top">
|
||||
<span class="label" @click="changeDropdownStatus">空间目录</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" style="text-align: right;">
|
||||
<AddMenu/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<a-flex align="center" justify="space-between">
|
||||
<div class="page-group-tag">
|
||||
<el-tooltip :content="spaceTreeIsClose?'点击展开目录':'点击收起目录'" placement="top">
|
||||
<span class="label" @click="changeDropdownStatus">空间目录</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<AddMenu/>
|
||||
</a-flex>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="!spaceTreeIsClose" class="wiki-page-tree-box">
|
||||
<el-tree ref="wikiPageTreeRef" :current-node-key="props.nowPageId" :data="storePage.pageList"
|
||||
:default-expanded-keys="wikiPageExpandedKeys" :expand-on-click-node="true"
|
||||
:filter-node-method="filterPageNode" :props="defaultProps" :draggable="!props.readOnly"
|
||||
:props="defaultProps" :draggable="!props.readOnly"
|
||||
@node-click="handleNodeClick" @node-drop="handlePageDrop" node-key="id" highlight-current
|
||||
style="background-color: #fafafa;">
|
||||
<template v-slot="{ node, data }">
|
||||
@@ -63,7 +59,7 @@
|
||||
<el-tooltip v-if="data.shareStatus > 0" :content="data.tags" placement="top-start" :show-after="500">
|
||||
<a-tag color="warning" style="margin-inline-end: 4px;padding-inline: 4px;"> {{data.shareStatus === 1 ? '公共模板' : '个人模板'}}</a-tag>
|
||||
</el-tooltip>
|
||||
<span style="vertical-align: middle;margin-left: 5px;">
|
||||
<span style="margin-left: 5px;">
|
||||
<el-tooltip :content="node.label" placement="top-start" :show-after="700">{{ node.label }}</el-tooltip>
|
||||
</span>
|
||||
<!--操作-->
|
||||
@@ -279,18 +275,20 @@ const doGetPageList = () => {
|
||||
let spaceId = storeSpace.chooseSpaceId;
|
||||
pageApi.pageList({spaceId: spaceId}).then((json) => {
|
||||
storePage.pageList = json.data || [];
|
||||
// 查看页面
|
||||
if (storePage.pageList.length <= 0) {
|
||||
router.push({path: `/view/${spaceId}`});
|
||||
} else {
|
||||
let routePageId = parseInt(route.params.pageId);
|
||||
let findPage = storePage.getPageById(routePageId);
|
||||
if (findPage) {
|
||||
router.replace({path: `/view/${spaceId}/${routePageId}`});
|
||||
if (route.path.startsWith('/view')) {
|
||||
// 查看页面
|
||||
if (storePage.pageList.length <= 0) {
|
||||
router.push({path: `/view/${spaceId}`});
|
||||
} else {
|
||||
let firstPage = storePage.getFirstViewPage();
|
||||
if (firstPage) {
|
||||
router.replace({path: `/view/${spaceId}/${firstPage.id}`});
|
||||
let routePageId = parseInt(route.params.pageId);
|
||||
let findPage = storePage.getPageById(routePageId);
|
||||
if (findPage) {
|
||||
router.replace({path: `/view/${spaceId}/${routePageId}`});
|
||||
} else {
|
||||
let firstPage = storePage.getFirstViewPage();
|
||||
if (firstPage) {
|
||||
router.replace({path: `/view/${spaceId}/${firstPage.id}`});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,18 +306,12 @@ const doSearchByKeywords = (queryString, callback) => {
|
||||
}
|
||||
const handleSearchKeywordsSelect = (item) => {
|
||||
searchKeywords.value = '';
|
||||
router.push({path: '/page/show', query: {pageId: item.pageId}});
|
||||
router.push({path: `/view/${item.spaceId}/${item.pageId}`});
|
||||
}
|
||||
let spaceTreeIsClose = ref(false);
|
||||
const changeDropdownStatus = () => {
|
||||
spaceTreeIsClose.value = !spaceTreeIsClose.value;
|
||||
}
|
||||
const filterPageNode = (value, data) => {
|
||||
if (!value || !data.name) return true;
|
||||
// issues:I2CG72 忽略大小写
|
||||
let name = data.name.toLowerCase();
|
||||
return name.indexOf(value.toLowerCase()) !== -1;
|
||||
}
|
||||
const searchByKeywords = () => {
|
||||
wikiPageTreeRef.value.filter(searchKeywords.value);
|
||||
}
|
||||
@@ -413,13 +405,8 @@ defineExpose({searchByKeywords});
|
||||
width: 100%;
|
||||
|
||||
.label {
|
||||
.el-icon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-left: 5px;
|
||||
vertical-align: middle;
|
||||
max-width: calc(100% - 40px);
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
@@ -454,6 +441,24 @@ defineExpose({searchByKeywords});
|
||||
|
||||
.search-autocomplete-popper {
|
||||
width: 600px !important;
|
||||
|
||||
.search-option-item {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.space-folder-box {
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
<a-button class="hover-button hover-bg" size="large" :icon="h(EllipsisOutlined)"></a-button>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item @click="editWikiAuth" v-if="storePage.pageAuth.canConfigAuth === 1"><el-icon><ElIconSCheck/></el-icon> 权限设置</a-menu-item>
|
||||
<a-menu-item @click="showOpenPage" v-if="storeSpace.spaceInfo.openDoc === 1"><el-icon><ElIconShare/></el-icon> 查看开放文档</a-menu-item>
|
||||
<a-menu-item @click="showMobileView" v-if="storeSpace.spaceInfo.openDoc === 1"><el-icon><ElIconMobilePhone/></el-icon> 手机端查看</a-menu-item>
|
||||
<a-menu-item @click="exportWord"><el-icon><ElIconDownload/></el-icon>导出为Word</a-menu-item>
|
||||
<a-menu-item @click="editWikiAuth" v-if="storePage.pageAuth.canConfigAuth === 1" :icon="h(SafetyOutlined)">权限设置</a-menu-item>
|
||||
<a-menu-item @click="showOpenPage" v-if="storeSpace.spaceInfo.openDoc === 1" :icon="h(ShareAltOutlined)">查看开放文档</a-menu-item>
|
||||
<a-menu-item @click="showMobileView" v-if="storeSpace.spaceInfo.openDoc === 1" :icon="h(MobileOutlined)">手机端查看</a-menu-item>
|
||||
<a-menu-item @click="exportWord" :icon="h(DownloadOutlined)">导出为Word</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item @click="deleteWikiPage" v-if="storePage.pageAuth.canDelete === 1" class="delete"><el-icon><ElIconDelete/></el-icon> 删除</a-menu-item>
|
||||
<a-menu-item @click="deleteWikiPage" v-if="storePage.pageAuth.canDelete === 1" :icon="h(DeleteOutlined)" danger class="delete">删除</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
@@ -70,20 +70,8 @@
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Fold as ElIconFold,
|
||||
Expand as ElIconExpand,
|
||||
Delete as ElIconDelete,
|
||||
Stamp as ElIconSCheck,
|
||||
Share as ElIconShare,
|
||||
Iphone as ElIconMobilePhone,
|
||||
Download as ElIconDownload,
|
||||
MoreFilled as ElIconMoreFilled,
|
||||
Setting as ElIconSetting,
|
||||
UserFilled as ElIconUserFilled,
|
||||
} from '@element-plus/icons-vue'
|
||||
import {
|
||||
UserOutlined, EditOutlined, MessageOutlined, CheckOutlined, EllipsisOutlined,
|
||||
MenuFoldOutlined, MenuUnfoldOutlined, LoadingOutlined
|
||||
UserOutlined, EditOutlined, MessageOutlined, CheckOutlined, EllipsisOutlined, DeleteOutlined, ShareAltOutlined,
|
||||
MenuFoldOutlined, MenuUnfoldOutlined, LoadingOutlined, SafetyOutlined, DownloadOutlined, MobileOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import {toRefs, ref, reactive, onMounted, watch, defineEmits, h, computed} from 'vue';
|
||||
import {useRouter, useRoute} from "vue-router";
|
||||
|
||||
@@ -10,7 +10,7 @@ import {toRefs, ref, reactive, onMounted, onBeforeUnmount, watch, defineEmits, c
|
||||
const props = defineProps({
|
||||
modelValue: Number,
|
||||
max: {type: Number, default: 600},
|
||||
min: {type: Number, default: 200}
|
||||
min: {type: Number, default: 240}
|
||||
});
|
||||
let emit = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ const getUserHeadBgColor = (userId) => {
|
||||
|
||||
.comment-btn-box {
|
||||
text-align: right;
|
||||
padding: 4px 15px 6px 0;
|
||||
padding: 4px 6px 6px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -20,7 +20,10 @@
|
||||
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";
|
||||
import applyOnce from "@/assets/js/applyOnce";
|
||||
import {useStoreDisplay} from "@/store/wikiDisplay";
|
||||
|
||||
let storeDisplay = useStoreDisplay();
|
||||
const props = defineProps({
|
||||
heading: {type: Array, default: []},
|
||||
});
|
||||
@@ -30,6 +33,9 @@ onMounted(() => {
|
||||
useResizeEvent(() => {
|
||||
computeNavigationWidth();
|
||||
});
|
||||
watch(() => storeDisplay.rightAsideWidth, (newVal) => {
|
||||
computeNavigationWidth();
|
||||
});
|
||||
let isLeave = false;
|
||||
let leaveTimer = undefined;
|
||||
const navigationMouseover = () => {
|
||||
@@ -53,7 +59,7 @@ const navigationToMax = () => {
|
||||
let navigationMin = ref(false);
|
||||
let navigationShow = ref(true);
|
||||
let navigationStyle = ref({width: '200px'});
|
||||
const computeNavigationWidth = () => {
|
||||
const computeNavigationWidth = applyOnce(() => {
|
||||
let pageViewContent = document.getElementById('pageContentBox');
|
||||
let pageContentScrollBox = document.getElementById('pageContentScrollBox');
|
||||
// pageContentScrollBox的宽度减去pageViewContent的宽度除以2
|
||||
@@ -68,7 +74,7 @@ const computeNavigationWidth = () => {
|
||||
}
|
||||
navigationMin.value = !navigationShow.value;
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
const headingItemClick = (item) => {
|
||||
// 滚动到指定节点
|
||||
item.node.scrollIntoView({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user