diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index a34e8a511..5e78a465c 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -442,6 +442,7 @@ class Detail extends Component { .catch(error => { console.log(error); }); + !flag && this.props.showNpsModal("indexProject", 1); } // 点赞和取消点赞 @@ -460,6 +461,7 @@ class Detail extends Component { .catch(error => { console.log(error); }); + !flag && this.props.showNpsModal("indexProject", 2); } setWatchersCount = (count, is_watched) => { @@ -494,6 +496,7 @@ class Detail extends Component { } this.props.history.push(`/${current_user && current_user.login}/${result.data.identifier}`); this.props.showNotification(result.data.message); + this.props.showNpsModal("indexProject", 3); } this.setState({ forkSpin: false @@ -669,7 +672,7 @@ class Detail extends Component { urlFlag={urlFlag} showNotification={this.props.showNotification} current_user={current_user} - isManager={isManager} + showNpsModal={this.props.showNpsModal} /> } diff --git a/src/forge/Main/sub/DetailBanner.jsx b/src/forge/Main/sub/DetailBanner.jsx index 679f7aacb..9ef750918 100644 --- a/src/forge/Main/sub/DetailBanner.jsx +++ b/src/forge/Main/sub/DetailBanner.jsx @@ -5,9 +5,18 @@ import { numFormat } from 'educoder'; import QuitBox from './quit'; import axios from 'axios'; -function DetailBanner({ history,list , owner , projectsId ,showNotification , url , pathname , state , urlFlag , projectDetail , platform ,open_devops ,current_user, isManager }){ +function DetailBanner({ history,list , owner , projectsId ,showNotification , url , pathname , state , urlFlag , projectDetail , platform ,open_devops ,current_user, showNpsModal }){ const [ menuName , setMenuName ] = useState(undefined); const [ visible , setVisible ] = useState(false); + + useEffect(()=>{ + const {location} = history; + const {query} = location; + if(query && query.showNps){ + showNpsModal("createProject", 1); + } + },[]) + useEffect(()=>{ if(Array.isArray(list)){ // 没有资源库banner但是通过连接进资源库页面时 diff --git a/src/forge/Merge/MessageCount.js b/src/forge/Merge/MessageCount.js index 8fa5e3b55..e8bca6ada 100644 --- a/src/forge/Merge/MessageCount.js +++ b/src/forge/Merge/MessageCount.js @@ -50,6 +50,12 @@ class MessageCount extends Component { this.getDetail(); // this.clickBody(); + // 监听路由query传参,实现nps调研效果 + const {location, showNpsModal} = this.props; + const {query} = location; + if(query && query.showNps){ + showNpsModal("createPullRequest", 1); + } }; bindFootRef = (footRef) => { @@ -119,6 +125,7 @@ class MessageCount extends Component { }); console.log(error); }); + this.props.showNpsModal("auditPullRequest", 2); }; //合并请求 @@ -157,6 +164,7 @@ class MessageCount extends Component { }); console.log(error); }); + this.props.showNpsModal("auditPullRequest", 1); }; changtitlepr = (e) => { diff --git a/src/forge/Merge/merge_form.js b/src/forge/Merge/merge_form.js index b02b9a049..130e93bf9 100644 --- a/src/forge/Merge/merge_form.js +++ b/src/forge/Merge/merge_form.js @@ -168,7 +168,7 @@ class MergeForm extends Component { isSpin: false, }); const { pull_request_number } = result.data; - this.props.history.push(`/${owner}/${projectsId}/pulls/${pull_request_number}`); + this.props.history.push({pathname: `/${owner}/${projectsId}/pulls/${pull_request_number}`, query:{showNps: true}}); const { getDetail } = this.props; getDetail && getDetail(); } else { @@ -197,9 +197,8 @@ class MergeForm extends Component { this.setState({ isSpin: false, }); - this.props.history.push( - `/${owner}/${projectsId}/pulls/${mergeId}` - ); + // , query:{showNps: true} + this.props.history.push({pathname: `/${owner}/${projectsId}/pulls/${mergeId}`}); } else { this.setState({ isSpin: false, diff --git a/src/forge/New/Index.js b/src/forge/New/Index.js index 0898683f5..4e1fb100a 100644 --- a/src/forge/New/Index.js +++ b/src/forge/New/Index.js @@ -187,7 +187,6 @@ class Index extends Component { subMitFrom = () => { this.props.form.validateFieldsAndScroll((err, values) => { - console.log(values); if (!err) { this.setState({ isSpin: true @@ -212,7 +211,7 @@ class Index extends Component { }).then((result) => { if (result && result.data.id) { projectsType && projectsType !== "mirror" && this.props.showNotification(`项目创建成功!`); - this.props.history.push(`/${result.data.login}/${result.data.identifier}`); + this.props.history.push({pathname: `/${result.data.login}/${result.data.identifier}`, query:{showNps: true}}); } this.setState({ isSpin: false diff --git a/src/forge/Order/order_form.js b/src/forge/Order/order_form.js index a3452c348..3cb3f07f2 100644 --- a/src/forge/Order/order_form.js +++ b/src/forge/Order/order_form.js @@ -212,6 +212,7 @@ class order_form extends Component { this.props.history.push(`/${owner}/${projectsId}/issues/${result.data.id}`); const { getDetail } = this.props; getDetail && getDetail(); + this.props.showNpsModal("createIssue", 1); } this.setState({ isSpin: false, @@ -238,6 +239,7 @@ class order_form extends Component { this.props.showNotification("任务更新成功!"); const { getDetail } = this.props; getDetail && getDetail(); + this.props.showNpsModal("submitIssue", 1); } this.setState({ isSpin: false diff --git a/src/forge/Server/data.jsx b/src/forge/Server/data.jsx index fc6a87b4b..d0680e5e4 100644 --- a/src/forge/Server/data.jsx +++ b/src/forge/Server/data.jsx @@ -162,7 +162,7 @@ function Data(props) { repeatBranch={repeatBranch} />
- 重晴鸟代码溯源 + 重晴鸟代码溯源服务 {!operateTime && isManager && 新建分析}
@@ -170,7 +170,7 @@ function Data(props) { {operateTime &&
系统维护中
-
预计{operateTime}小时后代码溯源系统将恢复正常访问,给您带来不便,敬请谅解!
+
预计{operateTime}小时后代码溯源服务将恢复正常访问,给您带来不便,敬请谅解!
} { !operateTime && dataSource && dataSource.length > 0 && diff --git a/src/forge/Server/reposyncer/component/storeList.jsx b/src/forge/Server/reposyncer/component/storeList.jsx index d44de6766..7ef95fb05 100644 --- a/src/forge/Server/reposyncer/component/storeList.jsx +++ b/src/forge/Server/reposyncer/component/storeList.jsx @@ -35,14 +35,14 @@ function StoreList(props){ return
-
Reposyncer仓库同步 +
Reposyncer仓库同步服务 {storeDetail !== null && ?}
{/* 空数据 */} {!storeDetail &&
-

欢迎使用跨平台代码同步

-
跨平台代码同步提供跨托管平台的项目协同开发同步功能。支持用户在任何一个托管平台上的代码提交、代码推送、合并请求等操作自动同步至其他托管平台。不仅增加每个开源项目与开发者的流量,也使不同平台的开源项目维护与更新变得方便与快捷
+

欢迎使用跨平台代码同步服务

+
跨平台代码同步服务提供跨托管平台的项目协同开发同步功能。支持用户在任何一个托管平台上的代码提交、代码推送、合并请求等操作自动同步至其他托管平台。不仅增加每个开源项目与开发者的流量,也使不同平台的开源项目维护与更新变得方便与快捷
} diff --git a/src/forge/Team/New.jsx b/src/forge/Team/New.jsx index 7a0fe0433..9e8b5df00 100644 --- a/src/forge/Team/New.jsx +++ b/src/forge/Team/New.jsx @@ -6,7 +6,7 @@ import axios from 'axios'; const port = window.location.port; const hostname = window.location.hostname; export default Form.create()( - forwardRef(({ form , showNotification , history })=>{ + forwardRef(({ form , showNotification , history, showNpsModal })=>{ const [ image , setImage ] = useState(undefined); const [ imageFlag , setImageFlag] = useState(false); const [ descNum ,setDescNum ] = useState(0); @@ -50,6 +50,7 @@ export default Form.create()( if(result && result.data){ showNotification("组织创建成功!"); history.push(`/${result.data.name}`); + showNpsModal("createOrganization", 1); } }).catch(error=>{}) } diff --git a/src/images/nps1.png b/src/images/nps1.png new file mode 100644 index 000000000..3a29afa5e Binary files /dev/null and b/src/images/nps1.png differ diff --git a/src/images/nps2.png b/src/images/nps2.png new file mode 100644 index 000000000..1f7e7291f Binary files /dev/null and b/src/images/nps2.png differ diff --git a/src/images/nps3.png b/src/images/nps3.png new file mode 100644 index 000000000..3bfcf7558 Binary files /dev/null and b/src/images/nps3.png differ diff --git a/src/images/nps4.png b/src/images/nps4.png new file mode 100644 index 000000000..4f6990c40 Binary files /dev/null and b/src/images/nps4.png differ diff --git a/src/images/nps5.png b/src/images/nps5.png new file mode 100644 index 000000000..3d4f0b6f9 Binary files /dev/null and b/src/images/nps5.png differ diff --git a/src/modules/modals/npsModal.jsx b/src/modules/modals/npsModal.jsx new file mode 100644 index 000000000..373815a2f --- /dev/null +++ b/src/modules/modals/npsModal.jsx @@ -0,0 +1,77 @@ +import { Button, Checkbox, Input, Modal } from 'antd'; +import axios from 'axios'; +import React, { useState } from 'react'; + +function NpmModal(props){ + const {npsActionType, npsActionId} = props; + const [activeGrade, setActiveGrade] = useState(undefined); + const [checkGroupValue, setCheckGroupValue] = useState(undefined); + const [inputValue, setInputValue] = useState(undefined); + const [success, setSuccess] = useState(false); + const [visible, setVisible] = useState(true); + // 提交按钮失效 + const [disabled, setDisabled] = useState(false); + const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + // 提交意见 + function submit(){ + setDisabled(true); + axios.post(`/nps.json`,{ + action_type: npsActionType, + action_id: npsActionId, + score: activeGrade, + memo:`${checkGroupValue && checkGroupValue.length !== 0 ? checkGroupValue.toString() + "。" : ''}${inputValue ? inputValue : ''}` + }).then((response) => { + if (response.data) { + setVisible(false); + setSuccess(true); + // 三秒之后自动关闭 + setTimeout(()=>{ + setSuccess(false); + },3000) + } + }).catch(function (error) { + console.log(error); + }); + } + return
+ 提交 : null} + > +
您向朋友或同事推荐GitLink平台的可能性有多大?
+
+ 不可能 + {arr.map(item=>{return {setActiveGrade(item)}}>{item}})} + 极有可能 +
+ {(activeGrade || activeGrade === 0) &&
+
您觉得以下哪些我们可以做的更好?(选填)
+ {setCheckGroupValue(e)}}> + 期待更加丰富的功能 + 部分功能不会用,希望有新手引导 + 已有的功能模块,用户体验需进一步提升 + 其他 + + {setInputValue(e.target.value);}}/> +
} +
+ {setSuccess(false)}} + className='npmSuccessModal' + width={450} + footer={null} + > +
+
提交成功
+
感谢您的反馈!
+
+
+
+} +export default NpmModal \ No newline at end of file diff --git a/src/modules/tpm/TPMIndex.css b/src/modules/tpm/TPMIndex.css index e0bb6ae25..da44feebc 100644 --- a/src/modules/tpm/TPMIndex.css +++ b/src/modules/tpm/TPMIndex.css @@ -332,4 +332,88 @@ body>.-task-title { .progress-container { flex: 1 0 0; margin-left: 20px; +} + +.npmModal .ant-modal-close-icon{ + font-size: 22px; +} +.npmModal .ant-modal-content, .npmSuccessModal .ant-modal-content{ + background-image:linear-gradient(359.37deg,#ebf3ff 0%,#f1f6ff 21.88%,#c1ceff 100%); + border:1.5px solid#ffffff; + min-height: 280px; +} +.npmModal .ant-modal-body, .npmModal .ant-modal-footer, .npmSuccessModal .ant-modal-body, .npmSuccessModal .ant-modal-footer{ + background-color: rgba(0, 0, 0, 0); +} +.npmModal .ant-modal-body, .npmSuccessModal .ant-modal-body{ + background-image: url('../../images/nps1.png'); + background-size: 100%; + background-repeat: no-repeat; + color:#202d40; +} +.npmSuccessModal .ant-modal-content{ + background-image:linear-gradient(359.37deg,#ebf3ff 0%,#f1f6ff 21.88%,#c1ceff 100%); +} +.npmSuccessModal .ant-modal-body{ + background-image: url('../../images/nps2.png'); + height: 300px; + text-align: center; +} +.npmModal .ant-modal-footer{ + border-top: none; + text-align: center; + padding-bottom: 30px; +} +.gradeBox{ + margin: 30px 0; +} +.oneGradeItem{ + width:36px; + height:36px; + border-radius: 50%; + line-height: 36px; + display: inline-block; + background-color:#d2ddff; + border:1px solid rgba(255, 255, 255, 0.61); + text-align: center; + font-weight: 700; + color: #334a6d; + background-size: 100% 100%; + cursor: pointer; +} +.npmModal .gradeCheckbox .ant-checkbox-wrapper{ + display: block; + margin: 0 0 15px 0; + font-size: 16px; + color: #3f4e64; +} +.gradeInput{ + background-color:rgba(255, 255, 255, 0.31) !important; + border:1px solid rgba(255, 255, 255, 0.66); + color:#202d40; + font-size:15px; + padding: 15px 18px; +} +.gradeInput:focus{ + background-color:rgba(255, 255, 255, 0.31) !important; +} +.grade1:hover, .grade2:hover, .grade3:hover, .grade1.active{ + background-image: url('../../images/nps5.png'); + color: rgba(255, 255, 255, 0); + background-repeat: no-repeat; +} +.grade2:hover, .grade2.active{ + background-image: url('../../images/nps4.png'); +} +.grade3:hover, .grade3.active{ + background-image: url('../../images/nps3.png'); +} +.oneGradeItem.active{ + color: rgba(255, 255, 255, 0); + background-repeat: no-repeat; +} +.successTips{margin-top: 135px;} +.npmSuccessModal .ant-modal-close-icon{ + font-size: 25px; + color: white; } \ No newline at end of file diff --git a/src/modules/tpm/TPMIndexHOC.js b/src/modules/tpm/TPMIndexHOC.js index 1fdf5f2a0..bfa61de96 100644 --- a/src/modules/tpm/TPMIndexHOC.js +++ b/src/modules/tpm/TPMIndexHOC.js @@ -8,6 +8,7 @@ import LoginDialog from '../login/LoginDialog'; import EducoderAccount from '../../forge/Component/EducoderAccount'; import ProfileModal from '../../forge/Component/ProfileModal/Index'; import SystemNotice from '../../forge/Component/NoticeModal/SystemNotice'; +import NpsModal from '../modals/npsModal'; export function TPMIndexHOC(WrappedComponent) { return class II extends React.Component { @@ -19,7 +20,6 @@ export function TPMIndexHOC(WrappedComponent) { tpmLoading: true, resLoading: true, Headertop: undefined, - isRender: false, globalLoading: false, dataquerys: {}, @@ -31,6 +31,9 @@ export function TPMIndexHOC(WrappedComponent) { showCP:false, showNotice:true, gopage: undefined, + npsModalVisible: false, + npsActionType: undefined, + npsActionId: undefined } } @@ -235,13 +238,43 @@ export function TPMIndexHOC(WrappedComponent) { }) } + showNpsModal = (type, index)=>{ + this.setState({ + npsActionType:type, + npsActionId: index + }) + const {current_user} = this.state; + current_user && current_user.nps && setTimeout(() => { + this.setState({npsModalVisible: true}) + }, 500) + } + + closeNpsModal(){ + axios.post(`/nps.json`,{ + action_type: 'close', + action_id: 1, + score: 0, + memo:'' + }).then((response) => { + if (response.data) { + // 关闭nps弹框之后需要重新请求一次get_user_info更新用户信息 + this.fetchUsers(); + this.setState({ + npsModalVisible: false + }) + } + }).catch(function (error) { + console.log(error); + }); + } render() { - let { isRender , current_user , giteaVisible , email , completeProfile , showCP , showNotice , publicNav , mygetHelmetapi } = this.state; + let { isRender , current_user , giteaVisible , email , completeProfile , showCP , showNotice , publicNav , mygetHelmetapi, npsModalVisible, npsActionType, npsActionId } = this.state; const common = { showLoginDialog: this.showLoginDialog, checkIfLogin: this.checkIfLogin, resetUserInfo:this.fetchUsers, - showCompeleteDialog:this.showCompeleteDialog + showCompeleteDialog:this.showCompeleteDialog, + showNpsModal: this.showNpsModal }; return (
@@ -263,6 +296,7 @@ export function TPMIndexHOC(WrappedComponent) { {...this.props} {...this.state} /> : ""} + {npsModalVisible && {this.closeNpsModal()}} npsActionType={npsActionType} npsActionId={npsActionId}/>}