README.html 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
  6. <style type="text/css">
  7. body {
  8. font-family: Helvetica, arial, sans-serif;
  9. font-size: 14px;
  10. line-height: 1.6;
  11. padding-top: 10px;
  12. padding-bottom: 10px;
  13. background-color: white;
  14. padding: 30px; }
  15. body > *:first-child {
  16. margin-top: 0 !important; }
  17. body > *:last-child {
  18. margin-bottom: 0 !important; }
  19. a {
  20. color: #4183C4; }
  21. a.absent {
  22. color: #cc0000; }
  23. a.anchor {
  24. display: block;
  25. padding-left: 30px;
  26. margin-left: -30px;
  27. cursor: pointer;
  28. position: absolute;
  29. top: 0;
  30. left: 0;
  31. bottom: 0; }
  32. h1, h2, h3, h4, h5, h6 {
  33. margin: 20px 0 10px;
  34. padding: 0;
  35. font-weight: bold;
  36. -webkit-font-smoothing: antialiased;
  37. cursor: text;
  38. position: relative; }
  39. h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  40. background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==) no-repeat 10px center;
  41. text-decoration: none; }
  42. h1 tt, h1 code {
  43. font-size: inherit; }
  44. h2 tt, h2 code {
  45. font-size: inherit; }
  46. h3 tt, h3 code {
  47. font-size: inherit; }
  48. h4 tt, h4 code {
  49. font-size: inherit; }
  50. h5 tt, h5 code {
  51. font-size: inherit; }
  52. h6 tt, h6 code {
  53. font-size: inherit; }
  54. h1 {
  55. font-size: 28px;
  56. color: black; }
  57. h2 {
  58. font-size: 24px;
  59. border-bottom: 1px solid #cccccc;
  60. color: black; }
  61. h3 {
  62. font-size: 18px; }
  63. h4 {
  64. font-size: 16px; }
  65. h5 {
  66. font-size: 14px; }
  67. h6 {
  68. color: #777777;
  69. font-size: 14px; }
  70. p, blockquote, ul, ol, dl, li, table, pre {
  71. margin: 15px 0; }
  72. hr {
  73. background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;
  74. border: 0 none;
  75. color: #cccccc;
  76. height: 4px;
  77. padding: 0;
  78. }
  79. body > h2:first-child {
  80. margin-top: 0;
  81. padding-top: 0; }
  82. body > h1:first-child {
  83. margin-top: 0;
  84. padding-top: 0; }
  85. body > h1:first-child + h2 {
  86. margin-top: 0;
  87. padding-top: 0; }
  88. body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  89. margin-top: 0;
  90. padding-top: 0; }
  91. a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  92. margin-top: 0;
  93. padding-top: 0; }
  94. h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  95. margin-top: 0; }
  96. li p.first {
  97. display: inline-block; }
  98. li {
  99. margin: 0; }
  100. ul, ol {
  101. padding-left: 30px; }
  102. ul :first-child, ol :first-child {
  103. margin-top: 0; }
  104. dl {
  105. padding: 0; }
  106. dl dt {
  107. font-size: 14px;
  108. font-weight: bold;
  109. font-style: italic;
  110. padding: 0;
  111. margin: 15px 0 5px; }
  112. dl dt:first-child {
  113. padding: 0; }
  114. dl dt > :first-child {
  115. margin-top: 0; }
  116. dl dt > :last-child {
  117. margin-bottom: 0; }
  118. dl dd {
  119. margin: 0 0 15px;
  120. padding: 0 15px; }
  121. dl dd > :first-child {
  122. margin-top: 0; }
  123. dl dd > :last-child {
  124. margin-bottom: 0; }
  125. blockquote {
  126. border-left: 4px solid #dddddd;
  127. padding: 0 15px;
  128. color: #777777; }
  129. blockquote > :first-child {
  130. margin-top: 0; }
  131. blockquote > :last-child {
  132. margin-bottom: 0; }
  133. table {
  134. padding: 0;border-collapse: collapse; }
  135. table tr {
  136. border-top: 1px solid #cccccc;
  137. background-color: white;
  138. margin: 0;
  139. padding: 0; }
  140. table tr:nth-child(2n) {
  141. background-color: #f8f8f8; }
  142. table tr th {
  143. font-weight: bold;
  144. border: 1px solid #cccccc;
  145. margin: 0;
  146. padding: 6px 13px; }
  147. table tr td {
  148. border: 1px solid #cccccc;
  149. margin: 0;
  150. padding: 6px 13px; }
  151. table tr th :first-child, table tr td :first-child {
  152. margin-top: 0; }
  153. table tr th :last-child, table tr td :last-child {
  154. margin-bottom: 0; }
  155. img {
  156. max-width: 100%; }
  157. span.frame {
  158. display: block;
  159. overflow: hidden; }
  160. span.frame > span {
  161. border: 1px solid #dddddd;
  162. display: block;
  163. float: left;
  164. overflow: hidden;
  165. margin: 13px 0 0;
  166. padding: 7px;
  167. width: auto; }
  168. span.frame span img {
  169. display: block;
  170. float: left; }
  171. span.frame span span {
  172. clear: both;
  173. color: #333333;
  174. display: block;
  175. padding: 5px 0 0; }
  176. span.align-center {
  177. display: block;
  178. overflow: hidden;
  179. clear: both; }
  180. span.align-center > span {
  181. display: block;
  182. overflow: hidden;
  183. margin: 13px auto 0;
  184. text-align: center; }
  185. span.align-center span img {
  186. margin: 0 auto;
  187. text-align: center; }
  188. span.align-right {
  189. display: block;
  190. overflow: hidden;
  191. clear: both; }
  192. span.align-right > span {
  193. display: block;
  194. overflow: hidden;
  195. margin: 13px 0 0;
  196. text-align: right; }
  197. span.align-right span img {
  198. margin: 0;
  199. text-align: right; }
  200. span.float-left {
  201. display: block;
  202. margin-right: 13px;
  203. overflow: hidden;
  204. float: left; }
  205. span.float-left span {
  206. margin: 13px 0 0; }
  207. span.float-right {
  208. display: block;
  209. margin-left: 13px;
  210. overflow: hidden;
  211. float: right; }
  212. span.float-right > span {
  213. display: block;
  214. overflow: hidden;
  215. margin: 13px auto 0;
  216. text-align: right; }
  217. code, tt {
  218. margin: 0 2px;
  219. padding: 0 5px;
  220. white-space: nowrap;
  221. border: 1px solid #eaeaea;
  222. background-color: #f8f8f8;
  223. border-radius: 3px; }
  224. pre code {
  225. margin: 0;
  226. padding: 0;
  227. white-space: pre;
  228. border: none;
  229. background: transparent; }
  230. .highlight pre {
  231. background-color: #f8f8f8;
  232. border: 1px solid #cccccc;
  233. font-size: 13px;
  234. line-height: 19px;
  235. overflow: auto;
  236. padding: 6px 10px;
  237. border-radius: 3px; }
  238. pre {
  239. background-color: #f8f8f8;
  240. border: 1px solid #cccccc;
  241. font-size: 13px;
  242. line-height: 19px;
  243. overflow: auto;
  244. padding: 6px 10px;
  245. border-radius: 3px; }
  246. pre code, pre tt {
  247. background-color: transparent;
  248. border: none; }
  249. sup {
  250. font-size: 0.83em;
  251. vertical-align: super;
  252. line-height: 0;
  253. }
  254. kbd {
  255. display: inline-block;
  256. padding: 3px 5px;
  257. font-size: 11px;
  258. line-height: 10px;
  259. color: #555;
  260. vertical-align: middle;
  261. background-color: #fcfcfc;
  262. border: solid 1px #ccc;
  263. border-bottom-color: #bbb;
  264. border-radius: 3px;
  265. box-shadow: inset 0 -1px 0 #bbb
  266. }
  267. * {
  268. -webkit-print-color-adjust: exact;
  269. }
  270. @media screen and (min-width: 914px) {
  271. body {
  272. width: 854px;
  273. margin:0 auto;
  274. }
  275. }
  276. @media print {
  277. table, pre {
  278. page-break-inside: avoid;
  279. }
  280. pre {
  281. word-wrap: break-word;
  282. }
  283. }
  284. </style>
  285. <style type="text/css">
  286. /**
  287. * prism.js default theme for JavaScript, CSS and HTML
  288. * Based on dabblet (http://dabblet.com)
  289. * @author Lea Verou
  290. */
  291. code[class*="language-"],
  292. pre[class*="language-"] {
  293. color: black;
  294. background: none;
  295. text-shadow: 0 1px white;
  296. font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  297. text-align: left;
  298. white-space: pre;
  299. word-spacing: normal;
  300. word-break: normal;
  301. word-wrap: normal;
  302. line-height: 1.5;
  303. -moz-tab-size: 4;
  304. -o-tab-size: 4;
  305. tab-size: 4;
  306. -webkit-hyphens: none;
  307. -moz-hyphens: none;
  308. -ms-hyphens: none;
  309. hyphens: none;
  310. }
  311. pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
  312. code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
  313. text-shadow: none;
  314. background: #b3d4fc;
  315. }
  316. pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
  317. code[class*="language-"]::selection, code[class*="language-"] ::selection {
  318. text-shadow: none;
  319. background: #b3d4fc;
  320. }
  321. @media print {
  322. code[class*="language-"],
  323. pre[class*="language-"] {
  324. text-shadow: none;
  325. }
  326. }
  327. /* Code blocks */
  328. pre[class*="language-"] {
  329. padding: 1em;
  330. margin: .5em 0;
  331. overflow: auto;
  332. }
  333. :not(pre) > code[class*="language-"],
  334. pre[class*="language-"] {
  335. background: #f5f2f0;
  336. }
  337. /* Inline code */
  338. :not(pre) > code[class*="language-"] {
  339. padding: .1em;
  340. border-radius: .3em;
  341. white-space: normal;
  342. }
  343. .token.comment,
  344. .token.prolog,
  345. .token.doctype,
  346. .token.cdata {
  347. color: slategray;
  348. }
  349. .token.punctuation {
  350. color: #999;
  351. }
  352. .namespace {
  353. opacity: .7;
  354. }
  355. .token.property,
  356. .token.tag,
  357. .token.boolean,
  358. .token.number,
  359. .token.constant,
  360. .token.symbol,
  361. .token.deleted {
  362. color: #905;
  363. }
  364. .token.selector,
  365. .token.attr-name,
  366. .token.string,
  367. .token.char,
  368. .token.builtin,
  369. .token.inserted {
  370. color: #690;
  371. }
  372. .token.operator,
  373. .token.entity,
  374. .token.url,
  375. .language-css .token.string,
  376. .style .token.string {
  377. color: #a67f59;
  378. background: hsla(0, 0%, 100%, .5);
  379. }
  380. .token.atrule,
  381. .token.attr-value,
  382. .token.keyword {
  383. color: #07a;
  384. }
  385. .token.function {
  386. color: #DD4A68;
  387. }
  388. .token.regex,
  389. .token.important,
  390. .token.variable {
  391. color: #e90;
  392. }
  393. .token.important,
  394. .token.bold {
  395. font-weight: bold;
  396. }
  397. .token.italic {
  398. font-style: italic;
  399. }
  400. .token.entity {
  401. cursor: help;
  402. }
  403. </style>
  404. </head>
  405. <body>
  406. <h2 id="toc_0">Nicon</h2>
  407. <p>Nicon 是一个集图标上传、展示、使用于一身的字体图标管理平台,流程简单,符合日常开发使用习惯,适合企业在内部部署使用。采用 Iconfont 字体图标替换项目中图片图标的使用,以达到缩减体积、风格统一、提高开发效率等目的。若配合设计师使用,设计师可在平台上管理图标,复用图标,减少设计图标耗费的时间,而开发只负责使用设计师维护好的图标库,减少了与设计师的交流成本。</p>
  408. <h2 id="toc_1">优势</h2>
  409. <p>与其他字体图标管理平台相比,它拥有以下优势:</p>
  410. <ul>
  411. <li>使用流程简单,符合日常开发使用习惯,无需在审核管理流程中耗费时间</li>
  412. <li>部署简单,支持可视化配置部署,平台自带注册、登录功能,还有静态资源路由,只需数据库配置就可部署使用</li>
  413. <li>支持接入三方登录、资源上传到三方CDN服务器。使用更安全,资源更稳定</li>
  414. <li>支持导出资源多样化,符合多种使用场合,更有配套的导出工具<a href="https://github.com/bolin-L/nicon-toolkit">nicon-tookit</a>, 方便快捷</li>
  415. </ul>
  416. <h2 id="toc_2">结构设计图</h2>
  417. <p><img src="https://static.qilebaba.com/392e675423334a86a6c6ca7913d3f50e.png" alt="结构设计图"></p>
  418. <h2 id="toc_3">使用流程图</h2>
  419. <p><strong>使用流程图</strong></p>
  420. <p><img src="http://edu-image.nosdn.127.net/0a712d18-fd7c-40ea-94ef-ef43dd2a5d88.png?imageView&amp;quality=100" alt="结构设计图"></p>
  421. <p><strong>开发使用流程图</strong></p>
  422. <p><img src="http://edu-image.nosdn.127.net/2436a363-6a6d-401e-95ba-f45b2d51d263.jpeg" alt="开发使用流程"></p>
  423. <p><strong>设计师参与使用流程图</strong></p>
  424. <p><img src="http://edu-image.nosdn.127.net/99297908-a6e8-4340-8df5-0b0d65b54f07.jpeg" alt="开发使用流程"></p>
  425. <p>如果设计师与开发协同参与使用维护图标库,不仅使设计师可以有一个可视化管理字体图标的平台。还可以减少开发与设计的交流时间。</p>
  426. <h2 id="toc_4">服务安装部署</h2>
  427. <p><strong>系统要求</strong></p>
  428. <ul>
  429. <li>linux/unix/mac/windows</li>
  430. </ul>
  431. <p><strong>环境要求</strong></p>
  432. <ul>
  433. <li>nodejs v8.17.0(由于模块不兼容,node版本超过8之后就出现启动失败问题,需要整体升级)</li>
  434. <li>npm 6.13.4</li>
  435. <li>mogondb 3.2+</li>
  436. <li>redis 3.2+</li>
  437. </ul>
  438. <p>在启动工程之前,必须确保数据库已经启动,且已经把相应的数据库创建好。</p>
  439. <p>1、 克隆项目到本地|服务器</p>
  440. <div><pre><code class="language-none">git clone git@github.com:bolin-L/nicon.git</code></pre></div>
  441. <p>2、 进入到项目工程nicon安装依赖</p>
  442. <div><pre><code class="language-none">cd nicon &amp;&amp; npm install</code></pre></div>
  443. <p>3、运行启动命令</p>
  444. <div><pre><code class="language-none">npm run publish</code></pre></div>
  445. <p>这时服务基本启动完毕,数据库等其他信息的配置等配置前端静态资源之后再配置。服务默认监听的端口是4843</p>
  446. <h2 id="toc_5">前端静态资源部署</h2>
  447. <p>图标管理平台采用的是前后端完全分离的开发方式,前端代码放在独立的<a href="https://github.com/bolin-L/nicon-front">icon-front</a>。但是前端打包后的代码需要拷贝到服务端工程<code>nicon</code>的<code>/public/static</code>中,由服务端提供静态资源服务,如需要修改前端样式,按照以下步骤即可</p>
  448. <p>1、克隆前端项目到本地</p>
  449. <div><pre><code class="language-none">git clone git@github.com:bolin-L/nicon-front.git</code></pre></div>
  450. <p>2、进入到nicon-front工程,安装依赖</p>
  451. <div><pre><code class="language-none">cd nicon-front &amp;&amp; npm install </code></pre></div>
  452. <p>3、运行打包命令、打包输出到nicon-front/dist文件夹下</p>
  453. <div><pre><code class="language-none">npm run build</code></pre></div>
  454. <p>4、拷贝<code>dist</code>下的所有资源到服务端工程<code>nicon</code>的<code>public/static</code>下</p>
  455. <h2 id="toc_6">Nginx配置</h2>
  456. <div><pre><code class="language-none">server {
  457. listen 80;
  458. listen [::]:80;
  459. server_name icon.bolin.site;
  460. access_log /var/log/nginx/bolin_sites_icon.access.log main;
  461. error_log /var/log/nginx/bolin_sites_icon.error.log;
  462. # 配置异步接口请求到服务器
  463. location / {
  464. proxy_set_header X-Real-IP $remote_addr;
  465. proxy_set_header Host $http_host;
  466. proxy_pass http://127.0.0.1:4843;
  467. }
  468. }</code></pre></div>
  469. <p>配置到此,平台基本就可以运行起来使用了,浏览器访问<code>icon.bolin.site</code>就可以访问到首页</p>
  470. <h2 id="toc_7">数据库信息配置与三方服务接入</h2>
  471. <p>该平台在未配置任何数据库信息时就可以启动,但是访问之后会被重定向到<a href="http://icon.bolin.site/#/install">安装页面</a>进行数据库信息与三方服务脚本的配置。配置分三部分,根据自己的需求来决定具体要配置哪部分。</p>
  472. <p><strong>启动数据配置</strong></p>
  473. <p>启动数据配置基本是<code>mongoDB</code>与<code>redis</code>数据库信息,且是必须。当然如果接入第三方服务时需要额外的配置也可以通过此页面来配置,添加的所有变量都可以从<code>process.env</code>环境变量对象中拿到。 这些配置最终会输出到 <code>./bin/start.sh</code>的启动脚本中,如果出现配置错误,先停掉服务然后手动去修改此文件,再执行 <code>sh ./bin/start.sh</code>命令即可重启服务</p>
  474. <p>比如我使用github登录与七牛上传服务最终配置如下</p>
  475. <div><pre><code class="language-none">#!/bin/bash
  476. # DB config
  477. # mongodb
  478. export MONGODB_NAME=iconRepo;
  479. export MONGODB_HOST=127.0.0.1;
  480. export MONGODB_PORT=27017;
  481. export MONGODB_USERNAME=&#39;&#39;;
  482. export MONGODB_PASSWORD=&#39;&#39;;
  483. # redis
  484. export REDIS_FAMILY=4;
  485. export REDIS_HOST=127.0.0.1;
  486. export REDIS_PORT=6379;
  487. export REDIS_PASSWORD=&#39;&#39;;
  488. export REDIS_DB=0;
  489. # config your website host
  490. export productHost=&#39;icon.bolin.site&#39;;
  491. # if you want login by github and upload by qiniu, set productType
  492. export productType=&#39;github_qiniu&#39;;
  493. # Login config
  494. # github openid login
  495. export GITHUB_LOGIN_CLIENT_ID=&#39;&#39;;
  496. export GITHUB_LOGIN_CLIENT_SECRET=&#39;&#39;;
  497. export GITHUB_LOGIN_REDIRECT_URI=&#39;&#39;;
  498. # Upload config
  499. # qiniu
  500. export QINIU_UPLOAD_ACCESS_KEY=&#39;&#39;;
  501. export QINIU_UPLOAD_SECRET_KEY=&#39;&#39;;
  502. export QINIU_UPLOAD_BUCKET=&#39;&#39;;
  503. export QINIU_UPLOAD_CDN_HOST=&#39;&#39;;
  504. # start command
  505. npm run restart
  506. </code></pre></div>
  507. <p>虽然该平台已经可以提供完成的登录、注册,图标库样式文件等静态资源的访问。但是对于企业来说,内部的工具平台最好只接受内部人或只能内网访问,对于静态资源最理想的就是放到自家的cdn服务器上,让平台操作更安全,访问所速度更快等等...</p>
  508. <p>基于这样的需求,Nicon支持接入三方登录与字体文件资源上传到三方服务器,但是具体的代码需要自己实现,代码要求暴露出指定的方法且该方法需返回指定的数据,然后通过配置的方式添加到工程中。具体调用什么服务由配置的<code>prodcutType</code>的值决定,<code>productType</code>的值格式为 <code>登录_上传</code>,目前默认服务类型有4种<code>default</code>、<code>default_qiniu</code>、<code>github_default</code>、<code>github_qiniu</code>,当<code>productType</code>的值为这4个时,三方服务脚本是不需要配置的。</p>
  509. <p>三方服务配置脚本就在以下的文件夹结构中生成名称为<code>productType</code>值的文件夹,有<code>index.js</code>、<code>config.js</code>两个文件。 除了以下的文件夹,用户配置后生成的文件夹都会被ignore掉。</p>
  510. <div><pre><code class="language-none">├── service
  511. │   ├── login
  512. │   │   ├── default
  513. │   │   │   ├── config.js
  514. │   │   │   └── index.js
  515. │   │   ├── github
  516. │   │   │   ├── config.js
  517. │   │   │   └── index.js
  518. │   │   ├── github_qiniu
  519. │   │   │   ├── config.js
  520. │   │   │   └── index.js
  521. │   │   ├── index.js
  522. │   └── upload
  523. │   ├── default
  524. │   │   ├── config.js
  525. │   │   └── index.js
  526. │   ├── github_qiniu
  527. │   │   ├── config.js
  528. │   │   └── index.js
  529. │   ├── index.js
  530. │   └── qiniu
  531. │   ├── config.js
  532. │   └── index.js
  533. </code></pre></div>
  534. <p><strong>三方登录</strong></p>
  535. <p>比如我需要接入github三方登录与qiniu上传存储服务,那么我的<code>productType</code>就设置为<code>github_qiniu</code>。 那么就会自动在<code>service/login/</code> 文件夹下创建文件夹 <code>github_qiniu</code>, 然后在该文件夹下创建<code>config.js</code> , 与<code>index.js</code>, 在index.js文件中必须暴露出async <code>login</code>方法, 调用方法后需要返回指定格式的数据</p>
  536. <div><pre><code class="language-none">// index.js
  537. require(&#39;request&#39;);
  538. let rp = require(&#39;request-promise&#39;);
  539. let config = require(&#39;./config&#39;);
  540. class GithubOpenIdLogin {
  541. async login (ctx) {
  542. return this.getUserBaseInfo(ctx);
  543. }
  544. async getUserBaseInfo (ctx) {
  545. // your code
  546. // login 方法返回的数据格式
  547. return {
  548. userName: tokenInfo.sub, // 必须且唯一
  549. password: tokenInfo.sub,
  550. email: openIdUserInfo.email,
  551. nickName: openIdUserInfo.nickname,
  552. fullName: openIdUserInfo.fullname
  553. }
  554. }
  555. }
  556. let loginIns = new GithubOpenIdLogin();
  557. module.exports = loginIns.login.bind(loginIns);
  558. </code></pre></div>
  559. <p><strong>三方上传</strong></p>
  560. <p>在<code>service/upload/</code> 文件夹下自动创建文件夹 <code>github_qiniu</code>, 然后在该文件夹下创建<code>config.js</code> , 与<code>index.js</code>, 在index.js文件中暴露出async <code>upload</code>方法, 调用方法后需要返回指定格式的数据</p>
  561. <div><pre><code class="language-none">// index.js
  562. let config = require(&#39;./config&#39;);
  563. let qiniu = require(&#39;qiniu&#39;);
  564. class QiniuUpload {
  565. async upload (dirPath) {
  566. let fontMap = await this.uploadFonts(dirPath);
  567. // 上传font完毕后替换css中的引用
  568. let cssContent = await this.replaceFontsInCss(dirPath, fontMap);
  569. let cssUrl = await this.uploadCss(dirPath, cssContent);
  570. // 上传返回数据格式
  571. return {
  572. url: cssUrl, // 必须
  573. cssContent: cssContent // 必须
  574. };
  575. }
  576. }
  577. let uploadIns = new QiniuUpload();
  578. module.exports = uploadIns.upload.bind(uploadIns);
  579. </code></pre></div>
  580. <p>至此就已经配置完毕,当保存提交之后工程就会重启,根据配置启动相应的服务。</p>
  581. <h2 id="toc_8">单元测试</h2>
  582. <p>待补充....</p>
  583. <h2 id="toc_9">License</h2>
  584. <p>MIT</p>
  585. <script type="text/javascript">
  586. var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function(e){var t=n.util.type(e);switch(t){case"Object":var a={};for(var r in e)e.hasOwnProperty(r)&&(a[r]=n.util.clone(e[r]));return a;case"Array":return e.map&&e.map(function(e){return n.util.clone(e)})}return e}},languages:{extend:function(e,t){var a=n.util.clone(n.languages[e]);for(var r in t)a[r]=t[r];return a},insertBefore:function(e,t,a,r){r=r||n.languages;var l=r[e];if(2==arguments.length){a=arguments[1];for(var i in a)a.hasOwnProperty(i)&&(l[i]=a[i]);return l}var o={};for(var s in l)if(l.hasOwnProperty(s)){if(s==t)for(var i in a)a.hasOwnProperty(i)&&(o[i]=a[i]);o[s]=l[s]}return n.languages.DFS(n.languages,function(t,n){n===r[e]&&t!=e&&(this[t]=o)}),r[e]=o},DFS:function(e,t,a,r){r=r||{};for(var l in e)e.hasOwnProperty(l)&&(t.call(e,l,e[l],a||l),"Object"!==n.util.type(e[l])||r[n.util.objId(e[l])]?"Array"!==n.util.type(e[l])||r[n.util.objId(e[l])]||(r[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,l,r)):(r[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,null,r)))}},plugins:{},highlightAll:function(e,t){var a={callback:t,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};n.hooks.run("before-highlightall",a);for(var r,l=a.elements||document.querySelectorAll(a.selector),i=0;r=l[i++];)n.highlightElement(r,e===!0,a.callback)},highlightElement:function(t,a,r){for(var l,i,o=t;o&&!e.test(o.className);)o=o.parentNode;o&&(l=(o.className.match(e)||[,""])[1],i=n.languages[l]),t.className=t.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,o=t.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var s=t.textContent,u={element:t,language:l,grammar:i,code:s};if(!s||!i)return n.hooks.run("complete",u),void 0;if(n.hooks.run("before-highlight",u),a&&_self.Worker){var c=new Worker(n.filename);c.onmessage=function(e){u.highlightedCode=e.data,n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(u.element),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},c.postMessage(JSON.stringify({language:u.language,code:u.code,immediateClose:!0}))}else u.highlightedCode=n.highlight(u.code,u.grammar,u.language),n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(t),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},highlight:function(e,t,r){var l=n.tokenize(e,t);return a.stringify(n.util.encode(l),r)},tokenize:function(e,t){var a=n.Token,r=[e],l=t.rest;if(l){for(var i in l)t[i]=l[i];delete t.rest}e:for(var i in t)if(t.hasOwnProperty(i)&&t[i]){var o=t[i];o="Array"===n.util.type(o)?o:[o];for(var s=0;s<o.length;++s){var u=o[s],c=u.inside,g=!!u.lookbehind,h=!!u.greedy,f=0,d=u.alias;u=u.pattern||u;for(var p=0;p<r.length;p++){var m=r[p];if(r.length>e.length)break e;if(!(m instanceof a)){u.lastIndex=0;var y=u.exec(m),v=1;if(!y&&h&&p!=r.length-1){var b=r[p+1].matchedStr||r[p+1],k=m+b;if(p<r.length-2&&(k+=r[p+2].matchedStr||r[p+2]),u.lastIndex=0,y=u.exec(k),!y)continue;var w=y.index+(g?y[1].length:0);if(w>=m.length)continue;var _=y.index+y[0].length,P=m.length+b.length;if(v=3,P>=_){if(r[p+1].greedy)continue;v=2,k=k.slice(0,P)}m=k}if(y){g&&(f=y[1].length);var w=y.index+f,y=y[0].slice(f),_=w+y.length,S=m.slice(0,w),O=m.slice(_),j=[p,v];S&&j.push(S);var A=new a(i,c?n.tokenize(y,c):y,d,y,h);j.push(A),O&&j.push(O),Array.prototype.splice.apply(r,j)}}}}}return r},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,l=0;r=a[l++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.matchedStr=a||null,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var l={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==l.type&&(l.attributes.spellcheck="true"),e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o="";for(var s in l.attributes)o+=(o?" ":"")+s+'="'+(l.attributes[s]||"")+'"';return"<"+l.tag+' class="'+l.classes.join(" ")+'" '+o+">"+l.content+"</"+l.tag+">"},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,l=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),l&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",n.highlightAll)),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
  587. </script>
  588. </body>
  589. </html>