Merge pull request #18 from fantasticit/feat/share

pull/20/head
fantasticit 2022-03-28 22:52:13 +08:00 committed by GitHub
commit 8bc7cb5665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 10 deletions

View File

@ -1,7 +1,20 @@
import React, { useMemo, useEffect } from 'react'; import React, { useMemo, useEffect } from 'react';
import cls from 'classnames'; import cls from 'classnames';
import { Layout, Nav, Space, Button, Typography, Skeleton, Input, Popover, Modal, BackTop } from '@douyinfe/semi-ui'; import {
Layout,
Nav,
Space,
Button,
Typography,
Skeleton,
Input,
Popover,
Modal,
Breadcrumb,
BackTop,
} from '@douyinfe/semi-ui';
import { IconArticle } from '@douyinfe/semi-icons'; import { IconArticle } from '@douyinfe/semi-icons';
import Link from 'next/link';
import { Seo } from 'components/seo'; import { Seo } from 'components/seo';
import { LogoImage, LogoText } from 'components/logo'; import { LogoImage, LogoText } from 'components/logo';
import { DataRender } from 'components/data-render'; import { DataRender } from 'components/data-render';
@ -91,9 +104,14 @@ export const DocumentPublicReader: React.FC<IProps> = ({ documentId, hideLogo =
<Skeleton active placeholder={<Skeleton.Title style={{ width: 80, marginBottom: 8 }} />} loading={true} /> <Skeleton active placeholder={<Skeleton.Title style={{ width: 80, marginBottom: 8 }} />} loading={true} />
} }
normalContent={() => ( normalContent={() => (
<Text strong ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWidth / 4) }}> <Breadcrumb>
{data.title} <Breadcrumb.Item>
</Text> <Link href="/share/wiki/[wikiId]" as={`/share/wiki/${data.wikiId}`}>
<a>{data?.wiki?.name}</a>
</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>{data.title}</Breadcrumb.Item>
</Breadcrumb>
)} )}
/> />
</Nav> </Nav>

View File

@ -49,6 +49,25 @@ export const DocumentShare: React.FC<IProps> = ({ documentId, render }) => {
onCancel={() => toggleVisible(false)} onCancel={() => toggleVisible(false)}
maskClosable={false} maskClosable={false}
style={{ maxWidth: '96vw' }} style={{ maxWidth: '96vw' }}
footer={
<>
<Button onClick={() => toggleVisible(false)}></Button>
<Button theme="solid" type={isPublic ? 'danger' : 'primary'} onClick={handleOk}>
{isPublic ? '关闭分享' : '开启分享'}
</Button>
{isPublic && (
<Button
theme="solid"
type="primary"
onClick={() => {
window.open(shareUrl, '_blank');
}}
>
</Button>
)}
</>
}
> >
<DataRender <DataRender
loading={loading} loading={loading}

View File

@ -14,9 +14,18 @@ interface IProps {
}; };
isActive?: boolean; isActive?: boolean;
hoverable?: boolean; hoverable?: boolean;
openNewTab?: boolean;
} }
export const NavItem: React.FC<IProps> = ({ icon, text, rightNode, href, isActive = false, hoverable = true }) => { export const NavItem: React.FC<IProps> = ({
icon,
text,
rightNode,
href,
isActive = false,
hoverable = true,
openNewTab = false,
}) => {
const right = rightNode ? <span className={styles.rightWrap}>{rightNode}</span> : null; const right = rightNode ? <span className={styles.rightWrap}>{rightNode}</span> : null;
const content = ( const content = (
<> <>
@ -32,7 +41,9 @@ export const NavItem: React.FC<IProps> = ({ icon, text, rightNode, href, isActiv
> >
{href ? ( {href ? (
<Link href={href as UrlObject}> <Link href={href as UrlObject}>
<a className={styles.navItem}>{content}</a> <a className={styles.navItem} target={openNewTab ? '_blank' : '_self'}>
{content}
</a>
</Link> </Link>
) : ( ) : (
<div className={styles.navItem}>{content}</div> <div className={styles.navItem}>{content}</div>

View File

@ -1,6 +1,6 @@
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Avatar, Button, Typography, Skeleton } from '@douyinfe/semi-ui'; import { Avatar, Button, Typography, Skeleton, Tooltip } from '@douyinfe/semi-ui';
import { IconPlus } from '@douyinfe/semi-icons'; import { IconPlus } from '@douyinfe/semi-icons';
import { useWikiDetail, useWikiTocs } from 'data/wiki'; import { useWikiDetail, useWikiTocs } from 'data/wiki';
import { useToggle } from 'hooks/use-toggle'; import { useToggle } from 'hooks/use-toggle';
@ -13,6 +13,7 @@ import { EventEmitter } from 'helpers/event-emitter';
import { NavItem } from './NavItem'; import { NavItem } from './NavItem';
import { Tree } from './tree'; import { Tree } from './tree';
import styles from './index.module.scss'; import styles from './index.module.scss';
import { isPublicWiki } from '@think/domains';
const em = new EventEmitter(); const em = new EventEmitter();
const EVENT_KEY = 'REFRESH_TOCS'; const EVENT_KEY = 'REFRESH_TOCS';
@ -127,6 +128,45 @@ export const WikiTocs: React.FC<IProps> = ({
isActive={pathname === '/wiki/[wikiId]/setting'} isActive={pathname === '/wiki/[wikiId]/setting'}
/> />
<DataRender
loading={wikiLoading}
loadingContent={
<NavItem
icon={
<Skeleton.Avatar
size="small"
style={{
marginRight: 8,
width: 24,
height: 24,
borderRadius: 4,
}}
></Skeleton.Avatar>
}
text={<Skeleton.Title style={{ width: 120 }} />}
/>
}
error={wikiError}
normalContent={() =>
isPublicWiki(wiki.status) ? (
<NavItem
icon={<IconOverview />}
text={
<Tooltip content="该知识库已公开,点我查看" position="right">
</Tooltip>
}
href={{
pathname: `/share/wiki/[wikiId]`,
query: { wikiId },
}}
isActive={pathname === '/share/wiki/[wikiId]'}
openNewTab
/>
) : null
}
/>
<DataRender <DataRender
loading={wikiLoading} loading={wikiLoading}
loadingContent={ loadingContent={

View File

@ -1,4 +1,4 @@
import type { IUser, IDocument } from '@think/domains'; import type { IUser, IDocument, IWiki } from '@think/domains';
import useSWR from 'swr'; import useSWR from 'swr';
import { useState, useCallback, useEffect } from 'react'; import { useState, useCallback, useEffect } from 'react';
import { useAsyncLoading } from 'hooks/use-async-loading'; import { useAsyncLoading } from 'hooks/use-async-loading';
@ -128,7 +128,7 @@ export const useStaredDocuments = () => {
*/ */
export const usePublicDocument = (documentId: string) => { export const usePublicDocument = (documentId: string) => {
const [fetch] = useAsyncLoading(getPublicDocumentDetail); const [fetch] = useAsyncLoading(getPublicDocumentDetail);
const [document, setDocument] = useState<IDocument | null>(null); const [document, setDocument] = useState<(IDocument & { createUse: IUser; wiki: IWiki }) | null>(null);
const [error, setError] = useState<(Error & { statusCode?: number }) | null>(null); const [error, setError] = useState<(Error & { statusCode?: number }) | null>(null);
const loading = !document && !error; const loading = !document && !error;

View File

@ -552,8 +552,9 @@ export class DocumentService {
await this.viewService.create({ userId: 'public', documentId, userAgent }); await this.viewService.create({ userId: 'public', documentId, userAgent });
const views = await this.viewService.getDocumentTotalViews(documentId); const views = await this.viewService.getDocumentTotalViews(documentId);
const createUser = await this.userService.findById(document.createUserId); const createUser = await this.userService.findById(document.createUserId);
const wiki = await this.wikiService.getPublicWikiDetail(document.wikiId);
return { ...document, views, createUser }; return { ...document, views, wiki, createUser };
} }
/** /**