123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- import React, { useState } from 'react'
- import useRequest from '@ahooksjs/use-request/es'
- import { useHistory } from 'react-router-dom'
- import dayjs from 'dayjs'
- import { Modal, message, Watermark } from 'antd'
- import { StarFilled, StarOutlined, EyeOutlined, LikeOutlined, LikeFilled } from '@ant-design/icons'
- import { ReactComponent as Close } from 'assets/close.svg'
- import { useLogin2p } from 'Login2p/Login2pContext'
- import { ColumnService, IColumnDetail, IDocsList, IEditColumnDetail } from 'Column/Column.service'
- import Picture from 'Activity/components/Picture'
- import { FilesSvg } from 'Column/ColumnEditor'
- import { ColumnStatus } from './ColumnCenter'
- import AskAdd from 'Material/components/AskAdd'
- import ColumnContentMessage from './ColumnContentMessage'
- import { ITryType, INewPermissionType } from 'Material/components/NoPermission'
- import PayNoPermission from 'Material/components/PayNoPermission'
- import styles from '../css/ColumnDetail.module.scss'
- import 'froala-editor/css/froala_style.min.css'
- import 'froala-editor/css/froala_editor.pkgd.min.css'
- import 'froala-editor/css/plugins/image.min.css'
- import 'froala-editor/css/third_party/image_tui.min.css'
- import 'froala-editor/css/plugins/file.min.css'
- import 'froala-editor/css/plugins/colors.min.css'
- import 'froala-editor/css/plugins/emoticons.min.css'
- export enum ColumnType {
- Note = 1,
- Viewpoint = 2
- }
- interface IColumnContentProps {
- detail: IColumnDetail | IEditColumnDetail // 直接传入渲染的数据
- type?: 'detail' | 'list' | 'preview' | 'check' // detail-详情页,list-列表页,preview-预览页,check-审查页
- onCollect?: (ID: number) => void // 收藏回调(预览时没有收藏功能)
- onLike?: (ID: number) => void // 收藏回调(预览时没有收藏功能)
- onClose?: () => void
- handleToRefresh?: () => void
- }
- /**笔记/观点 */
- const ColumnContent: React.FC<IColumnContentProps> = props => {
- const { detail, type = 'detail', onClose, onCollect, handleToRefresh, onLike } = props
- const login2p = useLogin2p()
- const history = useHistory()
- const [bigImg, setBigImg] = useState<string>() // 展开的图片
- const [visibleAsk, setVisibleAsk] = useState(false)
- // 收藏/取消收藏(研选专栏)
- const { run: applyCollect } = useRequest(ColumnService.postColumnCollect, {
- manual: true,
- onSuccess: res => {
- message.info(res.data.Msg || res.data.ErrMsg)
- if (res.data.Success) {
- onCollect && onCollect(detail.Id)
- }
- }
- })
- // 点赞/取消点赞(研选专栏)
- const { run: postColumnLike } = useRequest(ColumnService.postColumnLike, {
- manual: true,
- onSuccess: res => {
- message.info(res.data.Msg || res.data.ErrMsg)
- if (res.data.Success) {
- onLike && onLike(detail.Id)
- }
- }
- })
- // 审核文章
- const { run: applyCheckColumnNote } = useRequest(ColumnService.postCheckColumnNote, {
- manual: true,
- onSuccess: res => {
- res.data.Success ? message.success(res.data.Msg) : message.error(res.data.Msg || res.data.ErrMsg)
- res.data.Success && history.push(`/column`)
- }
- })
- // 专栏添加关注
- const { run: postColumnFollow } = useRequest(ColumnService.postColumnAuthorFollow, {
- manual: true,
- onSuccess: res => {
- res.data.Success
- ? (detail as IColumnDetail).IsFollowAuthor
- ? message.success(res.data.Msg)
- : Modal.info({
- title: '已关注专栏',
- content: '请关注【买方研选】公众号,及时获取专栏下内容更新提醒',
- okText: '知道了',
- centered: true
- })
- : message.error(res.data.Msg || res.data.ErrMsg)
- res.data.Success && onCollect && onCollect(detail.Id)
- }
- })
- // 关注专栏
- const handleOnFollowColumn = () => {
- // 检查是否登录了,未登录进入登录页面
- if (!login2p.jwt) {
- history.push(`/login2p?next=${encodeURIComponent(window.location.pathname + window.location.search)}`)
- return
- }
- postColumnFollow(detail.SpecialColumnId, (detail as IColumnDetail)?.IsFollowAuthor ? 2 : 1)
- }
- const handleOnClose = () => {
- onClose && onClose()
- }
- // 放大图片
- const handleOnClickPicture = (item: string) => {
- setBigImg(item)
- }
- // 关闭图片查看
- const handleToCloseBigImg = () => {
- setBigImg(undefined)
- }
- // 收藏与取消收藏
- const handleOnCollect = (collect: number) => {
- if (!login2p.jwt) {
- message.error('请先登录')
- return
- }
- applyCollect(detail.Id, !!collect ? 2 : 1)
- }
- // 点赞与取消点赞
- const handleOnLike = (like: boolean) => {
- if (!login2p.jwt) {
- message.error('请先登录')
- return
- }
- postColumnLike(detail.Id, !!like ? 0 : 1)
- }
- // 查看全文
- const handleToDetail = () => {
- window.open(`/column/detail/${detail.Id}`)
- }
- // 跳转到专栏详情页
- const handleToColumnIndex = () => {
- if (type === 'preview') return
- history.push(
- `/column/view/${(detail as IColumnDetail)?.SpecialColumnId}${
- login2p.inviteCode ? '?invite_code=' + login2p.inviteCode : ''
- }`
- )
- }
- // 预览文件
- const handlePreviewFile = (file: IDocsList) => {
- if (file.DocSuffix === 'pdf') {
- window.open(file.DocUrl)
- return
- }
- window.open('https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(file.DocUrl))
- }
- const computeFileSvgShow = (name: string, type: 'suffix' | 'svg') => {
- if (!name) return
- const suffix = name?.split('.')?.pop()
- if (type === 'suffix') return suffix
- return FilesSvg?.find(item => item.suffix === suffix)?.svg
- }
- // 如果是列表显示,隐藏img标签
- const handleHideImg = (html: string) => {
- if (
- type === 'list' ||
- ((detail as IColumnDetail)?.IsShowWxPay && (detail as IColumnDetail)?.HasPermission !== INewPermissionType.OK)
- ) {
- return html.replace(/<img[^>]*>/gi, '')
- }
- return html
- }
- const handleToClick = (type: string) => {
- if (!(detail as IColumnDetail).IsApprovalAdmin) return message.error('您没有权限操作')
- if ((detail as IColumnDetail).Status !== ColumnStatus.Auditing) return message.error('该文章未提交审批或已审批')
- const typeFn: {
- [key: string]: () => void
- } = {
- modify: () => {
- // 修改
- history.push(`/column/modify/${detail.Id}`)
- },
- reject: () => {
- // 打开一个弹框,输入驳回理由
- setVisibleAsk(true)
- },
- pass: () => {
- // 通过 打开二次确认框
- Modal.confirm({
- title: '提示',
- content: '确定通过此内容在小程序展示吗?',
- okText: '确定',
- cancelText: '取消',
- centered: true,
- closable: true,
- onOk: () => {
- applyCheckColumnNote(detail.Id, 1, '')
- }
- })
- }
- }
- typeFn[type]()
- }
- // 关闭驳回弹框
- const handleOkAsk = () => {
- setVisibleAsk(false)
- }
- // 提交驳回内容
- const handleApplyContent = (ID: number, content: string) => {
- applyCheckColumnNote(ID, 2, content)
- handleOkAsk()
- }
- // 查看更多
- const handleToShowMore = () => {
- if (!login2p.jwt) {
- history.push(`/login2p?next=${encodeURIComponent(window.location.pathname + window.location.search)}`)
- return
- }
- }
- return (
- <div className={`${styles['columndetail-show-wrapper']}`}>
- {type === 'preview' && (
- <div className="columndetail-close">
- <Close className="detail-close" onClick={handleOnClose} />
- </div>
- )}
- <div className="author-line g-flex g-flex-v-center g-flex-between g-flex-wap">
- <div className="g-flex g-flex-v-center g-flex-c1">
- <div className="artcle-tag artcle-tag-two m-r-sm m-b-xs">
- {detail.Type === ColumnType.Note ? '笔记' : '观点'}
- </div>
- <div className="g-flex g-flex-v-center">
- <img
- src={detail.HeadImg}
- alt="图片"
- className="author-avatar com-cursor-p g-va-middle m-b-xs"
- onClick={handleToColumnIndex}
- />
- <span
- className="com-cursor-p m-r-sm g-va-middle m-b-xs g-ellipsis1 nickname-text"
- onClick={handleToColumnIndex}
- >
- {detail.NickName}
- </span>
- {type === 'detail' && (
- <div className="columndetail-follow com-cursor-p m-b-xs" onClick={handleOnFollowColumn}>
- {(detail as IColumnDetail).IsFollowAuthor ? '取消关注' : '关注专栏'}
- </div>
- )}
- </div>
- </div>
- <div className="columndetail-time">{dayjs(detail?.PublishTime || '').format('YYYY-MM-DD HH:mm:ss')}</div>
- </div>
- <div className="com-fz18 com-fw-bold m-b-sm">{detail.Title}</div>
- <Watermark
- content={login2p.userInfo ? login2p.userInfo?.Mobile : '水印'}
- font={{ fontSize: 22, color: 'rgba(0,0,0,.08)' }}
- >
- <div
- className={`fr-element fr-view ${
- type === 'list' ||
- (type === 'detail' && !login2p.jwt) ||
- ((detail as IColumnDetail)?.IsShowWxPay &&
- (detail as IColumnDetail)?.HasPermission !== INewPermissionType.OK)
- ? 'note-content'
- : 'columndetail-content'
- } `}
- dangerouslySetInnerHTML={{
- __html: handleHideImg(detail.Content)
- }}
- />
- </Watermark>
- {(detail as IColumnDetail)?.IsShowWxPay &&
- (detail as IColumnDetail)?.HasPermission !== INewPermissionType.OK && ( // 暂时这么写
- <PayNoPermission
- dataInfo={detail as IColumnDetail}
- tryType={ITryType.YanxuanSpecial}
- border={false}
- onRefresh={handleToRefresh}
- />
- )}
- <>
- {type === 'list' && (
- <div className="g-flex g-flex-v-center g-flex-between m-b-md note-showmore-line">
- <div className="g-flex g-flex-v-center">
- <div className="note-pv">
- <EyeOutlined size={14} className="pv-icon" />
- <span>{(detail as IColumnDetail).Pv || 0}</span>
- </div>
- {(detail as IColumnDetail)?.IsCollect ? (
- <StarFilled
- className="collect-icon"
- onClick={handleOnCollect.bind(this, (detail as IColumnDetail)?.IsCollect)}
- />
- ) : (
- <StarOutlined
- className="collect-icon"
- onClick={handleOnCollect.bind(this, (detail as IColumnDetail)?.IsCollect)}
- />
- )}
- <span style={{ marginRight: 10 }} className="collect-count">
- {(detail as IColumnDetail)?.CollectNum}
- </span>
- {(detail as IColumnDetail)?.IsLikeCount ? (
- <LikeFilled
- className="collect-icon"
- onClick={handleOnLike.bind(this, (detail as IColumnDetail)?.IsLikeCount)}
- />
- ) : (
- <LikeOutlined
- className="collect-icon"
- onClick={handleOnLike.bind(this, (detail as IColumnDetail)?.IsLikeCount)}
- />
- )}
- <span className="collect-count">{(detail as IColumnDetail)?.LikeCount}</span>
- </div>
- <div className="note-showmore-btn" onClick={handleToDetail}>
- 查看全文
- </div>
- </div>
- )}
- </>
- {(detail as IColumnDetail)?.HasPermission === INewPermissionType.OK && (
- <>
- {!login2p.jwt && type === 'detail' ? (
- <div className="please-login-btn" onClick={handleToShowMore}>
- 请登录后查看更多内容
- </div>
- ) : (
- <>
- <div className="operate-file-wrapper">
- {detail?.Docs?.map((item: IDocsList, index: number) => (
- <div
- className="operate-file-item com-cursor-p"
- key={index}
- onClick={handlePreviewFile.bind(this, item)}
- >
- <div className="g-flex g-flex-v-center">
- {item.DocIcon ? (
- <img src={item.DocIcon} className="operate-file-type" alt="图标" />
- ) : (
- computeFileSvgShow(item.DocName, 'svg')
- )}
- <span className="operate-file-text">{item.DocName}</span>
- </div>
- </div>
- ))}
- </div>
- <div className="operate-file-wrapper">
- {detail?.ImgUrlList?.map((item, index) => (
- <React.Fragment key={index}>
- {item && (
- <div className="operate-image-item" key={item} onClick={handleOnClickPicture.bind(this, item)}>
- <img src={item} alt={'图片' + item} className="operate-image" />
- </div>
- )}
- </React.Fragment>
- ))}
- </div>
- <div className="columndetail-category-label g-flex g-flex-v-center g-flex-wap">
- {type !== 'list' ? (
- <>
- {detail?.IndustryTags?.map(item => (
- <div className="select-item" key={item}>
- <span>{item}</span>
- </div>
- ))}
- {detail?.CompanyTags?.map(item => (
- <div className="select-item" key={item}>
- <span>{item}</span>
- </div>
- ))}
- </>
- ) : (
- <>
- {(detail as IColumnDetail)?.TagList?.map(item => (
- <div className="select-item" key={item}>
- <span>{item}</span>
- </div>
- ))}
- </>
- )}
- </div>
- {type === 'detail' && (detail as IColumnDetail).Status === ColumnStatus.Published && (
- <>
- <div className="detail-pv-collect-like note-showmore-line">
- <div className="note-pv">
- <EyeOutlined size={14} className="pv-icon" />
- <span>{(detail as IColumnDetail).Pv || 0}</span>
- </div>
- <div>
- {(detail as IColumnDetail)?.IsCollect ? (
- <StarFilled
- className="collect-icon"
- onClick={handleOnCollect.bind(this, (detail as IColumnDetail)?.IsCollect)}
- />
- ) : (
- <StarOutlined
- className="collect-icon"
- onClick={handleOnCollect.bind(this, (detail as IColumnDetail)?.IsCollect)}
- />
- )}
- <span style={{ marginRight: 10 }} className="collect-count">
- {(detail as IColumnDetail)?.CollectNum}
- </span>
- {(detail as IColumnDetail)?.IsLikeCount ? (
- <LikeFilled
- className="collect-icon"
- onClick={handleOnLike.bind(this, (detail as IColumnDetail)?.IsLikeCount)}
- />
- ) : (
- <LikeOutlined
- className="collect-icon"
- onClick={handleOnLike.bind(this, (detail as IColumnDetail)?.IsLikeCount)}
- />
- )}
- <span className="collect-count">{(detail as IColumnDetail)?.LikeCount}</span>
- </div>
- </div>
- {/* <div>请写下您的留言</div>
- */}
- <ColumnContentMessage detailId={(detail as IColumnDetail).Id} />
- </>
- )}
- </>
- )}
- {type === 'check' && (
- <>
- <div className="check-operate-wrapper">
- <div className="operate-nomal-btn save-btn" onClick={handleToClick.bind(this, 'modify')}>
- 修改
- </div>
- <div className="operate-nomal-btn reject-btn" onClick={handleToClick.bind(this, 'reject')}>
- 驳回
- </div>
- <div className="operate-nomal-btn publish-btn" onClick={handleToClick.bind(this, 'pass')}>
- 通过
- </div>
- </div>
- {visibleAsk ? (
- <AskAdd
- title="驳回"
- placeholder="请输入驳回理由"
- visible={visibleAsk}
- ID={detail.Id}
- onApply={handleApplyContent}
- onCloseModel={handleOkAsk}
- />
- ) : null}
- </>
- )}
- <Picture visible={!!bigImg} imgSrc={bigImg} onClose={handleToCloseBigImg} />
- </>
- )}
- </div>
- )
- }
- export default ColumnContent
|