| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- import React, { Component } from 'react';
- import { message } from 'antd';
- import { connect } from 'react-redux';
- import axios from 'axios';
- import PropTypes from 'prop-types';
- import './index.scss';
- import { timeago } from '../../../common/utils';
- import { Link } from 'react-router-dom';
- import WikiView from './View.js';
- import WikiEditor from './Editor.js';
- @connect(
- state => {
- return {
- projectMsg: state.project.currProject
- };
- },
- {}
- )
- class WikiPage extends Component {
- constructor(props) {
- super(props);
- this.state = {
- isEditor: false,
- isUpload: true,
- desc: '',
- markdown: '',
- notice: props.projectMsg.switch_notice,
- status: 'INIT',
- editUid: '',
- editName: '',
- curdata: null
- };
- }
- static propTypes = {
- match: PropTypes.object,
- projectMsg: PropTypes.object
- };
- async componentDidMount() {
- const currProjectId = this.props.match.params.id;
- await this.handleData({ project_id: currProjectId });
- this.handleConflict();
- }
- componentWillUnmount() {
- // willUnmount
- try {
- if (this.state.status === 'CLOSE') {
- this.WebSocket.send('end');
- this.WebSocket.close();
- }
- } catch (e) {
- return null;
- }
- }
- // 结束编辑websocket
- endWebSocket = () => {
- try {
- if (this.state.status === 'CLOSE') {
- const sendEnd = () => {
- this.WebSocket.send('end');
- };
- this.handleWebsocketAccidentClose(sendEnd);
- }
- } catch (e) {
- return null;
- }
- };
- // 处理多人编辑冲突问题
- handleConflict = () => {
- // console.log(location)
- let domain = location.hostname + (location.port !== '' ? ':' + location.port : '');
- let s;
- //因后端 node 仅支持 ws, 暂不支持 wss
- let wsProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
- s = new WebSocket(
- wsProtocol +
- '://' +
- domain +
- '/api/ws_plugin/wiki_desc/solve_conflict?id=' +
- this.props.match.params.id
- );
- s.onopen = () => {
- this.WebSocket = s;
- s.send('start');
- };
- s.onmessage = e => {
- let result = JSON.parse(e.data);
- if (result.errno === 0) {
- // 更新
- if (result.data) {
- this.setState({
- // curdata: result.data,
- desc: result.data.desc,
- username: result.data.username,
- uid: result.data.uid,
- editorTime: timeago(result.data.up_time)
- });
- }
- // 新建
- this.setState({
- isEditor: !this.state.isEditor,
- status: 'CLOSE'
- });
- } else {
- this.setState({
- editUid: result.data.uid,
- editName: result.data.username,
- status: 'EDITOR'
- });
- }
- };
- s.onerror = () => {
- this.setState({
- status: 'CLOSE'
- });
- console.warn('websocket 连接失败,将导致多人编辑同一个接口冲突。');
- };
- };
- // 点击编辑按钮 发送 websocket 获取数据
- onEditor = () => {
- // this.WebSocket.send('editor');
- const sendEditor = () => {
- this.WebSocket.send('editor');
- };
- this.handleWebsocketAccidentClose(sendEditor, status => {
- // 如果websocket 启动不成功用户依旧可以对wiki 进行编辑
- if (!status) {
- this.setState({
- isEditor: !this.state.isEditor
- });
- }
- });
- };
- // 处理websocket 意外断开问题
- handleWebsocketAccidentClose = (fn, callback) => {
- // websocket 是否启动
- if (this.WebSocket) {
- // websocket 断开
- if (this.WebSocket.readyState !== 1) {
- message.error('websocket 链接失败,请重新刷新页面');
- } else {
- fn();
- }
- callback(true);
- } else {
- callback(false);
- }
- };
- // 获取数据
- handleData = async params => {
- let result = await axios.get('/api/plugin/wiki_desc/get', { params });
- if (result.data.errcode === 0) {
- const data = result.data.data;
- if (data) {
- this.setState({
- desc: data.desc,
- markdown: data.markdown,
- username: data.username,
- uid: data.uid,
- editorTime: timeago(data.up_time)
- });
- }
- } else {
- message.error(`请求数据失败: ${result.data.errmsg}`);
- }
- };
- // 数据上传
- onUpload = async (desc, markdown) => {
- const currProjectId = this.props.match.params.id;
- let option = {
- project_id: currProjectId,
- desc,
- markdown,
- email_notice: this.state.notice
- };
- let result = await axios.post('/api/plugin/wiki_desc/up', option);
- if (result.data.errcode === 0) {
- await this.handleData({ project_id: currProjectId });
- this.setState({ isEditor: false });
- } else {
- message.error(`更新失败: ${result.data.errmsg}`);
- }
- this.endWebSocket();
- // this.WebSocket.send('end');
- };
- // 取消编辑
- onCancel = () => {
- this.setState({ isEditor: false });
- this.endWebSocket();
- };
- // 邮件通知
- onEmailNotice = e => {
- this.setState({
- notice: e.target.checked
- });
- };
- render() {
- const { isEditor, username, editorTime, notice, uid, status, editUid, editName } = this.state;
- const editorEable =
- this.props.projectMsg.role === 'admin' ||
- this.props.projectMsg.role === 'owner' ||
- this.props.projectMsg.role === 'dev';
- const isConflict = status === 'EDITOR';
- return (
- <div className="g-row">
- <div className="m-panel wiki-content">
- <div className="wiki-content">
- {isConflict && (
- <div className="wiki-conflict">
- <Link to={`/user/profile/${editUid || uid}`}>
- <b>{editName || username}</b>
- </Link>
- <span>正在编辑该wiki,请稍后再试...</span>
- </div>
- )}
- </div>
- {!isEditor ? (
- <WikiView
- editorEable={editorEable}
- onEditor={this.onEditor}
- uid={uid}
- username={username}
- editorTime={editorTime}
- desc={this.state.desc}
- />
- ) : (
- <WikiEditor
- isConflict={isConflict}
- onUpload={this.onUpload}
- onCancel={this.onCancel}
- notice={notice}
- onEmailNotice={this.onEmailNotice}
- desc={this.state.desc}
- />
- )}
- </div>
- </div>
- );
- }
- }
- export default WikiPage;
|