diff --git a/package-lock.json b/package-lock.json index 9157e3cd1..69d6155f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1273,7 +1273,7 @@ }, "babel-cli": { "version": "6.26.0", - "resolved": "https://registry.npm.taobao.org/babel-cli/download/babel-cli-6.26.0.tgz", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", "dev": true, "requires": { @@ -1296,7 +1296,7 @@ "dependencies": { "chokidar": { "version": "1.7.0", - "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-1.7.0.tgz?cache=0&sync_timestamp=1602585438968&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-1.7.0.tgz", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "optional": true, @@ -1314,7 +1314,7 @@ }, "source-map": { "version": "0.5.7", - "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } @@ -1413,7 +1413,7 @@ }, "babel-helper-bindify-decorators": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-helper-bindify-decorators/download/babel-helper-bindify-decorators-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", "dev": true, "requires": { @@ -1476,7 +1476,7 @@ }, "babel-helper-explode-class": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-helper-explode-class/download/babel-helper-explode-class-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", "dev": true, "requires": { @@ -1676,7 +1676,7 @@ }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", - "resolved": "https://registry.npm.taobao.org/babel-plugin-syntax-async-generators/download/babel-plugin-syntax-async-generators-6.13.0.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", "dev": true }, @@ -1687,7 +1687,7 @@ }, "babel-plugin-syntax-decorators": { "version": "6.13.0", - "resolved": "https://registry.npm.taobao.org/babel-plugin-syntax-decorators/download/babel-plugin-syntax-decorators-6.13.0.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", "dev": true }, @@ -1723,7 +1723,7 @@ }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-plugin-transform-async-generator-functions/download/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", "dev": true, "requires": { @@ -1755,7 +1755,7 @@ }, "babel-plugin-transform-decorators": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-plugin-transform-decorators/download/babel-plugin-transform-decorators-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", "dev": true, "requires": { @@ -2060,7 +2060,7 @@ }, "babel-plugin-transform-runtime": { "version": "6.23.0", - "resolved": "https://registry.npm.taobao.org/babel-plugin-transform-runtime/download/babel-plugin-transform-runtime-6.23.0.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", "requires": { "babel-runtime": "^6.22.0" @@ -2077,7 +2077,7 @@ }, "babel-polyfill": { "version": "6.26.0", - "resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", "requires": { "babel-runtime": "^6.26.0", @@ -2087,7 +2087,7 @@ "dependencies": { "regenerator-runtime": { "version": "0.10.5", - "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz?cache=0&sync_timestamp=1595456367497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.10.5.tgz", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" } } @@ -2131,7 +2131,7 @@ }, "babel-preset-es2015": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-preset-es2015/download/babel-preset-es2015-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", "dev": true, "requires": { @@ -2179,7 +2179,7 @@ }, "babel-preset-react": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-preset-react/download/babel-preset-react-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", "requires": { "babel-plugin-syntax-jsx": "^6.3.13", @@ -2212,7 +2212,7 @@ }, "babel-preset-stage-2": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-preset-stage-2/download/babel-preset-stage-2-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", "dev": true, "requires": { @@ -2224,7 +2224,7 @@ }, "babel-preset-stage-3": { "version": "6.24.1", - "resolved": "https://registry.npm.taobao.org/babel-preset-stage-3/download/babel-preset-stage-3-6.24.1.tgz", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", "dev": true, "requires": { @@ -3507,7 +3507,7 @@ }, "code-prettify": { "version": "0.1.0", - "resolved": "https://registry.npm.taobao.org/code-prettify/download/code-prettify-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/code-prettify/-/code-prettify-0.1.0.tgz", "integrity": "sha1-RocMyMGlDQm61TmzOpg9vUqjSx4=" }, "codemirror": { @@ -4885,7 +4885,7 @@ }, "dom-closest": { "version": "0.2.0", - "resolved": "https://registry.npm.taobao.org/dom-closest/download/dom-closest-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz", "integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=", "requires": { "dom-matches": ">=1.0.1" @@ -4929,7 +4929,7 @@ }, "dom-matches": { "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/dom-matches/download/dom-matches-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz", "integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw=" }, "dom-scroll-into-view": { @@ -5187,7 +5187,7 @@ }, "enquire.js": { "version": "2.1.6", - "resolved": "https://registry.npm.taobao.org/enquire.js/download/enquire.js-2.1.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenquire.js%2Fdownload%2Fenquire.js-2.1.6.tgz", + "resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz", "integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ=" }, "entities": { @@ -5706,7 +5706,7 @@ }, "eventlistener": { "version": "0.0.1", - "resolved": "https://registry.npm.taobao.org/eventlistener/download/eventlistener-0.0.1.tgz", + "resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz", "integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg=" }, "events": { @@ -8040,7 +8040,7 @@ }, "hammerjs": { "version": "2.0.8", - "resolved": "https://registry.npm.taobao.org/hammerjs/download/hammerjs-2.0.8.tgz", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" }, "handle-thing": { @@ -8881,7 +8881,7 @@ }, "immutable": { "version": "3.7.6", - "resolved": "https://registry.npm.taobao.org/immutable/download/immutable-3.7.6.tgz", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" }, "import-fresh": { @@ -10486,7 +10486,7 @@ }, "lodash.throttle": { "version": "4.1.1", - "resolved": "https://registry.npm.taobao.org/lodash.throttle/download/lodash.throttle-4.1.1.tgz", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" }, "lodash.uniq": { @@ -11673,7 +11673,7 @@ }, "output-file-sync": { "version": "1.1.2", - "resolved": "https://registry.npm.taobao.org/output-file-sync/download/output-file-sync-1.1.2.tgz", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", "dev": true, "requires": { @@ -19100,7 +19100,7 @@ }, "user-home": { "version": "1.1.1", - "resolved": "https://registry.npm.taobao.org/user-home/download/user-home-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", "dev": true }, @@ -19157,7 +19157,7 @@ }, "v8flags": { "version": "2.1.1", - "resolved": "https://registry.npm.taobao.org/v8flags/download/v8flags-2.1.1.tgz?cache=0&sync_timestamp=1590964281452&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fv8flags%2Fdownload%2Fv8flags-2.1.1.tgz", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { diff --git a/public/css/iconfont.css b/public/css/iconfont.css index cb32b1a9f..a15df586f 100644 --- a/public/css/iconfont.css +++ b/public/css/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 2340181 */ - src: url('iconfont.woff2?t=1627870211301') format('woff2'), - url('iconfont.woff?t=1627870211301') format('woff'), - url('iconfont.ttf?t=1627870211301') format('truetype'); + src: url('iconfont.woff2?t=1628841816999') format('woff2'), + url('iconfont.woff?t=1628841816999') format('woff'), + url('iconfont.ttf?t=1628841816999') format('truetype'); } .iconfont { @@ -13,6 +13,150 @@ -moz-osx-font-smoothing: grayscale; } +.icon-xinjian2:before { + content: "\e8b0"; +} + +.icon-xieyiicon:before { + content: "\e870"; +} + +.icon-neicunicon:before { + content: "\e891"; +} + +.icon-zishuwenjian_icon:before { + content: "\e8a6"; +} + +.icon-dianzan_icon:before { + content: "\e8ba"; +} + +.icon-quxiaoguanzhu:before { + content: "\e8bb"; +} + +.icon-daimakuicon:before { + content: "\e8a9"; +} + +.icon-zhuyeicon:before { + content: "\e884"; +} + +.icon-biaoqianicon:before { + content: "\e882"; +} + +.icon-a-bianji:before { + content: "\e883"; +} + +.icon-cangkushezhiicon:before { + content: "\e885"; +} + +.icon-fuzhiicon:before { + content: "\e886"; +} + +.icon-lianjieicon:before { + content: "\e887"; +} + +.icon-hebingqingqiuicon:before { + content: "\e888"; +} + +.icon-lichengbeiicon:before { + content: "\e889"; +} + +.icon-gongzuoliuicon:before { + content: "\e88a"; +} + +.icon-dongtaiicon:before { + content: "\e88b"; +} + +.icon-morendianzan_icon:before { + content: "\e88e"; +} + +.icon-muluicon:before { + content: "\e894"; +} + +.icon-a-shezhi:before { + content: "\e899"; +} + +.icon-wenjian5:before { + content: "\e89a"; +} + +.icon-tijiaoicon:before { + content: "\e89e"; +} + +.icon-morenguanzhu_ICON:before { + content: "\e89f"; +} + +.icon-wenjianjia3:before { + content: "\e8a2"; +} + +.icon-xialaanniu1:before { + content: "\e8a4"; +} + +.icon-zuohuaicon:before { + content: "\e8b5"; +} + +.icon-master_icon:before { + content: "\e8b6"; +} + +.icon-morenfuke_icon:before { + content: "\e8b7"; +} + +.icon-a-wikiicon:before { + content: "\e8b8"; +} + +.icon-yixiuicon:before { + content: "\e8b9"; +} + +.icon-suofang:before { + content: "\e87f"; +} + +.icon-fangdaicon:before { + content: "\e881"; +} + +.icon-sousuo_icon1:before { + content: "\e873"; +} + +.icon-huanying_icon:before { + content: "\e878"; +} + +.icon-wenjianjia2:before { + content: "\e879"; +} + +.icon-shanchuicon1:before { + content: "\e87a"; +} + .icon-qingqiuicon:before { content: "\e871"; } @@ -49,10 +193,6 @@ content: "\e898"; } -.icon-xialaanniu_icon:before { - content: "\e89a"; -} - .icon-weixuanzhongqingqiuicon:before { content: "\e89b"; } @@ -61,10 +201,6 @@ content: "\e8a1"; } -.icon-xuanzhongxiangyingicon:before { - content: "\e8a2"; -} - .icon-xuanzhongfenzhiicon:before { content: "\e8a3"; } @@ -81,18 +217,6 @@ content: "\e8af"; } -.icon-xinzengmulu_xuantingicon:before { - content: "\e884"; -} - -.icon-xinzengyemian_morenicon:before { - content: "\e885"; -} - -.icon-zhankai_morenicon:before { - content: "\e889"; -} - .icon-shanchu_tc_icon:before { content: "\e88c"; } @@ -101,26 +225,14 @@ content: "\e88d"; } -.icon-xinzengyemian_shubiaodianjiicon:before { - content: "\e88e"; -} - .icon-daorumoban_icon:before { content: "\e86f"; } -.icon-daochu_xuanfu:before { - content: "\e870"; -} - .icon-cuowu:before { content: "\e872"; } -.icon-chenggong1:before { - content: "\e873"; -} - .icon-gengduo_icon:before { content: "\e874"; } @@ -137,18 +249,6 @@ content: "\e877"; } -.icon-a-lajitong_icon3x:before { - content: "\e878"; -} - -.icon-shouqi_morenicon:before { - content: "\e879"; -} - -.icon-huanying_icon:before { - content: "\e87a"; -} - .icon-sousuo_shanchuicon:before { content: "\e87b"; } @@ -161,22 +261,10 @@ content: "\e87e"; } -.icon-wenjianjia_icon:before { - content: "\e87f"; -} - .icon-xialaanniu:before { content: "\e880"; } -.icon-xinzengmulu_morenicon:before { - content: "\e882"; -} - -.icon-xinzengmulu_shubiaodianjiicon:before { - content: "\e883"; -} - .icon-erciqueren_icon:before { content: "\e867"; } diff --git a/public/css/iconfont.js b/public/css/iconfont.js index 55eeef19b..94af421b3 100644 --- a/public/css/iconfont.js +++ b/public/css/iconfont.js @@ -1 +1 @@ -!function(c){var l,a,h,i,o,z='',t=(t=document.getElementsByTagName("script"))[t.length-1].getAttribute("data-injectcss"),p=function(c,l){l.parentNode.insertBefore(c,l)};if(t&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}function v(){o||(o=!0,h())}function m(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(m,50)}v()}l=function(){var c,l;(l=document.createElement("div")).innerHTML=z,z=null,(c=l.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",l=c,(c=document.body).firstChild?p(l,c.firstChild):c.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),l()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(h=l,i=c.document,o=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,v())})}(window); \ No newline at end of file +!function(c){var l,a,h,i,o,z='',t=(t=document.getElementsByTagName("script"))[t.length-1].getAttribute("data-injectcss"),p=function(c,l){l.parentNode.insertBefore(c,l)};if(t&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}function v(){o||(o=!0,h())}function m(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(m,50)}v()}l=function(){var c,l;(l=document.createElement("div")).innerHTML=z,z=null,(c=l.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",l=c,(c=document.body).firstChild?p(l,c.firstChild):c.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),l()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(h=l,i=c.document,o=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,v())})}(window); diff --git a/public/css/iconfont.json b/public/css/iconfont.json index 2342c7975..7f25b322f 100644 --- a/public/css/iconfont.json +++ b/public/css/iconfont.json @@ -5,6 +5,258 @@ "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "23572260", + "name": "新建", + "font_class": "xinjian2", + "unicode": "e8b0", + "unicode_decimal": 59568 + }, + { + "icon_id": "23567674", + "name": "协议icon", + "font_class": "xieyiicon", + "unicode": "e870", + "unicode_decimal": 59504 + }, + { + "icon_id": "23567675", + "name": "内存icon", + "font_class": "neicunicon", + "unicode": "e891", + "unicode_decimal": 59537 + }, + { + "icon_id": "23567676", + "name": "自述文件_icon", + "font_class": "zishuwenjian_icon", + "unicode": "e8a6", + "unicode_decimal": 59558 + }, + { + "icon_id": "23492900", + "name": "点赞_icon", + "font_class": "dianzan_icon", + "unicode": "e8ba", + "unicode_decimal": 59578 + }, + { + "icon_id": "23492901", + "name": "取消关注", + "font_class": "quxiaoguanzhu", + "unicode": "e8bb", + "unicode_decimal": 59579 + }, + { + "icon_id": "23473151", + "name": "代码库icon", + "font_class": "daimakuicon", + "unicode": "e8a9", + "unicode_decimal": 59561 + }, + { + "icon_id": "23473104", + "name": "主页icon", + "font_class": "zhuyeicon", + "unicode": "e884", + "unicode_decimal": 59524 + }, + { + "icon_id": "23472253", + "name": "标签icon", + "font_class": "biaoqianicon", + "unicode": "e882", + "unicode_decimal": 59522 + }, + { + "icon_id": "23472254", + "name": "编 辑", + "font_class": "a-bianji", + "unicode": "e883", + "unicode_decimal": 59523 + }, + { + "icon_id": "23472256", + "name": "仓库设置icon", + "font_class": "cangkushezhiicon", + "unicode": "e885", + "unicode_decimal": 59525 + }, + { + "icon_id": "23472257", + "name": "复制icon", + "font_class": "fuzhiicon", + "unicode": "e886", + "unicode_decimal": 59526 + }, + { + "icon_id": "23472258", + "name": "链接icon", + "font_class": "lianjieicon", + "unicode": "e887", + "unicode_decimal": 59527 + }, + { + "icon_id": "23472259", + "name": "合并请求icon", + "font_class": "hebingqingqiuicon", + "unicode": "e888", + "unicode_decimal": 59528 + }, + { + "icon_id": "23472260", + "name": "里程碑icon", + "font_class": "lichengbeiicon", + "unicode": "e889", + "unicode_decimal": 59529 + }, + { + "icon_id": "23472261", + "name": "工作流icon", + "font_class": "gongzuoliuicon", + "unicode": "e88a", + "unicode_decimal": 59530 + }, + { + "icon_id": "23472262", + "name": "动态icon", + "font_class": "dongtaiicon", + "unicode": "e88b", + "unicode_decimal": 59531 + }, + { + "icon_id": "23472263", + "name": "默认点赞_icon", + "font_class": "morendianzan_icon", + "unicode": "e88e", + "unicode_decimal": 59534 + }, + { + "icon_id": "23472265", + "name": "目录icon", + "font_class": "muluicon", + "unicode": "e894", + "unicode_decimal": 59540 + }, + { + "icon_id": "23472267", + "name": "设 置", + "font_class": "a-shezhi", + "unicode": "e899", + "unicode_decimal": 59545 + }, + { + "icon_id": "23472268", + "name": "文件", + "font_class": "wenjian5", + "unicode": "e89a", + "unicode_decimal": 59546 + }, + { + "icon_id": "23472269", + "name": "提交icon", + "font_class": "tijiaoicon", + "unicode": "e89e", + "unicode_decimal": 59550 + }, + { + "icon_id": "23472270", + "name": "默认关注_ICON", + "font_class": "morenguanzhu_ICON", + "unicode": "e89f", + "unicode_decimal": 59551 + }, + { + "icon_id": "23472271", + "name": "文件夹", + "font_class": "wenjianjia3", + "unicode": "e8a2", + "unicode_decimal": 59554 + }, + { + "icon_id": "23472272", + "name": "下拉按钮", + "font_class": "xialaanniu1", + "unicode": "e8a4", + "unicode_decimal": 59556 + }, + { + "icon_id": "23472276", + "name": "左滑icon", + "font_class": "zuohuaicon", + "unicode": "e8b5", + "unicode_decimal": 59573 + }, + { + "icon_id": "23472277", + "name": "master_icon", + "font_class": "master_icon", + "unicode": "e8b6", + "unicode_decimal": 59574 + }, + { + "icon_id": "23472278", + "name": "默认复刻_icon", + "font_class": "morenfuke_icon", + "unicode": "e8b7", + "unicode_decimal": 59575 + }, + { + "icon_id": "23472279", + "name": "wiki icon", + "font_class": "a-wikiicon", + "unicode": "e8b8", + "unicode_decimal": 59576 + }, + { + "icon_id": "23472280", + "name": "易修icon", + "font_class": "yixiuicon", + "unicode": "e8b9", + "unicode_decimal": 59577 + }, + { + "icon_id": "23436350", + "name": "缩放", + "font_class": "suofang", + "unicode": "e87f", + "unicode_decimal": 59519 + }, + { + "icon_id": "23436351", + "name": "放大icon", + "font_class": "fangdaicon", + "unicode": "e881", + "unicode_decimal": 59521 + }, + { + "icon_id": "23384231", + "name": "搜索_icon", + "font_class": "sousuo_icon1", + "unicode": "e873", + "unicode_decimal": 59507 + }, + { + "icon_id": "23384232", + "name": "欢迎_icon", + "font_class": "huanying_icon", + "unicode": "e878", + "unicode_decimal": 59512 + }, + { + "icon_id": "23384233", + "name": "文件夹", + "font_class": "wenjianjia2", + "unicode": "e879", + "unicode_decimal": 59513 + }, + { + "icon_id": "23384234", + "name": "删除icon", + "font_class": "shanchuicon1", + "unicode": "e87a", + "unicode_decimal": 59514 + }, { "icon_id": "23261798", "name": "请求icon", @@ -68,13 +320,6 @@ "unicode": "e898", "unicode_decimal": 59544 }, - { - "icon_id": "23144154", - "name": "下拉按钮_icon", - "font_class": "xialaanniu_icon", - "unicode": "e89a", - "unicode_decimal": 59546 - }, { "icon_id": "23144155", "name": "未选中请求icon", @@ -89,13 +334,6 @@ "unicode": "e8a1", "unicode_decimal": 59553 }, - { - "icon_id": "23144159", - "name": "选中响应icon", - "font_class": "xuanzhongxiangyingicon", - "unicode": "e8a2", - "unicode_decimal": 59554 - }, { "icon_id": "23144160", "name": "选中分支icon", @@ -124,27 +362,6 @@ "unicode": "e8af", "unicode_decimal": 59567 }, - { - "icon_id": "23046282", - "name": "新增目录_悬停icon", - "font_class": "xinzengmulu_xuantingicon", - "unicode": "e884", - "unicode_decimal": 59524 - }, - { - "icon_id": "23046283", - "name": "新增页面_默认icon", - "font_class": "xinzengyemian_morenicon", - "unicode": "e885", - "unicode_decimal": 59525 - }, - { - "icon_id": "23046287", - "name": "展开_默认icon", - "font_class": "zhankai_morenicon", - "unicode": "e889", - "unicode_decimal": 59529 - }, { "icon_id": "23046290", "name": "shanchu_tc_icon", @@ -159,13 +376,6 @@ "unicode": "e88d", "unicode_decimal": 59533 }, - { - "icon_id": "23046311", - "name": "新增页面_鼠标点击icon", - "font_class": "xinzengyemian_shubiaodianjiicon", - "unicode": "e88e", - "unicode_decimal": 59534 - }, { "icon_id": "23046244", "name": "导入模版_icon", @@ -173,13 +383,6 @@ "unicode": "e86f", "unicode_decimal": 59503 }, - { - "icon_id": "23046247", - "name": "导出_悬浮", - "font_class": "daochu_xuanfu", - "unicode": "e870", - "unicode_decimal": 59504 - }, { "icon_id": "23046252", "name": "错误", @@ -187,13 +390,6 @@ "unicode": "e872", "unicode_decimal": 59506 }, - { - "icon_id": "23046254", - "name": "成功", - "font_class": "chenggong1", - "unicode": "e873", - "unicode_decimal": 59507 - }, { "icon_id": "23046255", "name": "更多_icon", @@ -222,27 +418,6 @@ "unicode": "e877", "unicode_decimal": 59511 }, - { - "icon_id": "23046269", - "name": "垃圾桶_icon@3x", - "font_class": "a-lajitong_icon3x", - "unicode": "e878", - "unicode_decimal": 59512 - }, - { - "icon_id": "23046270", - "name": "收起_默认icon", - "font_class": "shouqi_morenicon", - "unicode": "e879", - "unicode_decimal": 59513 - }, - { - "icon_id": "23046271", - "name": "欢迎_icon", - "font_class": "huanying_icon", - "unicode": "e87a", - "unicode_decimal": 59514 - }, { "icon_id": "23046273", "name": "搜索_删除icon", @@ -264,13 +439,6 @@ "unicode": "e87e", "unicode_decimal": 59518 }, - { - "icon_id": "23046277", - "name": "文件夹_icon", - "font_class": "wenjianjia_icon", - "unicode": "e87f", - "unicode_decimal": 59519 - }, { "icon_id": "23046278", "name": "下拉按钮", @@ -278,20 +446,6 @@ "unicode": "e880", "unicode_decimal": 59520 }, - { - "icon_id": "23046280", - "name": "新增目录_默认icon", - "font_class": "xinzengmulu_morenicon", - "unicode": "e882", - "unicode_decimal": 59522 - }, - { - "icon_id": "23046281", - "name": "新增目录_鼠标点击icon", - "font_class": "xinzengmulu_shubiaodianjiicon", - "unicode": "e883", - "unicode_decimal": 59523 - }, { "icon_id": "22906287", "name": "二次确认_icon", diff --git a/public/css/iconfont.ttf b/public/css/iconfont.ttf index 5e5ec5c63..484348baf 100644 Binary files a/public/css/iconfont.ttf and b/public/css/iconfont.ttf differ diff --git a/public/css/iconfont.woff b/public/css/iconfont.woff index 1f2744da7..bfdd0b9cb 100644 Binary files a/public/css/iconfont.woff and b/public/css/iconfont.woff differ diff --git a/public/css/iconfont.woff2 b/public/css/iconfont.woff2 index bb7c16cfd..386dde005 100644 Binary files a/public/css/iconfont.woff2 and b/public/css/iconfont.woff2 differ diff --git a/src/App.js b/src/App.js index f59412c8c..e6f1fc3e8 100644 --- a/src/App.js +++ b/src/App.js @@ -82,10 +82,14 @@ const Search = Loadable({ loader: () => import('./modules/search/'), loading: Loading, }) +const WikiPreview = Loadable({ + loader: () => import('./forge/Wiki/Preview'), + loading: Loading, +}) const ProjectIndex = Loadable({ - loader: () => import("./forge/Index"), - loading: Loading, + loader: () => import("./forge/Index"), + loading: Loading, }); class App extends Component { constructor(props) { @@ -199,9 +203,16 @@ class App extends Component { this.Modifyloginvalue()}> - + + {/* wiki预览 */} + { + return () + } + } /> + {/*项目*/} + {/* 个人主页 */} { return () } - }> + }> ( personal && personal.length > 0 ? - - : - + + : + ) } /> diff --git a/src/common/DateUtil.js b/src/common/DateUtil.js index 859182e18..630b2d7d6 100644 --- a/src/common/DateUtil.js +++ b/src/common/DateUtil.js @@ -1,4 +1,5 @@ import moment from "moment"; +import { number } from "prop-types"; // 处理整点 半点 // 取传入时间往后的第一个半点 @@ -97,3 +98,40 @@ export function formatDuring(mss){ } return days + "天" + hours + "小时" + minutes + "分"; } + +/* + 返回:多久以前 + backDate:以前的某个日期 +*/ +export function timeAgo(backDate) { + try { + moment(backDate); + } catch (e) { + return; + } + if(typeof backDate ==='number'){ + backDate=backDate*1000 + }else{ + backDate= moment(backDate); + } + let time = new Date() - backDate; + var days = Math.floor(time / (1000 * 60 * 60 * 24)); + var hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60)); + var seconds = Math.floor((time % (1000 * 60 * 60)) / 1000); + if (time <= 0) { + return "刚刚"; + } + if (days) { + return days + "天前"; + } + if (hours) { + return hours + "小时前"; + } + if (minutes) { + return minutes + "分前"; + } + if (seconds) { + return seconds + "秒前"; + } +} \ No newline at end of file diff --git a/src/common/educoder.js b/src/common/educoder.js index 1fc868930..c6eaf176d 100644 --- a/src/common/educoder.js +++ b/src/common/educoder.js @@ -27,7 +27,7 @@ export { markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension, downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml } from './TextUtil' -export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds } from './DateUtil' +export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds ,timeAgo} from './DateUtil' export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil' diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index f6dc83e08..a0e5f335b 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -127,7 +127,15 @@ const Source = Loadable({ const DevIndex = Loadable({ loader: () => import('../DevOps/Index'), loading: Loading, -}) +}); +const Wiki = Loadable({ + loader: () => import('../Wiki/Index'), + loading: Loading, +}); +const WikiEdit = Loadable({ + loader: () => import('../Wiki/EditWiki'), + loading: Loading, +}); /** * permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外) */ @@ -151,6 +159,8 @@ function checkPathname(projectsId,owner,pathname){ name="devops" }else if(url.indexOf(`/source`)>-1){ name="source" + }else if(url.indexOf(`/wiki`)>-1){ + name="wiki" } } return name; @@ -557,6 +567,24 @@ class Detail extends Component { () => () } > + {/* wiki新增文件 */} + () + } + > + {/* wiki编辑文件 */} + () + } + > + {/* wiki */} + () + } + > {/* 工作流 */} { - menuName.map((item,key)=>{ + Array.isArray(menuName)&& menuName.map((item,key)=>{ return( - + { item.menu_name === "home" &&
  • @@ -65,6 +65,15 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
  • :"" } + { + item.menu_name === "wiki" && +
  • + + + Wiki + +
  • + } { item.menu_name === "devops" && platform ?
  • diff --git a/src/forge/Settings/Setting.js b/src/forge/Settings/Setting.js index 220a50158..ba6e7a5a7 100644 --- a/src/forge/Settings/Setting.js +++ b/src/forge/Settings/Setting.js @@ -14,6 +14,7 @@ const menu = [ {name:"代码库",index:"code"}, {name:"易修 (Issue)",index:"issues"}, {name:"合并请求",index:"pulls"}, + {name:"Wiki",index:"wiki"}, {name:"工作流(beta版)",index:"devops"}, {name:"资源库",index:"resources"}, {name:"里程碑",index:"versions"}, diff --git a/src/forge/Wiki/EditWiki.jsx b/src/forge/Wiki/EditWiki.jsx new file mode 100644 index 000000000..633bf02f8 --- /dev/null +++ b/src/forge/Wiki/EditWiki.jsx @@ -0,0 +1,223 @@ +import React, { useEffect, useCallback, useState } from 'react'; +import { Button, Checkbox, Form, Icon, Radio, Input, message } from 'antd'; +import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor"; +import DelModal from './components/ModalFun'; +import { weekModal, monthModal } from './components/config'; +import { getWiki, wikiPages, addWiki, updateWiki } from './api'; +import './Index.scss'; + + +export default Form.create()(({ form, history, showNotification, projectDetail, match, project }) => { + // const permission = projectDetail && projectDetail.permission !== "Reporter"; + const permission = projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter"; + + const { getFieldDecorator, validateFields, setFieldsValue } = form; + const [fileArrInit, setFileArrInit] = useState(null); + let projectsId = match.params.projectsId; + let owner = match.params.owner; + + let wikiName = history.location.pathname.split('/').pop(); + if (wikiName === 'add') { + wikiName = ''; + } + + const [content, setContent] = useState(undefined); + const [modal, setModal] = useState(false); + const [modalType, setModalType] = useState(); + + + useEffect(() => { + wikiName && getWiki({ + owner, + repo: projectsId, + pagename: wikiName, + projectId: project.id + }).then(res => { + if (res && res.data) { + setContent(res.data.md_content); + setFieldsValue({ + name: res.data.name, + content: res.data.md_content, + }); + } + }); + }, [owner, wikiName]); + + // 加载wiki列表 + useEffect(() => { + project && wikiPages({ + owner: owner, + repo: projectsId, + projectId: project.id + }).then(res => { + if (res && res.message === "200" && Array.isArray(res.data)) { + setFileArrInit(res.data); + } else { + setFileArrInit([]); + } + }); + }, [project]); + + const helper = useCallback( + (label, name, rules, widget, initialValue, rightComponent) => ( + + {getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)} + {rightComponent} + + ), []); + + + function onContentChange(value) { + setContent(value); + setFieldsValue({ + content: value + }); + }; + + // 保存wiki文件,包括新增和修改 + function saveFile() { + validateFields((err, values) => { + if (!err) { + let regEn = /[\[\]`\/:*?''<>|%-+_]/g; + if (regEn.test(values.name)) { + message.error('文件名不能有特殊字符'); + return; + } + if (wikiName) { + updateWiki({ + owner, + repo: projectsId, + projectId: project.id, + pagename: wikiName, + ...values, + commit_message: '', + }).then(res => dealRes(res)); + } else { + if (Array.isArray(fileArrInit)) { + for (const item of fileArrInit) { + if (item.name === values.name) { + message.error('不能与已有文件标题相同'); + return false; + } + } + } + addWiki({ + owner, + repo: projectsId, + projectId: project.id, + pagename: values.name, + ...values, + commit_message: '', + }).then(res => dealRes(res)); + } + } + }) + } + + function dealRes(res) { + if (res && res.message === "200") { + showNotification("操作成功"); + goBack(); + } else if (res && res.message === "500") { + message.error('请检查格式是否正确或文件名是否重复'); + } else { + showNotification(res.message || "操作失败"); + } + } + + function goBack() { + history.push(`/projects/${owner}/${projectsId}/wiki`); + } + + function changeModal(e) { + setModal(e.target.checked); + if (!e.target.checked) { + setModalType(); + } + } + + function changeModalType(e) { + let value = e.target.value; + if (!content) { + setModalContent(value); + return; + } + DelModal({ + title: '添加模版', + contentTitle: `您确定要添加“${value}”模板吗`, + content: `此操作会将“${value}”模板替换编辑栏内所有内容,请确认以防文件的丢失`, + okText: '确认添加', + onOk: () => { + setModalType(value); + setModal(true); + setModalContent(value); + } + }); + } + + function setModalContent(value) { + if (value === '周报') { + setContent(weekModal); + setFieldsValue({ + content: weekModal + }); + } else if (value === '月报') { + setContent(monthModal); + setFieldsValue({ + content: monthModal + }); + } + } + + + return ( +
    +
    + Wiki 编辑页面 +
    + +
    +

    标题

    + {helper( + "", + "name", + [ + { required: true, message: "请输入标题" }, + // { pattern: /[^`\[\]\/:*?''<>|%-+_]/g, message: '不允许部分特殊字符' } + ], + + )} + + + + {getFieldDecorator('content', { + rules: [{ required: true, message: "请输入wiki内容" }], + validateFirst: true + })()} + + + 添加模版 + + + 周报 + 月报 + + +
    + + {permission && } +
    + + ) +}) \ No newline at end of file diff --git a/src/forge/Wiki/Index.jsx b/src/forge/Wiki/Index.jsx new file mode 100644 index 000000000..ed5c48996 --- /dev/null +++ b/src/forge/Wiki/Index.jsx @@ -0,0 +1,298 @@ +import React, { useEffect, useCallback, useState } from 'react'; +import { Button, Dropdown, Icon, Input, Menu, Tooltip, Select, Upload, message, Spin } from 'antd'; +import { getImageUrl, timeAgo } from 'educoder'; +import cookie from 'react-cookies'; +// import Loading from "../../Loading"; +import DelModal from './components/ModalFun'; +import Welcome from './Welcome'; +import { wikiPages, getWiki, deleteWiki } from './api'; +import { httpUrl, TokenKey } from './fetch'; +import './Index.scss'; +import { isArray } from 'lodash'; +const Search = Input.Search; +const InputGroup = Input.Group; +const { Option } = Select; + +export default (props) => { + const { match, current_user, history, showNotification, project, projectDetail } = props; + // const permission = projectDetail && projectDetail.permission !== "Reporter"; + const permission = projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter"; + + let projectsId = match.params.projectsId; + let owner = match.params.owner; + + console.log(project); + + const [fileArrInit, setFileArrInit] = useState(null); + const [checkItem, setCheckItem] = useState({}); + const [itemDetail, setItemDetail] = useState({}); + + const [fileArr, setFileArr] = useState([]); + const [reload, setReload] = useState(); + + const [urlType, setUrlType] = useState('HTTPS'); + + // 加载wiki列表 + useEffect(() => { + project && wikiPages({ + owner: owner, + repo: projectsId, + projectId: project.id + }).then(res => { + if (res && res.message === "200" && isArray(res.data)) { + setFileArr(res.data); + setFileArrInit(res.data); + if (res.data.length) { + setCheckItem(res.data[0]); + }; + } else { + setFileArr([]); + setFileArrInit([]); + } + }); + }, [project, reload]) + + // 加载单个wiki详情,参数尽量用驼峰,此处由于后端太麻烦所以不标准 + useEffect(() => { + project && checkItem.name && getWiki({ + owner: owner, + repo: projectsId, + pagename: checkItem.name, + projectId: project.id + }).then(res => { + if (res && res.message === "200") { + setItemDetail(res.data); + } else { + showNotification("加载失败") + } + }); + }, [project, checkItem]); + + function changeSearchValue(e) { + let value = e.target.value; + let newFileArr = []; + for (const item of fileArrInit) { + if (item.name.indexOf(value) > -1) { + newFileArr.push(item); + } + } + setFileArr(newFileArr); + } + + // 删除wiki模态框 + function deleteFileModal(e, item) { + e.stopPropagation(); + DelModal({ + title: '删除页面', + contentTitle: `您确定要删除“${item.name}”此页面吗?`, + content: '此操作将删除该页面,请进行确认以防文件的丢失。', + onOk: () => { + deleteWiki({ + owner: owner, + repo: projectsId, + pagename: item.name, + projectId: project.id + }).then(res => { + if (res && res.message === "200") { + message.success('删除成功'); + setReload(Math.random()); + } else { + message.error('删除失败'); + } + }); + } + }); + } + + + function goUser(login) { + window.location.href = `/users/${login}`; + } + + // 复制链接 + const copyUrl = useCallback(() => { + let wikiUrl = document.getElementById("wikiUrl"); + wikiUrl.select(); + if (document.execCommand('copy')) { + document.execCommand('copy'); + } + message.success('复制成功'); + wikiUrl.blur(); + }, []) + + function addFile() { + history.push(`/projects/${owner}/${projectsId}/wiki/add`); + } + + function goEdit() { + history.push(`/projects/${owner}/${projectsId}/wiki/edit/${encodeURI(checkItem.name)}`); + } + + function preview() { + window.open(`/projects/${owner}/${projectsId}/wiki/preview/${encodeURI(project.name)}/${project.id}`); + } + + // 支持 Markdown,Html,Pdf格式文件 + const menu = ( + + { downloadWiki('markdown') }}> + Markdown + + { downloadWiki('html') }}> + HTML + + { downloadWiki('pdf') }}> + PDF + + + ); + + function downloadWiki(type) { + window.open(`${httpUrl}/api/wikiExport/wikiExport-wrapper?repoName=${projectsId}&owner=${owner}&type=${type}&projectName=${project.name}&projectId=${project.id}`); + } + + function beforeUpload(file) { + if (!['md', 'txt'].includes(file.name.split('.').pop())) { + message.error('只能上传md、txt文件'); + return false; + } + + let regEn = /[\[\]`\/:*?''<>|%-+_]/g; + if (regEn.test(file.name)) { + message.error('文件名不能有特殊字符'); + return; + } + + for (const item of fileArrInit) { + if (item.name === file.name) { + message.error('不能上传与已有文件相同文件名的文件'); + return false; + } + } + const isLt100M = file.size / 1024 / 1024 < 100; + if (!isLt100M) { + showNotification(`文件大小必须小于${100}MB!`); + } + return isLt100M; + } + + const uploadProps = { + name: 'multipartFile', + withCredentials: true, + action: `${httpUrl}/api/wikiExport/uploadWiki/${owner}/${projectsId}/${project && project.id}`, //?token=${sessionStorage.taskToken} + showUploadList: false, + headers: { + Authorization: cookie.load(TokenKey) || sessionStorage.taskToken, + }, + beforeUpload: beforeUpload, + onChange(info) { + if (info.file.status === 'uploading') { + console.log(info.file, info.fileList); + } + if (info.file.status === 'done') { + if (info.file.response.message === '200') { + message.success(`${info.file.name} 上传成功`); + setReload(Math.random()); + } else if (info.file.response.message === '500') { + let data = JSON.parse(info.file.response.data); + message.error(data && data.message ? data.message : '文件上传失败'); + } else { + message.error('文件上传失败'); + } + } else if (info.file.status === 'error') { + message.error(`${info.file.name} 上传失败`); + } + }, + }; + + return ( + < Spin spinning={!fileArrInit} className="opacitySpin"> + {fileArrInit && fileArrInit.length ? +
    +
    + + + { + permission ? + + : "Wiki文档" + } + +
    + { + permission && + + + + + + } + + + + +
    +
    + +
    +
    +
    + + + { + fileArr.map(item => { + return
    +
    { setCheckItem(item) }}> +
    + + {item.name} +
    + {permission && { deleteFileModal(e, item) }}>} +
    +
    + }) + } +
    + + + {checkItem.wiki_clone_link && + + + + + + } + +
    + +
    +
    +
    +

    {checkItem.name}

    + { goUser(current_user.login) }}> + {itemDetail.image_url && 头像} + {checkItem.commit ? checkItem.commit.author.name : ''} + + 上次修改于{checkItem.commit && timeAgo(checkItem.commit.author.when)} +
    + {permission && } +
    + +
    +
    +
    +
    + : + + } + + ) +} diff --git a/src/forge/Wiki/Index.scss b/src/forge/Wiki/Index.scss new file mode 100644 index 000000000..c571da25f --- /dev/null +++ b/src/forge/Wiki/Index.scss @@ -0,0 +1,381 @@ +$wikiColor: #466aff; +$primaryBtnHover: #6482ff; +body { + width: 100% !important; +} +.ant-spin-nested-loading > div > .ant-spin.opacitySpin{ + max-height: 100vh; + background: rgba(255,255,255,1); +} +.wiki-main { + width: 1200px; + min-height: 400px; + margin: 20px auto; + + .ant-btn-primary { + background-color: $wikiColor; + border-color: $wikiColor; + &:hover, + &:focus, + &:active { + background-color: $primaryBtnHover; + } + } + + .ant-btn-default:hover, + .ant-btn-default:active, + .ant-btn-default:focus { + background: #f3f4f6; + color: #333; + border-color: #d0d0d0; + } + + .wiki-head { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 20px; + height: 64px; + background: #fafcff; + box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.13); + border-radius: 4px; + border-bottom-left-radius: 0; + .ant-btn .anticon { + margin: 0 -3px 0 0; + } + } + + .head-title { + font-size: 20px; + color: #05101a; + line-height: 30px; + font-weight: 500; + + .anticon-right { + color: #666; + font-size: 0.9rem; + } + } + + .back-wiki { + color: $wikiColor; + cursor: pointer; + &:hover { + color: $primaryBtnHover; + } + } + + .head-log-middle { + width: 3rem; + height: 3rem; + margin-right: 0.35rem; + border-radius: 50%; + } + + .head-log-small { + width: 1.25rem; + height: 1.25rem; + margin-right: 0.35rem; + border-radius: 50%; + } + + .user-box { + font-size: 12px; + font-family: "PingFangSC-Medium"; + color: $wikiColor; + cursor: pointer; + &:hover { + color: $primaryBtnHover; + } + .head-log-small { + position: relative; + top: -2px; + } + } + + .time-ago { + font-size: 12px; + color: #333; + letter-spacing: 0; + line-height: 17px; + font-weight: 400; + font-family: "PingFangSC-Regular"; + } + + .has-error .ant-form-explain, + .has-error .ant-form-split { + position: absolute; + } + .wiki-nav { + max-height: 60vh; + .wiki-search { + padding: 0 14px; + .ant-input { + padding-left: 30px; + } + .ant-input-suffix { + left: 26px; + right: auto; + } + &:hover .ant-input, + &:focus .ant-input { + border-color: $wikiColor !important; + } + } + } + + .wiki-nav-parent { + width: 260px; + flex: none; + } + + .ant-form-item-children .ant-input:hover { + border-color: $wikiColor !important; + } + + .ant-checkbox-checked .ant-checkbox-inner { + background-color: $wikiColor; + border-color: $wikiColor; + } + .ant-radio-checked .ant-radio-inner, + .ant-radio-checked::after { + border-color: $wikiColor; + } + + .ant-radio-inner::after { + background-color: $wikiColor; + } + + .ant-radio-group { + display: block; + margin: 10px 0 0 30px; + } + + .ant-radio-wrapper:hover .ant-radio, + .ant-radio:hover .ant-radio-inner, + .ant-radio-input:focus + .ant-radio-inner { + border-color: $wikiColor; + } +} + +#wikiUrl:focus { + border-right: 1px solid #d9d9d9 !important; +} + +.wiki-body { + display: flex; +} + +.wiki-content { + flex: auto; + width: 75%; +} + +.wiki-content-detail { + padding: 0 20px; + word-break: break-all; +} + +.ant-input-group.ant-input-group-compact.copy-url { + display: flex; + margin-top: 20px; + .ant-select-selection__rendered { + margin: 0 14px 0 5px; + width: 3rem; + font-size: 12px; + } + .ant-select-arrow { + right: 4px; + } + .ant-input { + font-size: 12px; + font-family: "PingFangSC-Regular"; + color: #666; + letter-spacing: 0; + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-break: break-all; + } + + .copy-svg { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0 5px; + background: #fff; + font-size: 1rem !important; + border: 1px solid #d9d9d9; + border-left: 0; + color: $wikiColor; + cursor: pointer; + } +} + +.wiki-url-type { + .ant-select-dropdown-menu-item { + font-size: 12px; + } +} + +.wiki-nav { + min-height: 300px; + padding: 20px 0; + background: #ffffff; + border: 1px solid rgba(153, 153, 153, 0.22); + overflow-y: scroll; + flex: none; + color: #333; +} + +.wiki-nav-title { + display: flex; + justify-content: space-between; + align-items: center; + height: 50px; + padding: 0 10px 0 10px; + font-size: 14px; + letter-spacing: 0; + font-weight: 400; + font-family: "PingFangSC-Regular"; + border-bottom: 1px solid #eee; + line-height: 16px; + cursor: pointer; + + .delete-title-icon { + display: none; + } + + &:hover { + background-color: #fbfbfb; + .delete-title-icon { + display: inline-block; + } + } +} + +.wiki-nav-title-parent { + padding: 0 14px; + &:hover { + background: #fbfbfb; + } +} + +.wiki-nav-title.active { + color: $wikiColor; +} + +.wiki-content-head { + margin: 20px 0 20px 20px; + padding: 0 20px 20px 0; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #eee; +} + +.wiki-content-head-left { + width: 90%; +} + +.nav-title-left { + display: inline-flex; + max-width: 90%; + svg { + margin-right: 0.5rem; + flex: none; + } + .nav-title-left-text { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } +} + +.wiki-detail-title { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +// 预览页面样式文件 +.wiki-preview { + overflow-y: scroll; + height: 100%; + .wiki-body { + width: 90%; + } + .ant-btn-primary { + background-color: $wikiColor; + border-color: $wikiColor; + &:hover, + &:focus, + &:active { + background-color: $primaryBtnHover; + } + } + .preview-head { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 12rem 0 2rem; + width: 100%; + height: 80px; + background: rgb(39, 47, 76); + color: #fff; + } + + .preview-head-left { + display: inline-flex; + align-items: center; + font-size: 24px; + cursor: pointer; + + .icon-wendangyulan_icon { + font-size: 24px !important; + font-weight: 700; + } + } + + .preview-head-right { + display: flex; + + .copy-url { + margin-top: 0; + } + .copy-desc { + width: 6rem; + padding-top: 1px; + } + } + + .wiki-nav-title { + padding: 0 10px 0 40px; + } + .wiki-nav-title.active { + background-color: #f3f4f6; + } + + .wiki-content-head { + padding: 10px 20px 10px 20px; + } + + .wiki-nav { + padding: 20px 0; + width: 20vw; + border-bottom: 0; + height: 80vh; + } + .wiki-content-detail { + padding: 0 40px; + img { + max-width: 100%; + } + } + + .ant-btn:hover { + background: #f3f4f6; + color: #333; + border-color: #d0d0d0; + } +} diff --git a/src/forge/Wiki/Preview.jsx b/src/forge/Wiki/Preview.jsx new file mode 100644 index 000000000..20645246a --- /dev/null +++ b/src/forge/Wiki/Preview.jsx @@ -0,0 +1,157 @@ +import React, { useEffect, useCallback, useState } from 'react'; +import { Input, Button, Tooltip, Select, Dropdown, Icon, Menu, message } from 'antd'; +import { wikiPages, getWiki, } from './api'; +import { httpUrl } from './fetch'; +import './Index.scss'; +const InputGroup = Input.Group; +const { Option } = Select; + +export default (props) => { + + const { match, history, showNotification, project, projectDetail } = props; + const permission = projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter"; + + let projectsId = match.params.projectsId; + let owner = match.params.owner; + + let projectName = match.params.projectName; + let projectId = match.params.projectId; + + console.log('projectName:'); + console.log(projectName); + + const [checkItem, setCheckItem] = useState({}); + const [itemDetail, setItemDetail] = useState({}); + + const [fileArr, setFileArr] = useState([]); + const [urlType, setUrlType] = useState('HTTPS'); + + useEffect(() => { + projectsId && wikiPages({ + owner: owner, + repo: projectsId, + projectId: projectId, + }).then(res => { + if (res && res.message === "200") { + setFileArr(res.data); + if (res.data.length) { + setCheckItem(res.data[0]); + }; + } else { + showNotification("加载失败") + } + }); + }, [project]) + + + useEffect(() => { + projectsId && checkItem.name && getWiki({ + owner: owner, + repo: projectsId, + pagename: checkItem.name, + projectId: projectId, + }).then(res => { + if (res && res.message === "200") { + setItemDetail(res.data); + } else { + showNotification("加载失败") + } + }); + }, [project, checkItem]); + + const copyUrl = useCallback(() => { + let wikiUrl = document.getElementById("wikiUrl"); + wikiUrl.select(); + if (document.execCommand('copy')) { + document.execCommand('copy'); + } + message.success('复制成功'); + wikiUrl.blur(); + }, []); + + function goEdit() { + history.push(`/projects/${owner}/${projectsId}/wiki/edit/${checkItem.name}`); + } + + function goBack() { + history.push(`/projects/${owner}/${projectsId}/wiki`); + } + + // 支持 Markdown,Html,Pdf格式文件 + const menu = ( + + { downloadWiki('markdown') }}> + Markdown + + { downloadWiki('html') }}> + HTML + + { downloadWiki('pdf') }}> + PDF + + + ); + + function downloadWiki(type) { + window.open(`${httpUrl}/api/wikiExport/wikiExport-wrapper?repoName=${projectsId}&owner=${owner}&type=${type}&projectName=${projectName}&projectId=${projectId}`); + } + + + return ( +
    +
    +
    + + {projectName} +
    +
    + 克隆地址 + { + checkItem.wiki_clone_link && + + + + + + + } + + + + +
    +
    + + +
    +
    + { + fileArr.map(item => { + return
    { setCheckItem(item) }}> + + + {item.name} + +
    + }) + } + +
    + +
    +
    +

    {checkItem.name}

    + {permission && } +
    + +
    +
    +
    + + +
    + ) +} \ No newline at end of file diff --git a/src/forge/Wiki/Welcome/index.jsx b/src/forge/Wiki/Welcome/index.jsx new file mode 100644 index 000000000..78cd34e45 --- /dev/null +++ b/src/forge/Wiki/Welcome/index.jsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { Button } from 'antd'; +// import { addWiki } from '../api'; +import './index.scss'; + +export default ({ project, isManager, history, showNotification, match, reloadList }) => { + + let projectsId = match.params.projectsId; + let owner = match.params.owner; + + // function addFile() { + // addWiki({ + // owner, + // repo: projectsId, + // pagename: 'Home', + // name: 'Home', + // content: 'Welcome to the wiki!', + // commit_message: '', + // }).then(res => { + // if (res.message === "200") { + // reloadList(Math.random()); + // showNotification("创建成功"); + // } else { + // showNotification("创建失败"); + // } + // }); + // } + + function addFile() { + history.push(`/projects/${owner}/${projectsId}/wiki/add`); + } + + return ( +
    + +

    欢迎使用  + + {project && project.name} + +  Wiki

    +

    Wiki主要是您项目的产品设计、文档描述、注释等等

    +
    + + { + isManager ? + :

    该项目暂时没有创建Wiki

    + } +
    + ) +} \ No newline at end of file diff --git a/src/forge/Wiki/Welcome/index.scss b/src/forge/Wiki/Welcome/index.scss new file mode 100644 index 000000000..b931fa622 --- /dev/null +++ b/src/forge/Wiki/Welcome/index.scss @@ -0,0 +1,55 @@ +.welcome-main { + display: flex; + flex-flow: column nowrap; + justify-content: center; + align-items: center; + width: 1200px; + min-height: 400px; + padding: 20px; + margin: 20px auto; + background: rgba(250, 252, 255, 1); + font-family: "PingFangSC-Medium"; + border-radius: 4px; + border: 1px solid rgba(42, 97, 255, 0.23); + + .icon-huanying_icon { + font-size: 48px !important; + font-weight: 700; + } + + .welcome-title { + display: inline-flex; + align-items: center; + margin: 10px 0; + font-size: 26px; + color: #333333; + font-weight: 500; + } + + .wiki-title { + display: inline-block; + max-width: 20em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .welcome-content { + font-size: 14px; + color: #333333; + font-weight: 400; + } + + .wiki-line { + margin: 50px 0 40px; + width: 400px; + height: 1px; + background: #eeeeee; + } + + .welcome-des { + font-size: 16px; + color: #333333; + font-weight: 500; + } +} diff --git a/src/forge/Wiki/api.js b/src/forge/Wiki/api.js new file mode 100644 index 000000000..353383221 --- /dev/null +++ b/src/forge/Wiki/api.js @@ -0,0 +1,48 @@ +import fetch from './fetch'; +// import { notification } from 'antd'; + +// 获取wiki列表 +export function wikiPages(params) { + return fetch({ + url: '/api/wiki/wikiPages', + method: 'get', + params + }); +} + +// 获取单个wiki +export function getWiki(params) { + return fetch({ + url: '/api/wiki/getWiki', + method: 'get', + params + }); +} + +//新增wiki +export function addWiki(data) { + return fetch({ + url: '/api/wiki/createWiki', + method: 'post', + data: data + }); +} + +//更新wiki +export function updateWiki(data) { + return fetch({ + url: '/api/wiki/updateWiki', + method: 'PUT', + data: data + }); +} + +//删除wiki +export function deleteWiki(data) { + return fetch({ + url: '/api/wiki/deleteWiki', + method: 'DELETE', + data, + }); +} + diff --git a/src/forge/Wiki/components/FolderTree/index.js b/src/forge/Wiki/components/FolderTree/index.js new file mode 100644 index 000000000..bbcdb3906 --- /dev/null +++ b/src/forge/Wiki/components/FolderTree/index.js @@ -0,0 +1,244 @@ +import * as React from 'react'; +import classNames from 'classnames'; +import { Icon, Tree } from 'antd'; +import omit from 'omit.js'; +import debounce from 'lodash/debounce'; +import { conductExpandParent, convertTreeToEntities } from 'rc-tree/lib/util'; +import { polyfill } from 'react-lifecycles-compat'; +import { ConfigConsumer } from '../../../../../node_modules/antd/lib/config-provider'; +import { + calcRangeKeys, + getFullKeyList, + convertDirectoryKeysToNodes, + getFullKeyListByTreeData, +} from '../../../../../node_modules/antd/lib/tree/util'; + +import { FolderSvg, FolderExpandSvg, FileSvg } from '../../Svg'; +import './index.scss'; + + +function getIcon(props) { + // console.log(props); + // console.log(props.expanded); + const { isLeaf, expanded ,selected} = props; + if (isLeaf) { + return ; + } + return expanded ? : + // return +} + +class DirectoryTree extends React.Component { + static defaultProps = { + showIcon: true, + expandAction: 'click', + }; + + static getDerivedStateFromProps(nextProps) { + const newState = {}; + if ('expandedKeys' in nextProps) { + newState.expandedKeys = nextProps.expandedKeys; + } + if ('selectedKeys' in nextProps) { + newState.selectedKeys = nextProps.selectedKeys; + } + return newState; + } + + // state: DirectoryTreeState; + + // tree: Tree; + + // onDebounceExpand: (event: React.MouseEvent, node: AntTreeNode) => void; + + // Shift click usage + // lastSelectedKey?: string; + + // cachedSelectedKeys?: string[]; + + constructor(props) { + super(props); + + const { + defaultExpandAll, + defaultExpandParent, + expandedKeys, + defaultExpandedKeys, + children, + } = props; + const { keyEntities } = convertTreeToEntities(children); + + // Selected keys + this.state = { + selectedKeys: props.selectedKeys || props.defaultSelectedKeys || [], + }; + + // Expanded keys + if (defaultExpandAll) { + if (props.treeData) { + this.state.expandedKeys = getFullKeyListByTreeData(props.treeData); + } else { + this.state.expandedKeys = getFullKeyList(props.children); + } + } else if (defaultExpandParent) { + this.state.expandedKeys = conductExpandParent( + expandedKeys || defaultExpandedKeys, + keyEntities, + ); + } else { + this.state.expandedKeys = expandedKeys || defaultExpandedKeys; + } + + this.onDebounceExpand = debounce(this.expandFolderNode, 200, { + leading: true, + }); + } + + onExpand = (expandedKeys, info) => { + const { onExpand } = this.props; + + this.setUncontrolledState({ expandedKeys }); + + // Call origin function + if (onExpand) { + return onExpand(expandedKeys, info); + } + + return undefined; + }; + + onClick = (event, node) => { + const { onClick, expandAction } = this.props; + + // Expand the tree + if (expandAction === 'click') { + this.onDebounceExpand(event, node); + } + + if (onClick) { + onClick(event, node); + } + }; + + onDoubleClick = (event, node) => { + const { onDoubleClick, expandAction } = this.props; + + // Expand the tree + if (expandAction === 'doubleClick') { + this.onDebounceExpand(event, node); + } + + if (onDoubleClick) { + onDoubleClick(event, node); + } + }; + + onSelect = (keys, event) => { + const { onSelect, multiple, children } = this.props; + const { expandedKeys = [] } = this.state; + const { node, nativeEvent } = event; + const { eventKey = '' } = node.props; + + const newState = {}; + + // We need wrap this event since some value is not same + const newEvent = { + ...event, + selected: true, // Directory selected always true + }; + + // Windows / Mac single pick + const ctrlPick = nativeEvent.ctrlKey || nativeEvent.metaKey; + const shiftPick = nativeEvent.shiftKey; + + // Generate new selected keys + let newSelectedKeys; + if (multiple && ctrlPick) { + // Control click + newSelectedKeys = keys; + this.lastSelectedKey = eventKey; + this.cachedSelectedKeys = newSelectedKeys; + newEvent.selectedNodes = convertDirectoryKeysToNodes(children, newSelectedKeys); + } else if (multiple && shiftPick) { + // Shift click + newSelectedKeys = Array.from( + new Set([ + ...(this.cachedSelectedKeys || []), + ...calcRangeKeys(children, expandedKeys, eventKey, this.lastSelectedKey), + ]), + ); + newEvent.selectedNodes = convertDirectoryKeysToNodes(children, newSelectedKeys); + } else { + // Single click + newSelectedKeys = [eventKey]; + this.lastSelectedKey = eventKey; + this.cachedSelectedKeys = newSelectedKeys; + newEvent.selectedNodes = [event.node]; + } + newState.selectedKeys = newSelectedKeys; + + if (onSelect) { + onSelect(newSelectedKeys, newEvent); + } + + this.setUncontrolledState(newState); + }; + + setTreeRef = (node) => { + this.tree = node; + }; + + expandFolderNode = (event, node) => { + const { isLeaf } = node.props; + + if (isLeaf || event.shiftKey || event.metaKey || event.ctrlKey) { + return; + } + + // Get internal rc-tree + const internalTree = this.tree.tree; + + // Call internal rc-tree expand function + // https://github.com/ant-design/ant-design/issues/12567 + internalTree.onNodeExpand(event, node); + }; + + setUncontrolledState = (state) => { + const newState = omit(state, Object.keys(this.props)); + if (Object.keys(newState).length) { + this.setState(newState); + } + }; + + renderDirectoryTree = ({ getPrefixCls }) => { + const { prefixCls: customizePrefixCls, className, ...props } = this.props; + const { expandedKeys, selectedKeys } = this.state; + + const prefixCls = getPrefixCls('tree', customizePrefixCls); + const connectClassName = classNames(`${prefixCls}-directory`, className); + + return ( + + ); + }; + + render() { + return {this.renderDirectoryTree}; + } +} + +polyfill(DirectoryTree); + +export default DirectoryTree; diff --git a/src/forge/Wiki/components/FolderTree/index.scss b/src/forge/Wiki/components/FolderTree/index.scss new file mode 100644 index 000000000..f74cfaf93 --- /dev/null +++ b/src/forge/Wiki/components/FolderTree/index.scss @@ -0,0 +1,61 @@ +.hide-file-icon.ant-tree.ant-tree-directory { + li span.ant-tree-switcher { + display: none !important; + } + + // li[role="treeitem"]:hover > span.ant-tree-switcher, + // li.ant-tree-treenode-selected > span.ant-tree-switcher { + // z-index: 1000; + // display: inline-block !important; + // } + + .ant-tree-node-content-wrapper{ + display: inline-flex; + width: 100%; + } + + .tree-title-icon{ + display: none; + } + + .ant-tree-node-content-wrapper:hover .tree-title-icon{ + transition: all 0.3s; + display: inline-block; + } + + &.ant-tree.ant-tree-directory + > li.ant-tree-treenode-selected + > span.ant-tree-node-content-wrapper::before, + &.ant-tree.ant-tree-directory + .ant-tree-child-tree + > li.ant-tree-treenode-selected + > span.ant-tree-node-content-wrapper::before { + background: #fff; + margin-top: -3px; + } + + &.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper::before, + &.ant-tree.ant-tree-directory + .ant-tree-child-tree + > li + span.ant-tree-node-content-wrapper::before { + margin-top: -3px; + } + + > li span.ant-tree-node-content-wrapper.ant-tree-node-selected, + .ant-tree-child-tree + > li + span.ant-tree-node-content-wrapper.ant-tree-node-selected { + color: #2a61ff; + } + + + + .ant-tree-title{ + display: inline-flex; + justify-content:space-between; + flex: auto; + } +} + + diff --git a/src/forge/Wiki/components/Login/index.jsx b/src/forge/Wiki/components/Login/index.jsx new file mode 100644 index 000000000..9574a9a51 --- /dev/null +++ b/src/forge/Wiki/components/Login/index.jsx @@ -0,0 +1,44 @@ +import React, { useState } from 'react'; +import * as ReactDOM from 'react-dom'; +import LoginDialog from '../../../../modules/login/LoginDialog'; +import './index.scss'; + +// 使用函数调用删除组件 +export default function DelModal(props) { + const div = document.createElement('div'); + document.body.appendChild(div); + + function destroy() { + const unmountResult = ReactDOM.unmountComponentAtNode(div); + if (unmountResult && div.parentNode) { + div.parentNode.removeChild(div); + } + } + + function render() { + /** + * Sync render blocks React event. Let's make this async. + */ + setTimeout(() => { + ReactDOM.render( + + , + div, + ); + }); + } + + render(); +} + +function MyLoginDialog({afterClose}) { + const [isRender, setIsRender] = useState(true); + return ( + {setIsRender(false);afterClose()}} + /> + ) +} + + diff --git a/src/forge/Wiki/components/Login/index.scss b/src/forge/Wiki/components/Login/index.scss new file mode 100644 index 000000000..13d160665 --- /dev/null +++ b/src/forge/Wiki/components/Login/index.scss @@ -0,0 +1,56 @@ +.delete-modal { + .ant-modal-header { + padding: 9px 24px; + background: #f8f8f8; + border-bottom: 1px solid #eee; + } + .ant-modal-title { + text-align: left; + } + .ant-modal-close { + top: 0px !important; + } + .ant-modal-close-x { + font-size: 24px; + } + .ant-modal-body { + text-align: center; + } + .delete-title { + display: flex; + justify-content: center; + align-items: center; + margin: 2rem 0 1rem !important; + font-size: 16px; + color: #333; + letter-spacing: 0; + line-height: 29px; + font-weight: 400; + } + .red-circle { + align-self: flex-start; + color: #ca0002; + font-size: 1.5rem !important; + } + .delete-descibe { + font-size: 14px; + color: #666; + line-height: 33px; + font-weight: 400; + } + .ant-modal-footer { + padding: 2rem 0; + text-align: center; + border: 0; + .ant-btn { + width: 6rem; + } + } + .foot-submit { + margin-left: 3rem; + color: #df0002; + &:hover { + border-color: #df0002; + } + } +} \ No newline at end of file diff --git a/src/forge/Wiki/components/ModalFun/index.jsx b/src/forge/Wiki/components/ModalFun/index.jsx new file mode 100644 index 000000000..661eca31b --- /dev/null +++ b/src/forge/Wiki/components/ModalFun/index.jsx @@ -0,0 +1,149 @@ +import React, { useState } from 'react'; +import * as ReactDOM from 'react-dom'; +import { Modal, Button } from 'antd'; +import './index.scss'; + +// 使用函数调用删除组件 +export default function DelModal(props) { + renderModal({ ...props, type: 'delete' }) +} + +export function confirmModal(props) { + renderModal({ ...props, type: 'confirm' }) +} + +function renderModal(props) { + const type = props.type; + const div = document.createElement('div'); + document.body.appendChild(div); + + function destroy() { + const unmountResult = ReactDOM.unmountComponentAtNode(div); + if (unmountResult && div.parentNode) { + div.parentNode.removeChild(div); + } + } + + function modalType(type) { + if (type === 'delete') { + return + } else if (type === 'confirm') { + return + } else { + return + } + } + + function render() { + /** + * Sync render blocks React event. Let's make this async. + */ + setTimeout(() => { + ReactDOM.render( + modalType(type), + div, + ); + }); + } + render(); +} + +// 真正的删除组件 +function DeleteModal({ + onCancel, + onOk, + title, + contentTitle, + content, + afterClose, + okText, + cancelText, +}) { + + const [visible, setVisible] = useState(true); + + function onCancelModal() { + setVisible(false); + onCancel && onCancel() + } + + function onSuccess() { + setVisible(false); + onOk && onOk(); + } + + return ( + + {cancelText||'取消'} + , + , + ]} + > +
    +

    + + {contentTitle}

    +

    {content}

    +
    +
    + ) +} + +// 选择组件 +function ConfirmModal({ + onCancel, + onOk, + title, + contentTitle, + content, + okText, + cancelText, + afterClose, +}) { + + const [visible, setVisible] = useState(true); + + function onCancelModal() { + setVisible(false); + onCancel && onCancel() + } + + function onSuccess() { + setVisible(false); + onOk && onOk(); + } + + return ( + + {cancelText||'取消'} + , + , + ]} + > +
    + {contentTitle &&

    {contentTitle}

    } +

    {content}

    +
    +
    + ) +} diff --git a/src/forge/Wiki/components/ModalFun/index.scss b/src/forge/Wiki/components/ModalFun/index.scss new file mode 100644 index 000000000..a598d2bf0 --- /dev/null +++ b/src/forge/Wiki/components/ModalFun/index.scss @@ -0,0 +1,56 @@ +.myself-modal { + .ant-modal-header { + padding: 9px 24px; + background: #f8f8f8; + border-bottom: 1px solid #eee; + } + .ant-modal-title { + text-align: left; + } + .ant-modal-close { + top: 0px !important; + } + .ant-modal-close-x { + font-size: 24px; + } + .ant-modal-body { + text-align: center; + } + .delete-title { + display: flex; + justify-content: center; + align-items: center; + margin: 2rem 0 1rem !important; + font-size: 16px; + color: #333; + letter-spacing: 0; + line-height: 29px; + font-weight: 400; + } + .red-circle { + align-self: flex-start; + color: #ca0002; + font-size: 1.5rem !important; + } + .delete-descibe { + font-size: 14px; + color: #666; + line-height: 33px; + font-weight: 400; + } + .ant-modal-footer { + padding: 2rem 0; + text-align: center; + border: 0; + .ant-btn { + width: 6rem; + } + } + .foot-submit { + margin-left: 3rem; + color: #df0002; + &:hover { + border-color: #df0002; + } + } +} \ No newline at end of file diff --git a/src/forge/Wiki/components/config.js b/src/forge/Wiki/components/config.js new file mode 100644 index 000000000..bda413390 --- /dev/null +++ b/src/forge/Wiki/components/config.js @@ -0,0 +1,29 @@ +import { httpUrl } from '../fetch'; + +export const editorConfig = { + placeholder: '请输入', + uploadImgServer: httpUrl + '/busiAttachments/upload', + uploadFileName: 'file', + uploadImgHeaders: { + 'X-Requested-With': 'XMLHttpRequest' + }, + excludeMenus: [ + 'list', + 'todo', + 'emoticon', + 'video' + ], + uploadImgHooks: { + // 图片上传并返回了结果,想要自己把图片插入到编辑器中 + customInsert: function (insertImgFn, result) { + // insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可 + if (result && result.data && result.data.id) { + insertImgFn(`${httpUrl}/busiAttachments/view/${result.data.id}`); + } + } + }, +} + + +export const weekModal="| 工作项目 | 本周工作计划 | 本周完成情况 |下周计划 | 待协同事项 |\n| ------------ | ------------ | ------------ | ------------ | ------------ |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n\n 备注:"; +export const monthModal="|工作项目 | 工作内容 | 项目进度情况 | 问题列表及解决方案| 下月工作计划 | 遗留未解决的问题 |\n| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |\n| | | | | | |\n| | | | | | |\n| | | | | | |\n| | | | | | |\n\n 月度总结:"; diff --git a/src/forge/Wiki/fetch.js b/src/forge/Wiki/fetch.js new file mode 100644 index 000000000..ccb9676a2 --- /dev/null +++ b/src/forge/Wiki/fetch.js @@ -0,0 +1,106 @@ +import { notification ,message} from 'antd'; +import axios from 'axios'; +import cookie from 'react-cookies'; +import Login from './components/Login'; + +let actionUrl = ''; +if (window.location.href.indexOf('localhost') > -1) { + // actionUrl = 'http://117.50.100.12:8008'; + // actionUrl = 'http://192.168.31.74:8081'; + actionUrl = "https://test-search.trustie.net"; +} else if(window.location.href.indexOf('testforgeplus')>-1){ + actionUrl = "https://test-search.trustie.net"; + // actionUrl = 'https://testforgeplus.trustie.net'; + axios.defaults.withCredentials = true; +}else if (window.location.href.indexOf('wiki-api') > -1) { + actionUrl = "https://wiki-api.trustie.net"; + axios.defaults.withCredentials = true; +} + +export const httpUrl = actionUrl; +export const TokenKey = 'autologin_trustie'; + +// 创建axios实例 +const service = axios.create({ + baseURL: httpUrl, + timeout: 10000, // 请求超时时间 +}); + +// request拦截器 +service.interceptors.request.use(config => { + if (cookie.load(TokenKey)) { + console.log(cookie.load(TokenKey)); + config.headers['Authorization'] = cookie.load(TokenKey); // 让每个请求携带自定义token 请根据实际情况自行修改 + } + if (window.location.port === "3007") { + // 模拟token为登录用户 + const taskToken = sessionStorage.taskToken; + if (config.url.indexOf('?') === -1) { + config.url = `${config.url}?token=${taskToken}`; + } else { + config.url = `${config.url}&token=${taskToken}`; + } + } + return config; +}, error => { + // Do something with request error + console.log(error); // for debug + // Promise.reject(error); +}); +// respone拦截器 +service.interceptors.response.use( + response => { + const res = response||{}; + if (res.status === 400) { + message.error(res.data.message || '操作失败'); + return Promise.reject('error'); + } + if (res.status === 401) { + message.error(res.data.message || '登录信息已过期'); + return Promise.reject('error'); + } + if (res.status === 403) { + message.error(res.data.message || '无权限!'); + return Promise.reject('error'); + } + if (res.status === 40001) { + notification.open({ + message: "提示", + description: '账户或密码错误!', + }); + return Promise.reject('error'); + } + if (response.status !== 200 && res.status !== 200) { + notification.open({ + message: "提示", + description: res.message, + }); + } else { + return response.data; + } + }, + error => { + console.log(error); + let res = error.response||{}; + if (res.status === 400) { + message.error(res.data.message || '操作失败'); + return Promise.reject('error'); + } + if (res.status === 401) { + message.error(res.data.message || '登录信息已过期'); + Login(); + return Promise.reject('error'); + } + if (res.status === 403) { + message.error(res.data.message || '无权限!'); + return Promise.reject('error'); + } + notification.open({ + message: "提示", + description: error.message, + }); + return Promise.reject(error); + } +); + +export default service;