diff --git a/package.json b/package.json
index 6f96decbb..420fac00d 100644
--- a/package.json
+++ b/package.json
@@ -177,7 +177,7 @@
"eslintConfig": {
"extends": "react-app"
},
- "proxy": "http://localhost:3000",
+ "proxy": "http://172.20.32.202:4000",
"port": "3007",
"devDependencies": {
"@babel/runtime": "7.0.0-beta.51",
diff --git a/public/index.html b/public/index.html
index 647288a0c..230100956 100755
--- a/public/index.html
+++ b/public/index.html
@@ -20,7 +20,7 @@
-
+
diff --git a/src/AppConfig.js b/src/AppConfig.js
index cf7fe8b6a..5c5b188a5 100644
--- a/src/AppConfig.js
+++ b/src/AppConfig.js
@@ -32,7 +32,7 @@ export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener();
- var proxy = "https://testforgeplus.trustie.net";
+ var proxy = "http://172.20.32.202:4000";
//响应前的设置
axios.interceptors.request.use(
@@ -43,18 +43,20 @@ export function initAxiosInterceptors(props) {
requestProxy(config);
let url = `/api${config.url}`;
- if (`${config[0]}` !== `true`) {
- if (window.location.port === "3007") {
- config.url = `${proxy}${url}`;
- if (config.url.indexOf('?') === -1) {
- config.url = `${config.url}?debug=${debugType}`;
- } else {
- config.url = `${config.url}&debug=${debugType}`;
- }
- } else {
- config.url = url;
- }
- }
+ // if (`${config[0]}` !== `true`) {
+ // if (window.location.port === "3007") {
+ // config.url = `${proxy}${url}`;
+ // if (config.url.indexOf('?') === -1) {
+ // config.url = `${config.url}`;
+ // } else {
+ // config.url = `${config.url}`;
+ // }
+ // } else {
+ // config.url = url;
+ // }
+ // }
+ config.url = url;
+ config.withCredentials = false;
return config;
},
err => {
diff --git a/src/common/UrlTool.js b/src/common/UrlTool.js
index 8360c5f10..452529717 100644
--- a/src/common/UrlTool.js
+++ b/src/common/UrlTool.js
@@ -140,10 +140,10 @@ export function setImagesUrl(path){
}
export function getUrl(path, goTest) {
- const local = 'https://testforgeplus.trustie.net'
- if (isDev) {
- return `${local}${path?path:''}`
- }
+ // const local = 'http://172.20.32.202:8080'
+ // if (isDev) {
+ // return `${local}${path?path:''}`
+ // }
return `${path ? path: ''}`;
}
diff --git a/src/forge/Information/Component/comments/editComment.jsx b/src/forge/Information/Component/comments/editComment.jsx
new file mode 100644
index 000000000..1f1727a89
--- /dev/null
+++ b/src/forge/Information/Component/comments/editComment.jsx
@@ -0,0 +1,167 @@
+import React from 'react';
+import { Button, message } from 'antd';
+import { getImageUrl } from 'educoder';
+import MDEditor from "../../../../modules/tpm/challengesnew/tpm-md-editor";
+import Upload from "../../../../forge/Upload/Index";
+import Attachments from "../../../../forge/Upload/attachment";
+import UploadImg from "../../../../forge/Images/upload.png";
+import './list.scss';
+import '../../../../forge/Order/order.scss';
+import { useState } from 'react';
+import { Link } from 'react-router-dom';
+import axios from 'axios';
+import { addComment, editComment } from '../../api'
+
+function EditComment(props){
+ const {owner, projectsId, index} = props.match.params;
+ const {current_user, current_user:{login}, docId, showNotification, reloadComment, cancelMd, parentId, replyId, updateId, showUserImg=true} = props;
+ const [content, setContent] = useState(props.content);
+ const [quillFlag, setQuillFlag] = useState(false);
+ // 确认评论按钮loading效果
+ const [journalSpin, setJournalSpin] = useState(false);
+ const [atWhoLoginList, setAtWhoLoginList] = useState(undefined);
+ const [fileList, setFileList] = useState(undefined);
+ const [attachmentClean, setAttachmentClean] = useState(true);
+ const [ save , setSave ] = useState(undefined);
+
+ useState(()=>{
+ setSave(props.defaultFileList);
+ },[props.defaultFileList])
+
+ // 评论点击函数
+ function addJournals(){
+ if(!content){
+ setQuillFlag(true);
+ return
+ }
+ setJournalSpin(true);
+ console.log(updateId)
+ if(updateId){
+ // 修改评论
+ const params = {
+ id: updateId,
+ notes: content,
+ attachmentIds: fileList,
+ receivers_login:atWhoLoginList
+ }
+ editComment(docId, params).then(res=>{
+ if(res && res.data && res.data.data){
+ // 刷新评论列表
+ reloadComment();
+ message.success('评论成功');
+ cancelMd();
+ setContent(undefined);
+ }
+ setJournalSpin(false);
+ })
+ }else{
+ // 新建评论
+ const params = {
+ parentId: parentId,
+ replyId: replyId,
+ notes: content,
+ attachmentIds: fileList,
+ }
+
+ addComment(docId, params).then(res=>{
+ if(res && res.data && res.data.data){
+ // 刷新评论列表
+ reloadComment();
+ message.success('评论成功');
+ cancelMd();
+ setContent(undefined);
+ }
+ setJournalSpin(false);
+ })
+ }
+ };
+ function deleteLoad(id){
+ let arr = [];
+ let list = save;
+ if(list && list.length>0 ){
+ arr = list.filter(i=>i.id !== id);
+ }
+ setFileList(arr.map(i=>{return i.id}));
+ setSave(arr);
+ }
+ function UploadFunc(f){
+ let list = [];
+ let arr = [];
+ if(save && save.length>0 ){
+ arr = save.map(i=>{return i.id});
+ }
+ list = arr && arr.length>0 ? f.concat(arr) : f ;
+ setFileList(list);
+ };
+
+ return(
+
+
+

+
+
+
{setQuillFlag(false);setContent(value);}}
+ changeAtWhoLoginList = {(loginList)=>{setAtWhoLoginList(loginList); setAttachmentClean(true)}}
+ owner = {owner}
+ projectsId = {projectsId}
+ >
+
+ {quillFlag && 请输入评论内容}
+
+
+ }
+ size={100}
+ showNotification={showNotification}
+ // defaultFileList={props.defaultFileList}
+ />
+ {props.defaultFileList && props.defaultFileList.length > 0 &&
+
+ }
+
+
+
+
+
+
+ )
+}
+export default EditComment;
\ No newline at end of file
diff --git a/src/forge/Information/Component/comments/list.jsx b/src/forge/Information/Component/comments/list.jsx
new file mode 100644
index 000000000..4e70f5468
--- /dev/null
+++ b/src/forge/Information/Component/comments/list.jsx
@@ -0,0 +1,226 @@
+import React, { useEffect, useState } from 'react';
+import { Button, Popconfirm, Radio, Input, message, Tooltip, Spin, Pagination } from 'antd';
+import axios from 'axios';
+import { getImageUrl, timeAgo } from 'educoder';
+import RenderHtml from '../../../../components/render-html';
+import Attachment from '../../../Upload/attachment';
+import EditComment from './editComment';
+import Nodata from '../../../Nodata';
+import CheckProfile from '../../../Component/ProfileModal/Profile';
+import './list.scss';
+import { Link } from 'react-router-dom';
+import { getCommentList, deleteComment } from '../../api'
+
+function IssueCommentList(props){
+ const{docId, history: {location}, reload, reloadComment, showNotification, current_user:{login, admin, image_url, username}, isManager, showLoginDialog, author} = props;
+ const {owner, projectsId, index} = props.match.params;
+ const [category, setCategory] = useState('comment');
+ const [journals, setJournals] = useState(undefined);
+ // 是否展示新建/编辑评论markdown部分新建评论1 编辑父级评论2 回复评论3 编辑回复内容4 回复子机评论5
+ const [showEdit, setShowEdit] = useState(false);
+ const [parentId, setParentId] = useState(undefined);
+ const [replyId, setReplyId] = useState(undefined);
+ // 修改评论id
+ const [updateId, setUpdateId] = useState(undefined);
+ // 操作日志展开效果
+ const [open, setOpen] = useState(undefined);
+ // 加载中效果(缓冲css 线条效果)
+ const [spin, setSpin] = useState(false);
+ // issue 评论总数
+ const [journalsCount, setJournalsCount] = useState(undefined);
+ // 分页
+ const limit = 50;
+ const [page, setPage] = useState(1);
+ const [totalCount, setTotalCount] = useState(undefined);
+ // 操作记录 icon
+ const journalsIcon ={
+ 'issue': 'icon-chuangjianqianbao',
+ 'branch_name': 'icon-fenzhi3',
+ 'assigner': 'icon-chengyuan2',
+ 'status_id': 'icon-xiugaibaobiaomoban',
+ 'fixed_version_id': 'icon-lichengbeiicon2',
+ 'due_date': 'icon-riqi',
+ 'issue_tag': 'icon-biaoji2',
+ 'description': 'icon-xiugaibaobiaomoban',
+ 'subject': 'icon-xiugaibaobiaomoban',
+ 'start_date': 'icon-riqi',
+ 'priority_id': 'icon-youxian',
+ 'attachment': 'icon-xiugaibaobiaomoban'
+ }
+
+ useEffect(()=>{
+ setSpin(true);
+ let params = {
+ limit: limit,
+ page: page
+ }
+ getCommentList(docId, params).then(res=>{
+ if(res && res.data && res.data.data){
+ const {journals, total_comment_journals_count, total_count} = res.data.data;
+ if(category === 'all'){
+ const array = [];
+ let start = undefined;
+ let isJournalCount = 0;
+ journals.map((item, index)=>{
+ !isJournalCount && (start = index)
+ item.is_journal_detail && (isJournalCount++)
+ if(!item.is_journal_detail && isJournalCount < 10){
+ isJournalCount = 0;
+ return
+ }
+ if(isJournalCount >= 10 && (!item.is_journal_detail || journals.length-1 === index)){
+ array.push({start, count: isJournalCount});
+ isJournalCount = 0;
+ }
+ })
+ array.map((item, i)=>{
+ journals[item.start].numCount = item.count-1;
+ for (let index = 0; index < item.count; index++) {
+ journals[item.start+index].start = journals[item.start].id;
+ journals[item.start+index].closeAndSpan = true;
+ }
+ })
+ }
+ setTotalCount(total_count);
+ setJournalsCount(total_comment_journals_count);
+ setJournals(journals);
+ setSpin(false)
+ }
+ })
+ }, [reload, category, page])
+
+ function commentCtx(v){
+ return ;
+ };
+
+ // 删除评论内容
+ function deleteCommentFunc(id){
+ deleteComment(docId, id).then(res=>{
+ if(res && res.data && !res.data.data.status){
+ reloadComment();
+ message.success('删除成功');
+ }
+ })
+ }
+
+ // markdown 取消操作
+ function cancelMd(){
+ setShowEdit(false);
+ }
+
+ return(
+
+ {/* 评论 */}
+
0 && 'pb15'}`}>
+
+
+
评论{ journalsCount > 0 && `(共${ journalsCount }条评论)` }
+
+
+ {/* 评论快速入口-仅有评论且登录时展示 */}
+ {login && category !== 'operate' && journalsCount > 0 &&
}
+ {/* 评论/操作日志 展示列表 */}
+
+
+ {journals && (journals.length > 0 && journals.map(item=>{return
+ {/* 评论 */}
+
+
})
+
+ {/* 判断是否是编辑状态 */}
+ {(showEdit === 2 && updateId === item.id) ?
:
+
+
+
+ {item.user.name}
+ {timeAgo(item.created_at)}
+
+ {login &&
+ {/* 平台管理员/仓库管理员/发布评论者/issue创建者 */}
+ {(admin || isManager || login === item.user.login || username === author) &&
0 ? '子评论也将被一起删除。' : ''}`}
+ okText="是"
+ cancelText="否"
+ onConfirm={() => deleteCommentFunc(item.id)}
+ >
+
+ }
+ {/* 仅评论者可修改 */}
+ {login === item.user.login &&
}
+
{setParentId(item.id); setReplyId(item.id); setShowEdit(3)}}>
+
}
+
+
{commentCtx(item.notes)}
+ {item && item.attachments && item.attachments.length > 0 &&
}
+
+
}
+ {showEdit === 3 && replyId === item.id &&
}
+ {/* 评论回复部分 */}
+ {item.children_journals.map(i =>{
+ return
+ {(showEdit === 4 && updateId === i.id) ?
:
+
+
+
})
+
{i.user.name}
+ {i.reply_user &&
回复}
+
{i.reply_user && i.reply_user.name}
+
{timeAgo(i.created_at)}
+
+ {login &&
+ {/* 平台管理员/仓库管理员/发布评论者/回复评论者/issue创建者 */}
+ {(admin || isManager || login === i.user.login || (i.reply_user && login === i.reply_user.login) || username === author) &&
deleteCommentFunc(i.id)}
+ >
+
+ }
+ {/* 仅回复评论者可修改 */}
+ {login === i.user.login &&
}
+
{setParentId(item.id);setReplyId(i.id); setShowEdit(5)}}>
+
+
+
}
+
+
{commentCtx(i.notes)}
+ {i && i.attachments && i.attachments.length > 0 &&
}
+
}
+ {showEdit === 5 && replyId === i.id &&
}
+
})}
+
+
}))}
+
+
+ {totalCount>limit &&
}
+ {/* 添加评论 */}
+ {category !== 'operate' &&
+ {login ? showEdit === 1 ?
: : }
+ }
+
+ )
+}
+export default IssueCommentList;
\ No newline at end of file
diff --git a/src/forge/Information/Component/comments/list.scss b/src/forge/Information/Component/comments/list.scss
new file mode 100644
index 000000000..7c548915a
--- /dev/null
+++ b/src/forge/Information/Component/comments/list.scss
@@ -0,0 +1,217 @@
+.typeActionBox{
+ display: flex;
+ align-items: center;
+ font-size: 16px;
+ .line {
+ width: 3px;
+ height: 14px;
+ background: var(--primary-color);
+ margin-right: 13px;
+ }
+}
+.commentUserImg{
+ height: 28px;
+ width: 28px;
+ border-radius: 50%;
+ object-fit: cover;
+}
+.issueCommentsBox{
+ .operationLog, .commentContentBox{
+ position: relative;
+ min-height: 62px;
+ display: flex;
+ >.flexCenter, >a{
+ z-index: 2;
+ }
+ &::before, &::after{
+ content: '';
+ width: 1px;
+ height: 50%;
+ position: absolute;
+ background: #eee;
+ left: 12px;
+ z-index: 1;
+ }
+ &::after{
+ background: #eee;
+ top: 50%;
+ }
+ }
+ .commentContentBox+.operationLog .operationCommentBor, .operationLog+.commentContentBox .commentOperationBor{
+ border-top: 1px solid #eee;
+ width: 98.5%;
+ position: absolute;
+ left: 12px;
+ }
+ .operationLog+.commentContentBox{
+ &>a, &>.commentContentRight{
+ margin-top: 25px;
+ }
+ }
+ .timeAgo{
+ color:#acb0bf;
+ }
+ .operationLog:last-child::after, .operationLog:first-child::before, .commentContentBox:last-child::after, &.justComment .commentContentBox::before, &.justComment .commentContentBox::after{
+ display: none;
+ }
+ .operationLog:first-child, .commentContentBox+.operationLog{
+ margin-top: -15px;
+ }
+ .commentContentBox:last-child::before{
+ height: 35%;
+ }
+ .flexCenter{
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+ .commentRenderHtml.markdown-body p{
+ font-size: 14px !important;
+ }
+ .commentReply{
+ padding: 15px 0 0 20px;
+ background-color: hsla(225, 31%, 95%, 0.41);
+ &>div{
+ padding-bottom: 5px;
+ }
+ &+.commentReply>div{
+ margin-top: -15px;
+ padding-top: 15px;
+ border-top: 1px dashed #eee;
+ }
+ }
+ .opBox{
+ justify-content: flex-start;
+ // flex: 1;
+ // width: 100%;
+ }
+ .commentContentBox{
+ display: flex;
+ align-items: flex-start;
+ }
+ .commentContentRight{
+ flex: 1;
+ background-color:#fafafc;
+ // border:1px solid var(--light-color-2);
+ border:1px solid rgba(42, 97, 255, 0.23);
+ border-radius:6px;
+ position: relative;
+ top: -6px;
+ padding: 10px 15px 16px;
+ width: 0;
+ &::before{
+ content: '';
+ display: block;
+ position: absolute;
+ top: 13px;
+ left: -14px;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+ font-size: 0;
+ line-height: 0;
+ border: 7px;
+ border-style: solid;
+ border-color: transparent rgba(42, 97, 255, 0.23) transparent transparent;
+ }
+ &::after{
+ content: '';
+ display: block;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+ font-size: 0;
+ line-height: 0;
+ border: 6px;
+ border-style: solid;
+ border-color: transparent #fafafc transparent transparent;
+ position: absolute;
+ top: 14px;
+ left: -11px;
+ }
+ }
+}
+.attachmentBox{
+ margin-top: -8px;
+}
+.color-grey-89{
+ color: #898d9d;
+ // &:hover {
+ // color: var(--primary-color);
+ // }
+}
+// 添加评论样式
+.unLoginComment{
+ height:58px;
+ line-height: 58px;
+ background-color:var(--more-light-color);
+ border-radius:4px;
+ color: rgba(84, 87, 103, 1);
+ .loginBtn{
+ color: var(--primary-color);
+ }
+}
+.quillFlagBox{
+ color: red;
+ margin-bottom: 5px !important;
+ height: 28px;
+}
+.addComments{
+ display: flex;
+ align-items: center;
+ background-color:var(--more-light-color);
+ border-radius:4px;
+ padding:7px 10px;
+ &>img{
+ height: 28px;
+ width: 28px;
+ border-radius: 50%;
+ margin-right: 13px;
+ }
+}
+.addCommentBox{
+ width: 100%;
+ height: 30px;
+ border: none;
+ &:focus {
+ border-color: var(--primary-color) !important;
+ }
+}
+.paginationIssueComment{
+ text-align: center;
+}
+.gotoComment{
+ // background-color:var(--more-light-color);
+ background-color:rgba(241, 243, 252, 0.55);
+ border-radius:4px;
+ color: rgba(172, 176, 191, 1);
+ padding: 8px 20px;
+ margin-top: -10px;
+ &>a{color: var(--primary-color);}
+}
+// .commentStyle {
+// &:hover {
+// border-color: var(--primary-color) !important;
+// }
+// }
+.colorButton {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ &:hover {
+ background-color: var(--light-color);
+ border-color: var(--primary-color);
+ }
+ &:focus {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ }
+}
+.colorButton2 {
+ &:hover {
+ border-color: var(--primary-color);
+ color: var(--light-color);
+ }
+ &:focus {
+ color: var(--primary-color);
+ }
+}
\ No newline at end of file
diff --git a/src/forge/Information/Pages/newsDetail.jsx b/src/forge/Information/Pages/newsDetail.jsx
index e625080bc..ac736791a 100644
--- a/src/forge/Information/Pages/newsDetail.jsx
+++ b/src/forge/Information/Pages/newsDetail.jsx
@@ -1,4 +1,4 @@
-import React,{ useState , useEffect } from 'react';
+import React,{ useState , useEffect, useRef } from 'react';
import { Badge, Breadcrumb , Divider, Spin } from 'antd';
import liulan from '../img/liulan.png';
import RenderHtml from '../../../components/render-html';
@@ -8,6 +8,7 @@ import { IsPC } from 'educoder';
import { tempConfig } from '../tempInfo';
import Acce from '../Component/mobile/accessory';
import { addMeta, setSeoMeta } from 'educoder';
+import CommentList from '../Component/comments/list'
function NewsDetail(props){
@@ -16,6 +17,7 @@ function NewsDetail(props){
const [ cmsDir , setCmsDir ] = useState(undefined);
const [ content , setContent]=useState(undefined);
const [ isSpin , setIsSpin]=useState(false);
+ const [ commentReload, setCommentReload] = useState(undefined);
const temp = props.temp;
const zonedetail = props.data;
@@ -76,6 +78,7 @@ function NewsDetail(props){
setIsSpin(false)
})
}
+
return(
{
@@ -120,6 +123,13 @@ function NewsDetail(props){
暂无详情~
}
+ {
+ // 审核通过才有评论
+ detail.auditStatus === '1' &&
+ {setCommentReload(Math.random())}}/>
+
+ }
+
}
diff --git a/src/forge/Information/api.js b/src/forge/Information/api.js
index 1dcdea4d7..fb4daeb67 100644
--- a/src/forge/Information/api.js
+++ b/src/forge/Information/api.js
@@ -252,4 +252,40 @@ export function updateMyResource(data) {
method: 'PUT',
data: data
});
+}
+
+// 评论相关
+// 评论列表
+export function getCommentList(id, params) {
+ return fetch({
+ url: `cms/doc/open/${ id }/journalList`,
+ method: 'GET',
+ params
+ })
+}
+
+// 新增评论
+export function addComment(id, data) {
+ return fetch({
+ url: `cms/docComment/${ id }`,
+ method: 'POST',
+ data: data
+ })
+}
+
+// 编辑评论
+export function editComment(id, data) {
+ return fetch({
+ url: `cms/docComment/${ id }/${ data.id }`,
+ method: 'PUT',
+ data: data
+ })
+}
+
+// 删除评论
+export function deleteComment(docId, id) {
+ return fetch({
+ url: `cms/docComment/${ docId }/${ id }`,
+ method: 'DELETE',
+ })
}
\ No newline at end of file
diff --git a/src/forge/Information/theme.scss b/src/forge/Information/theme.scss
index ecfc43a29..0a6cc1be3 100644
--- a/src/forge/Information/theme.scss
+++ b/src/forge/Information/theme.scss
@@ -4,6 +4,8 @@ html[data-theme="zone"] {
--more-light-color: rgba(70, 106, 255, 0.05);
--linear-back-color: linear-gradient(89.9deg,rgba(70, 106, 255, 0) 0%,rgba(70, 106, 255, 0.09) 100%);
--tag-back: rgba(70, 106, 255, 0.12);
+ --light-color-2: rgba(70,106,255,0.23);
+ --light-color-3: rgba(70,106,255,0.55);
}
html[data-theme="zone1"] {
--primary-color: #089f7f;
@@ -11,4 +13,6 @@ html[data-theme="zone1"] {
--light-color: rgba(7, 165, 131, 0.85);
--linear-back-color: linear-gradient(89.9deg,rgba(7, 165, 131, 0) 0%,rgba(7, 165, 131, 0.09) 100%);
--tag-back: rgba(142, 147, 161, 0.1);
+ --light-color-2: rgba(7, 165, 131, 0.23);
+ --light-color-3: rgba(7, 165, 131, 0.55);
}
\ No newline at end of file