背景
公司需要向外开放一些能力,为了方便接入和管理,需要一个开放平台,目的是连接开发者 供应商 和企业系统
需要包含的模块
-
账号体系 Developer
- 开发者身份注册
- 登陆
- 创建应用
- 数据权限
-
文档中心 Doc
- 概述
- 使用说明:注册->创建->绑定->配置->接入上线
- 接口文档
-
开放能力 Platform
- 管理开发者应用
- 查看接口权限
- 在线测试工具
-
管理后台 Admin
- 开发者管理
- 应用管理
- 配置管理
- 数据库管理
- 权限管理
- 监控报表
-
常见问题 Questions
- 问题列表
- 联系我们
安全层面
- 加密
- 应用秘钥
- 应用接口权限控制
- 访问黑白名单
- 字段脱敏还原等
技术实践
文档中心
-
Markdown
md转html:github.com/markedjs/ma…
json转md:github.com/IonicaBizau…
json转table:www.npmjs.com/package/jso…
-
代码高亮
import React, { useEffect, useState } from 'react';
import marked from 'marked';
import hljs from 'highlight.js';
import 'highlight.js/styles/monokai-sublime.css';
import Tocify from '../Component/tocify';
import json2md from 'json2md';
const renderer = new marked.Renderer();
let tocify = new Tocify();
interface jsonType {
[key: string]: string | jsonType[] | string[] | jsonType;
}
const jsonData: jsonType[] = [
{ h1: 'JSON To Markdown' },
{ blockquote: 'A JSON to Markdown converter.' },
{
img: [
{ title: 'Some image', source: 'https://example.com/some-image.png' },
{ title: 'Another image', source: 'https://example.com/some-image1.png' },
{
title: 'Yet another image',
source: 'https://example.com/some-image2.png',
},
],
},
{ h2: 'Features' },
{
ul: [
'Easy to use',
'You can programmatically generate Markdown content',
'...',
],
},
];
const { TextArea } = Input;
function AddArticle() {
// 渲染标题时触发,将标题添加到tocify目录列表中
renderer.heading = function (text, level, raw) {
const anchor = tocify.add(text, level);
return `<a id="${anchor}" href="#${anchor}" class="anchor-fix"><h${level}>${text}</h${level}></a>\n`;
};
marked.setOptions({
renderer,
highlight: function (code) {
return hljs.highlightAuto(code).value;
}, //代码高亮
gfm: true, // 允许 Git Hub标准的markdown.
pedantic: false, // 不纠正原始模型任何的不良行为和错误(默认为false)
sanitize: false, // 对输出进行过滤(清理),将忽略任何已经输入的html代码(标签)
breaks: true, // 允许回车换行(该选项要求 gfm 为true)
smartLists: false, // 使用比原生markdown更时髦的列表
smartypants: false, // 使用更为时髦的标点
});
const initMD = json2md(jsonData);
const [articleContent, setArticleContent] = useState(initMD); //markdown的编辑内容
const [markdownContent, setMarkdownContent] = useState(marked(initMD)); //html内容
return (
<div>
{/* markdown内容 */}
<TextArea
className="markdown-content"
rows={35}
placeholder="编辑内容"
value={articleContent}
/>
{/* html内容 */}
<div
className={css({
border: '1px solid #d9d9d9',
background: '#ffffff',
height: '100%',
})}
dangerouslySetInnerHTML={{ __html: markdownContent }}></div>
{/* 目录 */}
<div className="toc" >
{tocify && tocify.render()}
</div>
</div>
);
}
export default AddArticle;
../Component/Tocify
// tocify 生成目录 hash定位
import React from 'react';
import { Anchor } from 'antd';
import { last } from 'lodash';
const { Link } = Anchor;
export interface TocItem {
anchor: string;
level: number;
text: string;
children?: TocItem[];
}
export type TocItems = TocItem[]; // TOC目录树结构
export default class Tocify {
anchors: string[];
tocItems: TocItems = [];
constructor() {
this.anchors = [];
this.tocItems = [];
}
add(text: string, level: number, id: string = '') {
const count = this.anchors.filter((anchor) => anchor === text).length;
const anchor = id || (count ? `${text}${count}` : text);
this.anchors.push(anchor);
const item = { anchor, level, text };
const items = this.tocItems;
if (items.length === 0) {
// 第一个 item 直接 push
items.push(item);
} else {
let lastItem = last(items) as TocItem; // 最后一个 item
if (item.level > lastItem.level) {
// item 是 lastItem 的 children
for (let i = lastItem.level + 1; i <= 6; i++) {
const { children } = lastItem;
if (!children) {
// 如果 children 不存在
lastItem.children = [item];
break;
}
lastItem = last(children) as TocItem; // 重置 lastItem 为 children 的最后一个 item
if (item.level <= lastItem.level) {
// item level 小于或等于 lastItem level 都视为与 children 同级
children.push(item);
break;
}
}
}else{
// 置于最顶级
items.push(item);
}
}
return anchor;
}
reset = () => {
this.tocItems = [];
this.anchors = [];
};
renderToc(items: TocItem[]) {
// 递归 render
return items.map((item) => (
<Link key={item.anchor} href={`#${item.anchor}`} title={item.text}>
{item.children && this.renderToc(item.children)}
</Link>
));
}
render() {
return (
<Anchor style={{ padding: 24 }} affix showInkInFixed>
{this.renderToc(this.tocItems)}
</Anchor>
);
}
}