mock平台

controller.js 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. const baseController = require('controllers/base.js');
  2. const interfaceModel = require('models/interface.js');
  3. const projectModel = require('models/project.js');
  4. // const wikiModel = require('../yapi-plugin-wiki/wikiModel.js');
  5. const interfaceCatModel = require('models/interfaceCat.js');
  6. const yapi = require('yapi.js');
  7. const markdownIt = require('markdown-it');
  8. const markdownItAnchor = require('markdown-it-anchor');
  9. const markdownItTableOfContents = require('markdown-it-table-of-contents');
  10. const defaultTheme = require('./defaultTheme.js');
  11. const md = require('../../common/markdown');
  12. // const htmlToPdf = require("html-pdf");
  13. class exportController extends baseController {
  14. constructor(ctx) {
  15. super(ctx);
  16. this.catModel = yapi.getInst(interfaceCatModel);
  17. this.interModel = yapi.getInst(interfaceModel);
  18. this.projectModel = yapi.getInst(projectModel);
  19. }
  20. async handleListClass(pid, status) {
  21. let result = await this.catModel.list(pid),
  22. newResult = [];
  23. for (let i = 0, item, list; i < result.length; i++) {
  24. item = result[i].toObject();
  25. list = await this.interModel.listByInterStatus(item._id, status);
  26. list = list.sort((a, b) => {
  27. return a.index - b.index;
  28. });
  29. if (list.length > 0) {
  30. item.list = list;
  31. newResult.push(item);
  32. }
  33. }
  34. return newResult;
  35. }
  36. handleExistId(data) {
  37. function delArrId(arr, fn) {
  38. if (!Array.isArray(arr)) return;
  39. arr.forEach(item => {
  40. delete item._id;
  41. delete item.__v;
  42. delete item.uid;
  43. delete item.edit_uid;
  44. delete item.catid;
  45. delete item.project_id;
  46. if (typeof fn === 'function') fn(item);
  47. });
  48. }
  49. delArrId(data, function(item) {
  50. delArrId(item.list, function(api) {
  51. delArrId(api.req_body_form);
  52. delArrId(api.req_params);
  53. delArrId(api.req_query);
  54. delArrId(api.req_headers);
  55. if (api.query_path && typeof api.query_path === 'object') {
  56. delArrId(api.query_path.params);
  57. }
  58. });
  59. });
  60. return data;
  61. }
  62. // @feat: serives
  63. async exportFullData (ctx) {
  64. return this.exportData(ctx, 'full-path');
  65. }
  66. async exportData(ctx, fullPath) {
  67. let pid = ctx.request.query.pid;
  68. let type = ctx.request.query.type;
  69. let status = ctx.request.query.status;
  70. let isWiki = ctx.request.query.isWiki;
  71. if (!pid) {
  72. return ctx.body = yapi.commons.resReturn(null, 200, 'pid 不为空');
  73. }
  74. let curProject, wikiData;
  75. let tp = '';
  76. try {
  77. curProject = await this.projectModel.get(pid);
  78. const basepath = curProject.basepath;
  79. if (isWiki === 'true') {
  80. const wikiModel = require('../yapi-plugin-wiki/wikiModel.js');
  81. wikiData = await yapi.getInst(wikiModel).get(pid);
  82. }
  83. ctx.set('Content-Type', 'application/octet-stream');
  84. const list = await this.handleListClass(pid, status);
  85. switch (type) {
  86. case 'markdown': {
  87. tp = await createMarkdown.bind(this)(list, false);
  88. ctx.set('Content-Disposition', `attachment; filename=api.md`);
  89. return (ctx.body = tp);
  90. }
  91. case 'json': {
  92. let data = this.handleExistId(list);
  93. if (Array.isArray(data) && fullPath === 'full-path' && basepath) {
  94. data.forEach(function(cate) {
  95. if (Array.isArray(cate.list)) {
  96. cate.proBasepath = basepath;
  97. cate.proName = curProject.name;
  98. cate.proDescription = curProject.desc;
  99. cate.list = cate.list.map(function(api) {
  100. api.path = api.query_path.path = (basepath + '/' + api.path).replace(/[\/]{2,}/g, '/');
  101. return api;
  102. });
  103. }
  104. })
  105. }
  106. tp = JSON.stringify(data, null, 2);
  107. ctx.set('Content-Disposition', `attachment; filename=api.json`);
  108. return (ctx.body = tp);
  109. }
  110. default: {
  111. //默认为html
  112. tp = await createHtml.bind(this)(list);
  113. ctx.set('Content-Disposition', `attachment; filename=api.html`);
  114. return (ctx.body = tp);
  115. }
  116. }
  117. } catch (error) {
  118. yapi.commons.log(error, 'error');
  119. ctx.body = yapi.commons.resReturn(null, 502, '下载出错');
  120. }
  121. async function createHtml(list) {
  122. let md = await createMarkdown.bind(this)(list, true);
  123. let markdown = markdownIt({ html: true, breaks: true });
  124. markdown.use(markdownItAnchor); // Optional, but makes sense as you really want to link to something
  125. markdown.use(markdownItTableOfContents, {
  126. markerPattern: /^\[toc\]/im
  127. });
  128. // require('fs').writeFileSync('./a.markdown', md);
  129. let tp = unescape(markdown.render(md));
  130. // require('fs').writeFileSync('./a.html', tp);
  131. let left;
  132. // console.log('tp',tp);
  133. let content = tp.replace(
  134. /<div\s+?class="table-of-contents"\s*>[\s\S]*?<\/ul>\s*<\/div>/gi,
  135. function(match) {
  136. left = match;
  137. return '';
  138. }
  139. );
  140. return createHtml5(left || '', content);
  141. }
  142. function createHtml5(left, tp) {
  143. //html5模板
  144. let html = `<!DOCTYPE html>
  145. <html>
  146. <head>
  147. <title>${curProject.name}</title>
  148. <meta charset="utf-8" />
  149. ${defaultTheme}
  150. </head>
  151. <body>
  152. <div class="m-header">
  153. <a href="#" style="display: inherit;"><svg class="svg" width="32px" height="32px" viewBox="0 0 64 64" version="1.1"><title>Icon</title><desc>Created with Sketch.</desc><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1"><stop stop-color="#FFFFFF" offset="0%"></stop><stop stop-color="#F2F2F2" offset="100%"></stop></linearGradient><circle id="path-2" cx="31.9988602" cy="31.9988602" r="2.92886048"></circle><filter x="-85.4%" y="-68.3%" width="270.7%" height="270.7%" filterUnits="objectBoundingBox" id="filter-3"><feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset><feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.159703351 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix></filter></defs><g id="首页" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="大屏幕"><g id="Icon"><circle id="Oval-1" fill="url(#linearGradient-1)" cx="32" cy="32" r="32"></circle><path d="M36.7078009,31.8054514 L36.7078009,51.7110548 C36.7078009,54.2844537 34.6258634,56.3695395 32.0579205,56.3695395 C29.4899777,56.3695395 27.4099998,54.0704461 27.4099998,51.7941246 L27.4099998,31.8061972 C27.4099998,29.528395 29.4909575,27.218453 32.0589004,27.230043 C34.6268432,27.241633 36.7078009,29.528395 36.7078009,31.8054514 Z" id="blue" fill="#2359F1" fill-rule="nonzero"></path><path d="M45.2586091,17.1026914 C45.2586091,17.1026914 45.5657231,34.0524383 45.2345291,37.01141 C44.9033351,39.9703817 43.1767091,41.6667796 40.6088126,41.6667796 C38.040916,41.6667796 35.9609757,39.3676862 35.9609757,37.0913646 L35.9609757,17.1034372 C35.9609757,14.825635 38.0418959,12.515693 40.6097924,12.527283 C43.177689,12.538873 45.2586091,14.825635 45.2586091,17.1026914 Z" id="green" fill="#57CF27" fill-rule="nonzero" transform="translate(40.674608, 27.097010) rotate(60.000000) translate(-40.674608, -27.097010) "></path><path d="M28.0410158,17.0465598 L28.0410158,36.9521632 C28.0410158,39.525562 25.9591158,41.6106479 23.3912193,41.6106479 C20.8233227,41.6106479 18.7433824,39.3115545 18.7433824,37.035233 L18.7433824,17.0473055 C18.7433824,14.7695034 20.8243026,12.4595614 23.3921991,12.4711513 C25.9600956,12.4827413 28.0410158,14.7695034 28.0410158,17.0465598 Z" id="red" fill="#FF561B" fill-rule="nonzero" transform="translate(23.392199, 27.040878) rotate(-60.000000) translate(-23.392199, -27.040878) "></path><g id="inner-round"><use fill="black" fill-opacity="1" filter="url(#filter-3)" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#path-2"></use><use fill="#F7F7F7" fill-rule="evenodd" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#path-2"></use></g></g></g></g></svg></a>
  154. <a href="#"><h1 class="title">YAPI 接口文档</h1></a>
  155. <div class="nav">
  156. <a href="https://yapi.ymfe.org/">YApi</a>
  157. </div>
  158. </div>
  159. <div class="g-doc">
  160. ${left}
  161. <div id="right" class="content-right">
  162. ${tp}
  163. <footer class="m-footer">
  164. <p>Build by <a href="https://ymfe.org/">YMFE</a>.</p>
  165. </footer>
  166. </div>
  167. </div>
  168. </body>
  169. </html>
  170. `;
  171. return html;
  172. }
  173. function createMarkdown(list, isToc) {
  174. //拼接markdown
  175. //模板
  176. let mdTemplate = ``;
  177. try {
  178. // 项目名称信息
  179. mdTemplate += md.createProjectMarkdown(curProject, wikiData);
  180. // 分类信息
  181. mdTemplate += md.createClassMarkdown(curProject, list, isToc);
  182. return mdTemplate;
  183. } catch (e) {
  184. yapi.commons.log(e, 'error');
  185. ctx.body = yapi.commons.resReturn(null, 502, '下载出错');
  186. }
  187. }
  188. }
  189. }
  190. module.exports = exportController;