├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.MD ├── api └── v1 │ ├── api.go │ ├── article.go │ ├── ask.go │ ├── captcha.go │ ├── category.go │ ├── content.go │ ├── file.go │ ├── index.go │ ├── interact.go │ ├── login.go │ ├── profile.go │ ├── register.go │ ├── reply.go │ ├── search.go │ ├── topic.go │ └── user.go ├── go.mod ├── go.sum ├── hack └── config.yaml ├── internal ├── cmd │ └── cmd.go ├── consts │ ├── consts.go │ ├── content.go │ ├── interact.go │ ├── openapi.go │ ├── session.go │ └── user.go ├── controller │ ├── article.go │ ├── ask.go │ ├── captcha.go │ ├── category.go │ ├── content.go │ ├── file.go │ ├── index.go │ ├── interact.go │ ├── login.go │ ├── profile.go │ ├── register.go │ ├── reply.go │ ├── search.go │ ├── topic.go │ └── user.go ├── dao │ ├── category.go │ ├── content.go │ ├── file.go │ ├── interact.go │ ├── internal │ │ ├── category.go │ │ ├── content.go │ │ ├── file.go │ │ ├── interact.go │ │ ├── reply.go │ │ ├── setting.go │ │ └── user.go │ ├── reply.go │ ├── setting.go │ └── user.go ├── logic │ ├── bizctx │ │ └── bizctx.go │ ├── captcha │ │ └── captcha.go │ ├── category │ │ └── category.go │ ├── content │ │ └── content.go │ ├── file │ │ └── file.go │ ├── interact │ │ └── interact.go │ ├── logic.go │ ├── menu │ │ └── menu.go │ ├── middleware │ │ └── middleware.go │ ├── reply │ │ └── reply.go │ ├── session │ │ └── session.go │ ├── setting │ │ └── setting.go │ ├── user │ │ └── user.go │ └── view │ │ ├── view.go │ │ └── view_buildin.go ├── model │ ├── category.go │ ├── content.go │ ├── context.go │ ├── do │ │ ├── category.go │ │ ├── content.go │ │ ├── file.go │ │ ├── interact.go │ │ ├── reply.go │ │ ├── setting.go │ │ └── user.go │ ├── entity │ │ ├── category.go │ │ ├── content.go │ │ ├── file.go │ │ ├── interact.go │ │ ├── reply.go │ │ ├── setting.go │ │ └── user.go │ ├── file.go │ ├── menu.go │ ├── reply.go │ ├── session.go │ ├── user.go │ └── view.go ├── packed │ └── packed.go └── service │ ├── bizctx.go │ ├── captcha.go │ ├── category.go │ ├── content.go │ ├── file.go │ ├── interact.go │ ├── menu.go │ ├── middleware.go │ ├── reply.go │ ├── session.go │ ├── setting.go │ ├── user.go │ └── view.go ├── main.go ├── manifest ├── config │ └── config.example.yaml ├── deploy │ └── kustomize │ │ ├── base │ │ ├── deployment.yaml │ │ ├── kustomization.yaml │ │ └── service.yaml │ │ └── overlays │ │ └── develop │ │ ├── configmap.yaml │ │ ├── deployment.yaml │ │ └── kustomization.yaml ├── docker │ ├── Dockerfile │ └── docker.sh └── document │ ├── design │ ├── focus-v0.1.0-beta.png │ ├── focus-v0.2.0.png │ ├── focus-v0.2.0.xmind │ └── focus-v1.0.xmind │ ├── focus.sql │ ├── images │ ├── databases.png │ ├── demo1.png │ ├── demo2.png │ ├── demo3.png │ ├── demo4.png │ ├── demo5.png │ ├── demo6.png │ ├── demo7.png │ ├── demo8.png │ └── plan.png │ ├── mwb │ ├── gf.mwb │ └── gf.mwb.bak │ └── sqlite │ ├── focus.db │ └── focus.sql ├── resource ├── public │ ├── admin │ │ ├── css │ │ │ ├── .gitkeep │ │ │ └── common.css │ │ ├── images │ │ │ └── .gitkeep │ │ └── js │ │ │ ├── .gitkeep │ │ │ └── common.js │ ├── css │ │ └── common.css │ ├── favicon.ico │ ├── images │ │ ├── avatar │ │ │ ├── avatar1.jpg │ │ │ ├── avatar2.jpg │ │ │ ├── avatar3.jpg │ │ │ └── avatar4.jpg │ │ ├── error │ │ │ ├── error_401.png │ │ │ ├── error_403.png │ │ │ ├── error_404.png │ │ │ └── error_500.png │ │ └── logo.png │ ├── js │ │ ├── common.js │ │ └── encrypt │ │ │ ├── base64.js │ │ │ └── md5.js │ └── plugin │ │ ├── bootstrap-dialog │ │ ├── bootstrap-dialog-common.js │ │ ├── bootstrap-dialog.css │ │ ├── bootstrap-dialog.js │ │ ├── bootstrap-dialog.min.css │ │ ├── bootstrap-dialog.min.js │ │ ├── common-demo.html │ │ └── index.html │ │ ├── bootstrap │ │ ├── bootstrap.css │ │ ├── bootstrap.min.css │ │ ├── bootstrap.min.js │ │ └── popper.min.js │ │ ├── iconfont │ │ ├── demo.css │ │ ├── demo_index.html │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.js │ │ ├── iconfont.json │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ │ ├── jquery │ │ ├── jquery.form.min.js │ │ ├── jquery.min.js │ │ ├── jquery.validate.min.js │ │ └── sweetalert.min.js │ │ ├── markdown-css │ │ └── github-markdown.css │ │ ├── marked │ │ └── marked.min.js │ │ ├── md-toc │ │ ├── md-toc.js │ │ └── md-toc.min.js │ │ ├── prism │ │ ├── prism.css │ │ └── prism.js │ │ └── vditor │ │ └── dist │ │ ├── css │ │ └── content-theme │ │ │ ├── ant-design.css │ │ │ ├── dark.css │ │ │ ├── light.css │ │ │ └── wechat.css │ │ ├── images │ │ ├── emoji │ │ │ ├── b3log.png │ │ │ ├── chainbook.png │ │ │ ├── doge.png │ │ │ ├── hacpai.png │ │ │ ├── huaji.gif │ │ │ ├── latke.png │ │ │ ├── lute.png │ │ │ ├── octocat.png │ │ │ ├── pipe.png │ │ │ ├── solo.png │ │ │ ├── sym.png │ │ │ ├── trollface.png │ │ │ ├── vditor.png │ │ │ ├── wide.png │ │ │ └── wulian.png │ │ ├── img-loading.svg │ │ └── logo.png │ │ ├── index.css │ │ ├── index.d.ts │ │ ├── index.min.js │ │ ├── js │ │ ├── abcjs │ │ │ └── abcjs_basic.min.js │ │ ├── echarts │ │ │ └── echarts.min.js │ │ ├── flowchart.js │ │ │ └── flowchart.min.js │ │ ├── graphviz │ │ │ ├── full.render.js │ │ │ └── viz.js │ │ ├── highlight.js │ │ │ ├── highlight.pack.js │ │ │ └── styles │ │ │ │ ├── abap.css │ │ │ │ ├── algol.css │ │ │ │ ├── algol_nu.css │ │ │ │ ├── ant-design.css │ │ │ │ ├── arduino.css │ │ │ │ ├── autumn.css │ │ │ │ ├── borland.css │ │ │ │ ├── bw.css │ │ │ │ ├── colorful.css │ │ │ │ ├── dracula.css │ │ │ │ ├── emacs.css │ │ │ │ ├── friendly.css │ │ │ │ ├── fruity.css │ │ │ │ ├── github.css │ │ │ │ ├── igor.css │ │ │ │ ├── lovelace.css │ │ │ │ ├── manni.css │ │ │ │ ├── monokai.css │ │ │ │ ├── monokailight.css │ │ │ │ ├── murphy.css │ │ │ │ ├── native.css │ │ │ │ ├── paraiso-dark.css │ │ │ │ ├── paraiso-light.css │ │ │ │ ├── pastie.css │ │ │ │ ├── perldoc.css │ │ │ │ ├── pygments.css │ │ │ │ ├── rainbow_dash.css │ │ │ │ ├── rrt.css │ │ │ │ ├── solarized-dark.css │ │ │ │ ├── solarized-dark256.css │ │ │ │ ├── solarized-light.css │ │ │ │ ├── swapoff.css │ │ │ │ ├── tango.css │ │ │ │ ├── trac.css │ │ │ │ ├── vim.css │ │ │ │ ├── vs.css │ │ │ │ └── xcode.css │ │ ├── icons │ │ │ ├── ant.js │ │ │ └── material.js │ │ ├── katex │ │ │ ├── fonts │ │ │ │ ├── KaTeX_AMS-Regular.ttf │ │ │ │ ├── KaTeX_AMS-Regular.woff │ │ │ │ ├── KaTeX_AMS-Regular.woff2 │ │ │ │ ├── KaTeX_Caligraphic-Bold.ttf │ │ │ │ ├── KaTeX_Caligraphic-Bold.woff │ │ │ │ ├── KaTeX_Caligraphic-Bold.woff2 │ │ │ │ ├── KaTeX_Caligraphic-Regular.ttf │ │ │ │ ├── KaTeX_Caligraphic-Regular.woff │ │ │ │ ├── KaTeX_Caligraphic-Regular.woff2 │ │ │ │ ├── KaTeX_Fraktur-Bold.ttf │ │ │ │ ├── KaTeX_Fraktur-Bold.woff │ │ │ │ ├── KaTeX_Fraktur-Bold.woff2 │ │ │ │ ├── KaTeX_Fraktur-Regular.ttf │ │ │ │ ├── KaTeX_Fraktur-Regular.woff │ │ │ │ ├── KaTeX_Fraktur-Regular.woff2 │ │ │ │ ├── KaTeX_Main-Bold.ttf │ │ │ │ ├── KaTeX_Main-Bold.woff │ │ │ │ ├── KaTeX_Main-Bold.woff2 │ │ │ │ ├── KaTeX_Main-BoldItalic.ttf │ │ │ │ ├── KaTeX_Main-BoldItalic.woff │ │ │ │ ├── KaTeX_Main-BoldItalic.woff2 │ │ │ │ ├── KaTeX_Main-Italic.ttf │ │ │ │ ├── KaTeX_Main-Italic.woff │ │ │ │ ├── KaTeX_Main-Italic.woff2 │ │ │ │ ├── KaTeX_Main-Regular.ttf │ │ │ │ ├── KaTeX_Main-Regular.woff │ │ │ │ ├── KaTeX_Main-Regular.woff2 │ │ │ │ ├── KaTeX_Math-BoldItalic.ttf │ │ │ │ ├── KaTeX_Math-BoldItalic.woff │ │ │ │ ├── KaTeX_Math-BoldItalic.woff2 │ │ │ │ ├── KaTeX_Math-Italic.ttf │ │ │ │ ├── KaTeX_Math-Italic.woff │ │ │ │ ├── KaTeX_Math-Italic.woff2 │ │ │ │ ├── KaTeX_SansSerif-Bold.ttf │ │ │ │ ├── KaTeX_SansSerif-Bold.woff │ │ │ │ ├── KaTeX_SansSerif-Bold.woff2 │ │ │ │ ├── KaTeX_SansSerif-Italic.ttf │ │ │ │ ├── KaTeX_SansSerif-Italic.woff │ │ │ │ ├── KaTeX_SansSerif-Italic.woff2 │ │ │ │ ├── KaTeX_SansSerif-Regular.ttf │ │ │ │ ├── KaTeX_SansSerif-Regular.woff │ │ │ │ ├── KaTeX_SansSerif-Regular.woff2 │ │ │ │ ├── KaTeX_Script-Regular.ttf │ │ │ │ ├── KaTeX_Script-Regular.woff │ │ │ │ ├── KaTeX_Script-Regular.woff2 │ │ │ │ ├── KaTeX_Size1-Regular.ttf │ │ │ │ ├── KaTeX_Size1-Regular.woff │ │ │ │ ├── KaTeX_Size1-Regular.woff2 │ │ │ │ ├── KaTeX_Size2-Regular.ttf │ │ │ │ ├── KaTeX_Size2-Regular.woff │ │ │ │ ├── KaTeX_Size2-Regular.woff2 │ │ │ │ ├── KaTeX_Size3-Regular.ttf │ │ │ │ ├── KaTeX_Size3-Regular.woff │ │ │ │ ├── KaTeX_Size3-Regular.woff2 │ │ │ │ ├── KaTeX_Size4-Regular.ttf │ │ │ │ ├── KaTeX_Size4-Regular.woff │ │ │ │ ├── KaTeX_Size4-Regular.woff2 │ │ │ │ ├── KaTeX_Typewriter-Regular.ttf │ │ │ │ ├── KaTeX_Typewriter-Regular.woff │ │ │ │ └── KaTeX_Typewriter-Regular.woff2 │ │ │ ├── katex.min.css │ │ │ └── katex.min.js │ │ ├── lute │ │ │ └── lute.min.js │ │ ├── mathjax │ │ │ ├── input │ │ │ │ ├── asciimath.js │ │ │ │ ├── mml.js │ │ │ │ ├── mml │ │ │ │ │ └── entities.js │ │ │ │ ├── tex-base.js │ │ │ │ ├── tex-full.js │ │ │ │ ├── tex.js │ │ │ │ └── tex │ │ │ │ │ └── extensions │ │ │ │ │ ├── action.js │ │ │ │ │ ├── all-packages.js │ │ │ │ │ ├── ams.js │ │ │ │ │ ├── amscd.js │ │ │ │ │ ├── autoload.js │ │ │ │ │ ├── bbox.js │ │ │ │ │ ├── boldsymbol.js │ │ │ │ │ ├── braket.js │ │ │ │ │ ├── bussproofs.js │ │ │ │ │ ├── cancel.js │ │ │ │ │ ├── color.js │ │ │ │ │ ├── colorV2.js │ │ │ │ │ ├── configMacros.js │ │ │ │ │ ├── enclose.js │ │ │ │ │ ├── extpfeil.js │ │ │ │ │ ├── html.js │ │ │ │ │ ├── mhchem.js │ │ │ │ │ ├── newcommand.js │ │ │ │ │ ├── noerrors.js │ │ │ │ │ ├── noundefined.js │ │ │ │ │ ├── physics.js │ │ │ │ │ ├── require.js │ │ │ │ │ ├── tagFormat.js │ │ │ │ │ ├── unicode.js │ │ │ │ │ └── verb.js │ │ │ └── tex-svg.js │ │ └── mermaid │ │ │ └── mermaid.min.js │ │ ├── method.d.ts │ │ ├── method.min.js │ │ ├── ts │ │ ├── constants.d.ts │ │ ├── devtools │ │ │ └── index.d.ts │ │ ├── export │ │ │ └── index.d.ts │ │ ├── hint │ │ │ └── index.d.ts │ │ ├── i18n │ │ │ └── index.d.ts │ │ ├── ir │ │ │ ├── expandMarker.d.ts │ │ │ ├── highlightToolbarIR.d.ts │ │ │ ├── index.d.ts │ │ │ ├── input.d.ts │ │ │ ├── process.d.ts │ │ │ └── processKeydown.d.ts │ │ ├── markdown │ │ │ ├── abcRender.d.ts │ │ │ ├── anchorRender.d.ts │ │ │ ├── chartRender.d.ts │ │ │ ├── codeRender.d.ts │ │ │ ├── flowchartRender.d.ts │ │ │ ├── getHTML.d.ts │ │ │ ├── getMarkdown.d.ts │ │ │ ├── graphvizRender.d.ts │ │ │ ├── highlightRender.d.ts │ │ │ ├── lazyLoadImageRender.d.ts │ │ │ ├── mathRender.d.ts │ │ │ ├── mediaRender.d.ts │ │ │ ├── mermaidRender.d.ts │ │ │ ├── mindmapRender.d.ts │ │ │ ├── outlineRender.d.ts │ │ │ ├── previewRender.d.ts │ │ │ ├── setLute.d.ts │ │ │ └── speechRender.d.ts │ │ ├── outline │ │ │ └── index.d.ts │ │ ├── preview │ │ │ └── index.d.ts │ │ ├── resize │ │ │ └── index.d.ts │ │ ├── sv │ │ │ ├── index.d.ts │ │ │ ├── inputEvent.d.ts │ │ │ ├── process.d.ts │ │ │ └── processKeydown.d.ts │ │ ├── tip │ │ │ └── index.d.ts │ │ ├── toolbar │ │ │ ├── Both.d.ts │ │ │ ├── Br.d.ts │ │ │ ├── CodeTheme.d.ts │ │ │ ├── ContentTheme.d.ts │ │ │ ├── Counter.d.ts │ │ │ ├── Custom.d.ts │ │ │ ├── Devtools.d.ts │ │ │ ├── Divider.d.ts │ │ │ ├── EditMode.d.ts │ │ │ ├── Emoji.d.ts │ │ │ ├── Export.d.ts │ │ │ ├── Fullscreen.d.ts │ │ │ ├── Headings.d.ts │ │ │ ├── Help.d.ts │ │ │ ├── Indent.d.ts │ │ │ ├── Info.d.ts │ │ │ ├── InsertAfter.d.ts │ │ │ ├── InsertBefore.d.ts │ │ │ ├── MenuItem.d.ts │ │ │ ├── Outdent.d.ts │ │ │ ├── Outline.d.ts │ │ │ ├── Preview.d.ts │ │ │ ├── Record.d.ts │ │ │ ├── Redo.d.ts │ │ │ ├── Undo.d.ts │ │ │ ├── Upload.d.ts │ │ │ ├── index.d.ts │ │ │ └── setToolbar.d.ts │ │ ├── ui │ │ │ ├── initUI.d.ts │ │ │ ├── setCodeTheme.d.ts │ │ │ ├── setContentTheme.d.ts │ │ │ ├── setPreviewMode.d.ts │ │ │ └── setTheme.d.ts │ │ ├── undo │ │ │ └── index.d.ts │ │ ├── util │ │ │ ├── Options.d.ts │ │ │ ├── RecordMedia.d.ts │ │ │ ├── addScript.d.ts │ │ │ ├── addStyle.d.ts │ │ │ ├── code160to32.d.ts │ │ │ ├── compatibility.d.ts │ │ │ ├── editorCommonEvent.d.ts │ │ │ ├── fixBrowserBehavior.d.ts │ │ │ ├── getSelectText.d.ts │ │ │ ├── hasClosest.d.ts │ │ │ ├── hasClosestByHeadings.d.ts │ │ │ ├── highlightToolbar.d.ts │ │ │ ├── hotKey.d.ts │ │ │ ├── log.d.ts │ │ │ ├── merge.d.ts │ │ │ ├── processCode.d.ts │ │ │ ├── selection.d.ts │ │ │ └── toc.d.ts │ │ └── wysiwyg │ │ │ ├── afterRenderEvent.d.ts │ │ │ ├── highlightToolbarWYSIWYG.d.ts │ │ │ ├── index.d.ts │ │ │ ├── inlineTag.d.ts │ │ │ ├── input.d.ts │ │ │ ├── processKeydown.d.ts │ │ │ ├── renderDomByMd.d.ts │ │ │ ├── setHeading.d.ts │ │ │ ├── showCode.d.ts │ │ │ └── toolbarEvent.d.ts │ │ └── types │ │ └── index.d.ts └── template │ ├── admin │ └── index.html │ └── index │ ├── article │ ├── detail.html │ └── index.html │ ├── ask │ ├── detail.html │ └── index.html │ ├── content │ ├── create.html │ ├── detail.html │ ├── index.html │ └── update.html │ ├── footer.html │ ├── header.html │ ├── index.html │ ├── index │ ├── index.html │ └── page_link.html │ ├── login │ └── index.html │ ├── message.html │ ├── navbar.html │ ├── pages │ ├── 401.html │ ├── 403.html │ ├── 404.html │ └── 500.html │ ├── profile │ ├── avatar.html │ ├── index.html │ ├── message.html │ └── password.html │ ├── register │ └── index.html │ ├── reply.html │ ├── search │ └── index.html │ ├── topic │ ├── detail.html │ └── index.html │ └── user │ ├── article.html │ ├── ask.html │ ├── detail.html │ ├── profile.html │ ├── topic.html │ ├── user_content_list.html │ └── user_menu.html └── utility ├── response └── response.go └── utils ├── utils.go └── utils_test.go /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=GO 2 | *.css linguist-language=GO 3 | *.html linguist-language=GO -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .buildpath 3 | .hgignore.swp 4 | .project 5 | .orig 6 | .swp 7 | .idea/ 8 | .settings/ 9 | .vscode/ 10 | vender/ 11 | log/ 12 | logs/ 13 | composer.lock 14 | gitpush.sh 15 | pkg/ 16 | upload/ 17 | bin/ 18 | cbuild 19 | */.DS_Store 20 | config/config.toml 21 | main 22 | .vscode 23 | node_modules/ 24 | temp/ 25 | logs/ 26 | packed/data.go 27 | focus 28 | manifest/config/config.yaml 29 | 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ROOT_DIR = $(shell pwd) 2 | NAMESPACE = "default" 3 | DEPLOY_NAME = "focus-single" 4 | DOCKER_NAME = "focus-single" 5 | 6 | # Install/Update to the latest CLI tool. 7 | .PHONY: cli 8 | cli: 9 | @set -e; \ 10 | wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \ 11 | chmod +x gf && \ 12 | ./gf install -y && \ 13 | rm ./gf 14 | 15 | 16 | # Check and install CLI tool. 17 | .PHONY: cli.install 18 | cli.install: 19 | @set -e; \ 20 | gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \ 21 | echo "GoFame CLI is not installed, start proceeding auto installation..."; \ 22 | make cli; \ 23 | fi; 24 | 25 | 26 | # Generate Go files for DAO/DO/Entity. 27 | .PHONY: dao 28 | dao: cli.install 29 | @gf gen dao 30 | 31 | # Generate Go files for Service. 32 | .PHONY: service 33 | service: cli.install 34 | @gf gen service 35 | 36 | # Build image, deploy image and yaml to current kubectl environment and make port forward to local machine. 37 | .PHONY: start 38 | start: 39 | @set -e; \ 40 | make image; \ 41 | make deploy; \ 42 | make port; 43 | 44 | # Build docker image. 45 | .PHONY: image 46 | image: cli.install 47 | $(eval _TAG = $(shell git log -1 --format="%cd.%h" --date=format:"%Y%m%d%H%M%S")) 48 | ifneq (, $(shell git status --porcelain 2>/dev/null)) 49 | $(eval _TAG = $(_TAG).dirty) 50 | endif 51 | $(eval _TAG = $(if ${TAG}, ${TAG}, $(_TAG))) 52 | $(eval _PUSH = $(if ${PUSH}, ${PUSH}, )) 53 | @gf docker -p -b "-a amd64 -s linux -p temp" -tn $(DOCKER_NAME):${_TAG}; 54 | 55 | 56 | # Build docker image and automatically push to docker repo. 57 | .PHONY: image.push 58 | image.push: 59 | @make image PUSH=-p; 60 | 61 | 62 | # Deploy image and yaml to current kubectl environment. 63 | .PHONY: deploy 64 | deploy: 65 | $(eval _TAG = $(if ${TAG}, ${TAG}, develop)) 66 | 67 | @set -e; \ 68 | mkdir -p $(ROOT_DIR)/temp/kustomize;\ 69 | cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_TAG};\ 70 | kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\ 71 | kubectl apply -f $(ROOT_DIR)/temp/kustomize.yaml; \ 72 | kubectl patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; 73 | 74 | 75 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # 1. Focus Single 2 | 3 | A `MVC` project using `GoFrame`. 4 | 5 | # 2. Quick start 6 | 7 | ## 2.1 If you use SQLite 8 | 9 | 1. Download the source code 10 | ``` 11 | git clone https://github.com/gogf/focus-single.git 12 | cd focus-single 13 | ``` 14 | 15 | 2. Run Focus Single 16 | ``` 17 | cp manifest/config/config.example.yaml manifest/config/config.yaml 18 | gf run main.go 19 | ``` 20 | 21 | 3. Enjoy it 22 | then open http://127.0.0.1:8199/ and enjoy it. 23 | 24 | ``` 25 | user: goframe 26 | password: 123456 27 | ``` 28 | 29 | ## 2.2 If you use MySQL 30 | 31 | 1. Download the source code 32 | ``` 33 | git clone https://github.com/gogf/focus-single.git 34 | cd focus-single 35 | ``` 36 | 37 | 2. Update config 38 | copy manifest/config/config.yaml and edit database.default config 39 | ``` 40 | cp manifest/config/config.example.yaml manifest/config/config.yaml 41 | ``` 42 | 43 | 3. Import Db 44 | Import manifest/document/focus.sql to your Mysql 45 | 46 | 4. Run Focus Single And Enjoy 47 | ``` 48 | gf run main.go 49 | ``` 50 | 51 | then open http://127.0.0.1:8199/ and enjoy it. 52 | ``` 53 | user: goframe 54 | password: 123456 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /api/v1/api.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | type CommonPaginationReq struct { 4 | Page int `json:"page" in:"query" d:"1" v:"min:0#分页号码错误" dc:"分页号码,默认1"` 5 | Size int `json:"size" in:"query" d:"10" v:"max:50#分页数量最大50条" dc:"分页数量,最大50"` 6 | } 7 | 8 | type CommonPaginationRes struct { 9 | Total int `dc:"总数"` 10 | } 11 | -------------------------------------------------------------------------------- /api/v1/article.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type ArticleIndexReq struct { 8 | g.Meta `path:"/article" method:"get" tags:"文章" summary:"展示Article列表页面"` 9 | ContentGetListCommonReq 10 | } 11 | type ArticleIndexRes struct { 12 | ContentGetListCommonRes 13 | } 14 | 15 | type ArticleDetailReq struct { 16 | g.Meta `path:"/article/{Id}" method:"get" tags:"文章" summary:"展示Article详情页面" ` 17 | Id uint `in:"path" v:"min:1#请选择查看的内容" dc:"内容id"` 18 | } 19 | type ArticleDetailRes struct { 20 | g.Meta `mime:"text/html" type:"string" example:""` 21 | } 22 | -------------------------------------------------------------------------------- /api/v1/ask.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type AskIndexReq struct { 8 | g.Meta `path:"/ask" method:"get" tags:"问答" summary:"展示Ask列表页面"` 9 | ContentGetListCommonReq 10 | } 11 | type AskIndexRes struct { 12 | ContentGetListCommonRes 13 | } 14 | 15 | type AskDetailReq struct { 16 | g.Meta `path:"/ask/{Id}" method:"get" tags:"问答" summary:"展示Ask详情页面" ` 17 | Id uint `in:"path" v:"min:1#请选择查看的内容" dc:"内容id"` 18 | } 19 | type AskDetailRes struct { 20 | g.Meta `mime:"text/html" type:"string" example:""` 21 | } 22 | -------------------------------------------------------------------------------- /api/v1/captcha.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type CaptchaIndexReq struct { 8 | g.Meta `path:"/captcha" method:"get" tags:"工具" summary:"获取默认的验证码" dc:"注意直接返回的是图片二进制内容"` 9 | } 10 | type CaptchaIndexRes struct { 11 | g.Meta `mime:"png" dc:"验证码二进制内容" ` 12 | } 13 | -------------------------------------------------------------------------------- /api/v1/category.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "focus-single/internal/model" 5 | "github.com/gogf/gf/v2/frame/g" 6 | ) 7 | 8 | type CategoryTreeReq struct { 9 | g.Meta `path:"/category/tree" method:"get" tags:"分类" summary:"获取分类列表" dc:"获取分类列表,构造成树形结构返回"` 10 | ContentType string `json:"contentType" dc:"栏目类型:topic/question/article。当传递空时表示获取所有类型的栏目"` 11 | } 12 | type CategoryTreeRes struct { 13 | List []*model.CategoryTreeItem `json:"list" dc:"栏目列表"` 14 | } 15 | -------------------------------------------------------------------------------- /api/v1/file.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "github.com/gogf/gf/v2/net/ghttp" 6 | ) 7 | 8 | type FileUploadReq struct { 9 | g.Meta `path:"/file" method:"post" mime:"multipart/form-data" tags:"工具" summary:"上传文件"` 10 | File *ghttp.UploadFile `json:"file" type:"file" dc:"选择上传文件"` 11 | } 12 | type FileUploadRes struct { 13 | Name string `json:"name" dc:"文件名称"` 14 | Url string `json:"url" dc:"访问URL,可能只是URI"` 15 | } 16 | -------------------------------------------------------------------------------- /api/v1/index.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type IndexReq struct { 8 | g.Meta `path:"/" method:"get" tags:"首页" summary:"首页"` 9 | ContentGetListCommonReq 10 | } 11 | type IndexRes struct { 12 | ContentGetListCommonRes 13 | } 14 | -------------------------------------------------------------------------------- /api/v1/interact.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import "github.com/gogf/gf/v2/frame/g" 4 | 5 | type InteractZanReq struct { 6 | g.Meta `path:"/interact/zan" method:"put" summary:"赞" tags:"交互"` 7 | Id uint `json:"id" v:"min:1#请选择需要赞的内容"` 8 | Type string `json:"type" v:"required#请提交需要赞的内容类型" dc:"content/reply"` 9 | } 10 | type InteractZanRes struct{} 11 | 12 | type InteractCancelZanReq struct { 13 | g.Meta `path:"/interact/zan" method:"delete" summary:"取消赞" tags:"交互"` 14 | Id uint `json:"id" v:"min:1#请选择需要取消赞的内容"` 15 | Type string `json:"type" v:"required#请提交需要取消赞的内容类型" ` 16 | } 17 | type InteractCancelZanRes struct{} 18 | 19 | type InteractCaiReq struct { 20 | g.Meta `path:"/interact/cai" method:"put" summary:"踩" tags:"交互"` 21 | Id uint `json:"id" v:"min:1#请选择需要踩的内容"` 22 | Type string `json:"type" v:"required#请提交需要踩的内容类型" dc:"content/reply"` 23 | } 24 | type InteractCaiRes struct{} 25 | 26 | type InteractCancelCaiReq struct { 27 | g.Meta `path:"/interact/cai" method:"delete" summary:"取消踩" tags:"交互"` 28 | Id uint `json:"id" v:"min:1#请选择需要取消踩的内容"` 29 | Type string `json:"type" v:"required#请提交需要取消踩的内容类型" dc:"content/reply"` 30 | } 31 | type InteractCancelCaiRes struct{} 32 | -------------------------------------------------------------------------------- /api/v1/login.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import "github.com/gogf/gf/v2/frame/g" 4 | 5 | type LoginIndexReq struct { 6 | g.Meta `path:"/login" method:"get" summary:"展示登录页面" tags:"登录"` 7 | } 8 | type LoginIndexRes struct { 9 | g.Meta `mime:"text/html" type:"string" example:""` 10 | } 11 | 12 | type LoginDoReq struct { 13 | g.Meta `path:"/login" method:"post" summary:"执行登录请求" tags:"登录"` 14 | Passport string `json:"passport" v:"required#请输入账号" dc:"账号"` 15 | Password string `json:"password" v:"required#请输入密码" dc:"密码(明文)"` 16 | Captcha string `json:"captcha" v:"required#请输入验证码" dc:"验证码"` 17 | } 18 | type LoginDoRes struct { 19 | Referer string `json:"referer" dc:"引导客户端跳转地址"` 20 | } 21 | -------------------------------------------------------------------------------- /api/v1/profile.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type ProfileIndexReq struct { 8 | g.Meta `path:"/profile" method:"get" summary:"展示个人资料页面" tags:"个人"` 9 | } 10 | type ProfileIndexRes struct { 11 | g.Meta `mime:"text/html" type:"string" example:""` 12 | } 13 | 14 | type ProfileUpdateReq struct { 15 | g.Meta `path:"/profile" method:"post" summary:"修改个人资料" tags:"个人"` 16 | Id uint `json:"id" dc:"用户ID"` 17 | Avatar string `json:"avatar" dc:"头像地址"` 18 | Gender int `json:"gender" dc:"性别 0: 未设置 1: 男 2: 女"` 19 | Nickname string `json:"nickname" v:"required#请输入昵称信息" dc:"昵称"` 20 | } 21 | type ProfileUpdateRes struct{} 22 | 23 | type ProfileAvatarReq struct { 24 | g.Meta `path:"/profile/avatar" method:"get" summary:"展示头像管理页面" tags:"个人"` 25 | } 26 | type ProfileAvatarRes struct { 27 | g.Meta `mime:"text/html" type:"string" example:""` 28 | } 29 | 30 | type ProfileUpdateAvatarReq struct { 31 | g.Meta `path:"/profile/avatar" method:"post" summary:"修改个人头像" tags:"个人"` 32 | Id uint `json:"id" dc:"用户ID"` 33 | Avatar string `json:"avatar" dc:"头像地址"` 34 | } 35 | type ProfileUpdateAvatarRes struct{} 36 | 37 | type ProfilePasswordReq struct { 38 | g.Meta `path:"/profile/password" method:"get" summary:"展示密码修改页面" tags:"个人"` 39 | } 40 | type ProfilePasswordRes struct { 41 | g.Meta `mime:"text/html" type:"string" example:""` 42 | } 43 | 44 | type ProfileUpdatePasswordReq struct { 45 | g.Meta `path:"/profile/password" method:"post" summary:"修改个人密码" tags:"个人"` 46 | OldPassword string `json:"oldPassword" v:"required#请输入原始密码" dc:"原密码"` 47 | NewPassword string `json:"newPassword" v:"required#请输入新密码" dc:"新密码"` 48 | } 49 | type ProfileUpdatePasswordRes struct{} 50 | 51 | type ProfileMessageReq struct { 52 | g.Meta `path:"/profile/message" method:"get" summary:"展示查询用户消息列表页面" tags:"个人"` 53 | CommonPaginationReq 54 | TargetType string `json:"targetType" dc:"数据类型"` 55 | TargetId uint `json:"targetId" dc:"数据ID"` 56 | } 57 | type ProfileMessageRes struct { 58 | g.Meta `mime:"text/html" type:"string" example:""` 59 | } 60 | -------------------------------------------------------------------------------- /api/v1/register.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import "github.com/gogf/gf/v2/frame/g" 4 | 5 | type RegisterIndexReq struct { 6 | g.Meta `path:"/register" method:"get" summary:"展示注册页面" tags:"注册"` 7 | } 8 | type RegisterIndexRes struct { 9 | g.Meta `mime:"text/html" type:"string" example:""` 10 | } 11 | 12 | type RegisterDoReq struct { 13 | g.Meta `path:"/register" method:"post" summary:"执行注册请求" tags:"注册"` 14 | Passport string `json:"passport" v:"required#请输入账号" dc:"账号"` 15 | Password string `json:"password" v:"required#请输入密码" dc:"密码"` 16 | Nickname string `json:"nickname" v:"required#请输入昵称" dc:"昵称"` 17 | Captcha string `json:"captcha" v:"required#请输入验证码" dc:"验证码"` 18 | } 19 | type RegisterDoRes struct{} 20 | -------------------------------------------------------------------------------- /api/v1/reply.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type ReplyGetListContentReq struct { 8 | g.Meta `path:"/reply" method:"get" summary:"查询回复列表" tags:"回复"` 9 | Page int `json:"page" dc:"分页码"` 10 | Size int `json:"size" dc:"分页数量"` 11 | TargetType string `json:"targetType" v:"required#评论内容类型错误" dc:"评论类型: topic/ask/article/reply"` 12 | TargetId uint `json:"targetId" v:"required#评论目标ID错误" dc:"对应内容ID"` 13 | } 14 | type ReplyGetListContentRes struct { 15 | Content string `json:"content" dc:"HTML内容"` 16 | } 17 | 18 | type ReplyCreateReq struct { 19 | g.Meta `path:"/reply" method:"put" summary:"执行回复接口" tags:"回复"` 20 | Title string `json:"title" dc:"回复标题"` 21 | ParentId uint `json:"parentId" dc:"回复对应的上一级回复ID(没有的话默认为0)"` 22 | TargetType string `json:"targetType" v:"required#评论内容类型错误" dc:"评论类型: topic/ask/article/reply"` 23 | TargetId uint `json:"targetId" v:"required#评论目标ID错误" dc:"对应内容ID"` 24 | Content string `json:"content" v:"required#评论内容不能为空" dc:"回复内容"` 25 | } 26 | type ReplyCreateRes struct{} 27 | 28 | type ReplyDeleteReq struct { 29 | g.Meta `path:"/reply" method:"delete" summary:"删除回复接口" tags:"回复"` 30 | Id uint `v:"min:1#请选择需要删除的内容" dc:"删除时ID不能为空"` 31 | } 32 | type ReplyDeleteRes struct{} 33 | -------------------------------------------------------------------------------- /api/v1/search.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type SearchIndexReq struct { 8 | g.Meta `path:"/search" method:"get" summary:"展示内容搜索页面" tags:"搜索"` 9 | ContentGetListCommonReq 10 | Key string `json:"key" v:"required#请输入搜索关键字" dc:"关键字"` 11 | Type string `json:"type" dc:"内容模型"` 12 | CategoryId uint `json:"cate" dc:"栏目ID"` 13 | Sort int `json:"sort" dc:"排序类型(0:最新, 默认。1:活跃, 2:热度)"` 14 | } 15 | type SearchIndexRes struct { 16 | g.Meta `mime:"text/html" type:"string" example:""` 17 | } 18 | -------------------------------------------------------------------------------- /api/v1/topic.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type TopicIndexReq struct { 8 | g.Meta `path:"/topic" method:"get" tags:"话题" summary:"展示Topic列表页面"` 9 | ContentGetListCommonReq 10 | } 11 | type TopicIndexRes struct { 12 | ContentGetListCommonRes 13 | } 14 | 15 | type TopicDetailReq struct { 16 | g.Meta `path:"/topic/{Id}" method:"get" tags:"话题" summary:"展示Topic详情页面" ` 17 | Id uint `in:"path" v:"min:1#请选择查看的内容" dc:"内容id"` 18 | } 19 | type TopicDetailRes struct { 20 | g.Meta `mime:"text/html" type:"string" example:""` 21 | } 22 | -------------------------------------------------------------------------------- /api/v1/user.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | ) 6 | 7 | type UserIndexReq struct { 8 | g.Meta `path:"/user/{UserId}" method:"get" summary:"展示查询用户内容列表页面" tags:"用户"` 9 | ContentGetListCommonReq 10 | UserId uint `json:"userId" in:"path" dc:"用户ID"` 11 | } 12 | type UserIndexRes struct { 13 | g.Meta `mime:"text/html" type:"string" example:""` 14 | } 15 | 16 | type UserArticleReq struct { 17 | g.Meta `path:"/user/article" method:"get" summary:"展示查询用户Article列表页面" tags:"用户"` 18 | ContentGetListCommonReq 19 | UserId uint `json:"userId" in:"path" dc:"用户ID"` 20 | } 21 | type UserArticleRes struct { 22 | g.Meta `mime:"text/html" type:"string" example:""` 23 | } 24 | 25 | type UserTopicReq struct { 26 | g.Meta `path:"/user/topic" method:"get" summary:"展示查询用户Topic列表页面" tags:"用户"` 27 | ContentGetListCommonReq 28 | UserId uint `json:"userId" in:"path" dc:"用户ID"` 29 | } 30 | type UserTopicRes struct { 31 | g.Meta `mime:"text/html" type:"string" example:""` 32 | } 33 | 34 | type UserAskReq struct { 35 | g.Meta `path:"/user/ask" method:"get" summary:"展示查询用户Ask列表页面" tags:"用户"` 36 | ContentGetListCommonReq 37 | UserId uint `json:"userId" in:"path" dc:"用户ID"` 38 | } 39 | type UserAskRes struct { 40 | g.Meta `mime:"text/html" type:"string" example:""` 41 | } 42 | 43 | type UserLogoutReq struct { 44 | g.Meta `path:"/user/logout" method:"get" summary:"执行用户注销接口" tags:"个人"` 45 | } 46 | 47 | type UserLogoutRes struct { 48 | g.Meta `mime:"text/html" type:"string" example:""` 49 | } 50 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module focus-single 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/BurntSushi/toml v1.2.1 // indirect 7 | github.com/clbanning/mxj/v2 v2.5.7 // indirect 8 | github.com/fatih/color v1.15.0 // indirect 9 | github.com/fsnotify/fsnotify v1.6.0 // indirect 10 | github.com/glebarez/go-sqlite v1.21.0 // indirect 11 | github.com/go-sql-driver/mysql v1.7.0 // indirect 12 | github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.3 13 | github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.3.3 14 | github.com/gogf/gf/v2 v2.4.0-beta.0.20230328132849-d3c96b5e6b45 15 | github.com/kr/text v0.2.0 // indirect 16 | github.com/magiconair/properties v1.8.7 // indirect 17 | github.com/mattn/go-isatty v0.0.18 // indirect 18 | github.com/mattn/go-runewidth v0.0.14 // indirect 19 | github.com/mojocn/base64Captcha v1.3.1 20 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect 21 | github.com/o1egl/govatar v0.3.0 22 | github.com/rivo/uniseg v0.4.4 // indirect 23 | github.com/russross/blackfriday/v2 v2.1.0 24 | go.opentelemetry.io/otel/sdk v1.14.0 // indirect 25 | golang.org/x/net v0.8.0 // indirect 26 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect 27 | modernc.org/sqlite v1.21.0 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /hack/config.yaml: -------------------------------------------------------------------------------- 1 | 2 | # 工具相关配置 3 | gfcli: 4 | # 工具编译配置 5 | build: 6 | name: "focus" 7 | arch: "amd64" 8 | system: "linux,darwin,windows" 9 | mod: "" 10 | cgo: 0 11 | 12 | # dao生成 13 | gen: 14 | dao: 15 | - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/focus" 16 | removePrefix: "gf_" 17 | descriptionTag: true 18 | noModelComment: true 19 | -------------------------------------------------------------------------------- /internal/consts/consts.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | const ( 4 | Version = "v0.2.0" // 当前服务版本(用于模板展示) 5 | CaptchaDefaultName = "CaptchaDefaultName" // 验证码默认存储空间名称 6 | ContextKey = "ContextKey" // 上下文变量存储键名,前后端系统共享 7 | FileMaxUploadCountMinute = 10 // 同一用户1分钟之内最大上传数量 8 | ) 9 | -------------------------------------------------------------------------------- /internal/consts/content.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | const ( 4 | ContentListDefaultSize = 10 5 | ContentListMaxSize = 50 6 | ContentSortDefault = 0 // 排序:按照创建时间 7 | ContentSortActive = 1 // 排序:按照更新时间 8 | ContentSortHot = 2 // 排序:按照浏览量 9 | ContentSortScore = 3 // 排序:按照搜索结果关联性 10 | ContentTypeArticle = "article" 11 | ContentTypeAsk = "ask" 12 | ContentTypeTopic = "topic" 13 | ) 14 | -------------------------------------------------------------------------------- /internal/consts/interact.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | const ( 4 | InteractTypeZan = 0 5 | InteractTypeCai = 1 6 | InteractTargetTypeContent = "content" 7 | InteractTargetTypeReply = "reply" 8 | ) 9 | -------------------------------------------------------------------------------- /internal/consts/openapi.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | const ( 4 | OpenAPITagNameIndex = `首页` 5 | OpenAPITagNameLogin = `登录` 6 | OpenAPITagNameRegister = `注册` 7 | OpenAPITagNameArticle = `文章` 8 | OpenAPITagNameTopic = `话题` 9 | OpenAPITagNameAsk = `问答` 10 | OpenAPITagNameReply = `回复` 11 | OpenAPITagNameContent = `内容` 12 | OpenAPITagNameSearch = `搜索` 13 | OpenAPITagNameInteract = `交互` 14 | OpenAPITagNameCategory = `分类` 15 | OpenAPITagNameProfile = `个人` 16 | OpenAPITagNameUser = `用户` 17 | OpenAPITagNameMess = `工具` 18 | ) 19 | -------------------------------------------------------------------------------- /internal/consts/session.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | const ( 4 | SessionNoticeTypeSuccess = "success" 5 | SessionNoticeTypeInfo = "primary" 6 | SessionNoticeTypeWarn = "warning" 7 | SessionNoticeTypeError = "danger" 8 | ) 9 | -------------------------------------------------------------------------------- /internal/consts/user.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | const ( 4 | UserStatusOk = 0 // 用户状态正常 5 | UserStatusDisabled = 1 // 用户状态禁用 6 | UserGenderUnknown = 0 // 性别: 未知 7 | UserGenderMale = 1 // 性别: 男 8 | UserGenderFemale = 2 // 性别: 女 9 | UserLoginUrl = "/login" 10 | ) 11 | -------------------------------------------------------------------------------- /internal/controller/article.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/consts" 8 | "focus-single/internal/model" 9 | "focus-single/internal/service" 10 | ) 11 | 12 | // Article 文章管理 13 | var Article = cArticle{} 14 | 15 | type cArticle struct{} 16 | 17 | // Index article list 18 | func (a *cArticle) Index(ctx context.Context, req *v1.ArticleIndexReq) (res *v1.ArticleIndexRes, err error) { 19 | req.Type = consts.ContentTypeArticle 20 | getListRes, err := service.Content().GetList(ctx, model.ContentGetListInput{ 21 | Type: req.Type, 22 | CategoryId: req.CategoryId, 23 | Page: req.Page, 24 | Size: req.Size, 25 | Sort: req.Sort, 26 | }) 27 | if err != nil { 28 | return nil, err 29 | } 30 | service.View().Render(ctx, model.View{ 31 | ContentType: req.Type, 32 | Data: getListRes, 33 | Title: service.View().GetTitle(ctx, &model.ViewGetTitleInput{ 34 | ContentType: req.Type, 35 | CategoryId: req.CategoryId, 36 | }), 37 | }) 38 | return 39 | } 40 | 41 | // Detail .article details 42 | func (a *cArticle) Detail(ctx context.Context, req *v1.ArticleDetailReq) (res *v1.ArticleDetailRes, err error) { 43 | getDetailRes, err := service.Content().GetDetail(ctx, req.Id) 44 | if err != nil { 45 | return nil, err 46 | } 47 | if getDetailRes == nil { 48 | service.View().Render404(ctx) 49 | return nil, nil 50 | } 51 | if err = service.Content().AddViewCount(ctx, req.Id, 1); err != nil { 52 | return res, err 53 | } 54 | service.View().Render(ctx, model.View{ 55 | ContentType: consts.ContentTypeArticle, 56 | Data: getDetailRes, 57 | Title: service.View().GetTitle(ctx, &model.ViewGetTitleInput{ 58 | ContentType: getDetailRes.Content.Type, 59 | CategoryId: getDetailRes.Content.CategoryId, 60 | CurrentName: getDetailRes.Content.Title, 61 | }), 62 | BreadCrumb: service.View().GetBreadCrumb(ctx, &model.ViewGetBreadCrumbInput{ 63 | ContentId: getDetailRes.Content.Id, 64 | ContentType: getDetailRes.Content.Type, 65 | CategoryId: getDetailRes.Content.CategoryId, 66 | }), 67 | }) 68 | return 69 | } 70 | -------------------------------------------------------------------------------- /internal/controller/ask.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/consts" 8 | "focus-single/internal/model" 9 | "focus-single/internal/service" 10 | ) 11 | 12 | // Ask 问答管理 13 | var Ask = cAak{} 14 | 15 | type cAak struct{} 16 | 17 | func (a *cAak) Index(ctx context.Context, req *v1.AskIndexReq) (res *v1.AskIndexRes, err error) { 18 | req.Type = consts.ContentTypeAsk 19 | getListRes, err := service.Content().GetList(ctx, model.ContentGetListInput{ 20 | Type: req.Type, 21 | CategoryId: req.CategoryId, 22 | Page: req.Page, 23 | Size: req.Size, 24 | Sort: req.Sort, 25 | }) 26 | if err != nil { 27 | return nil, err 28 | } 29 | service.View().Render(ctx, model.View{ 30 | ContentType: req.Type, 31 | Data: getListRes, 32 | Title: service.View().GetTitle(ctx, &model.ViewGetTitleInput{ 33 | ContentType: req.Type, 34 | CategoryId: req.CategoryId, 35 | }), 36 | }) 37 | return 38 | } 39 | 40 | func (a *cAak) Detail(ctx context.Context, req *v1.AskDetailReq) (res *v1.AskDetailRes, err error) { 41 | getDetailRes, err := service.Content().GetDetail(ctx, req.Id) 42 | if err != nil { 43 | return nil, err 44 | } 45 | if getDetailRes == nil { 46 | service.View().Render404(ctx) 47 | return nil, nil 48 | } 49 | if err = service.Content().AddViewCount(ctx, req.Id, 1); err != nil { 50 | return nil, err 51 | } 52 | var ( 53 | title = service.View().GetTitle(ctx, &model.ViewGetTitleInput{ 54 | ContentType: getDetailRes.Content.Type, 55 | CategoryId: getDetailRes.Content.CategoryId, 56 | CurrentName: getDetailRes.Content.Title, 57 | }) 58 | breadCrumb = service.View().GetBreadCrumb(ctx, &model.ViewGetBreadCrumbInput{ 59 | ContentId: getDetailRes.Content.Id, 60 | ContentType: getDetailRes.Content.Type, 61 | CategoryId: getDetailRes.Content.CategoryId, 62 | }) 63 | ) 64 | service.View().Render(ctx, model.View{ 65 | ContentType: consts.ContentTypeAsk, 66 | Data: getDetailRes, 67 | Title: title, 68 | BreadCrumb: breadCrumb, 69 | }) 70 | return 71 | } 72 | -------------------------------------------------------------------------------- /internal/controller/captcha.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/consts" 8 | "focus-single/internal/service" 9 | ) 10 | 11 | // 图形验证码 12 | var Captcha = cCaptcha{} 13 | 14 | type cCaptcha struct{} 15 | 16 | func (a *cCaptcha) Index(ctx context.Context, req *v1.CaptchaIndexReq) (res *v1.CaptchaIndexRes, err error) { 17 | err = service.Captcha().NewAndStore(ctx, consts.CaptchaDefaultName) 18 | return 19 | } 20 | -------------------------------------------------------------------------------- /internal/controller/category.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/service" 8 | ) 9 | 10 | // 栏目管理 11 | var Category = cCategory{} 12 | 13 | type cCategory struct{} 14 | 15 | func (a *cCategory) Tree(ctx context.Context, req *v1.CategoryTreeReq) (res *v1.CategoryTreeRes, err error) { 16 | res = &v1.CategoryTreeRes{} 17 | res.List, err = service.Category().GetTree(ctx, req.ContentType) 18 | return 19 | } 20 | -------------------------------------------------------------------------------- /internal/controller/file.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/model" 8 | "focus-single/internal/service" 9 | "github.com/gogf/gf/v2/errors/gcode" 10 | "github.com/gogf/gf/v2/errors/gerror" 11 | ) 12 | 13 | // 文件管理 14 | var File = cFile{} 15 | 16 | type cFile struct{} 17 | 18 | func (a *cFile) Upload(ctx context.Context, req *v1.FileUploadReq) (res *v1.FileUploadRes, err error) { 19 | if req.File == nil { 20 | return nil, gerror.NewCode(gcode.CodeMissingParameter, "请选择需要上传的文件") 21 | } 22 | result, err := service.File().Upload(ctx, model.FileUploadInput{ 23 | File: req.File, 24 | RandomName: true, 25 | }) 26 | if err != nil { 27 | return nil, err 28 | } 29 | res = &v1.FileUploadRes{ 30 | Name: result.Name, 31 | Url: result.Url, 32 | } 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /internal/controller/index.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/model" 8 | "focus-single/internal/service" 9 | ) 10 | 11 | // 首页接口 12 | var Index = cIndex{} 13 | 14 | type cIndex struct{} 15 | 16 | func (a *cIndex) Index(ctx context.Context, req *v1.IndexReq) (res *v1.IndexRes, err error) { 17 | if getListRes, err := service.Content().GetList(ctx, model.ContentGetListInput{ 18 | Type: req.Type, 19 | CategoryId: req.CategoryId, 20 | Page: req.Page, 21 | Size: req.Size, 22 | Sort: req.Sort, 23 | }); err != nil { 24 | return nil, err 25 | } else { 26 | service.View().Render(ctx, model.View{ 27 | ContentType: req.Type, 28 | Data: getListRes, 29 | Title: "首页", 30 | }) 31 | } 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /internal/controller/interact.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/service" 8 | ) 9 | 10 | // 赞踩控制器 11 | var Interact = cInteract{} 12 | 13 | type cInteract struct{} 14 | 15 | func (a *cInteract) Zan(ctx context.Context, req *v1.InteractZanReq) (res *v1.InteractZanRes, err error) { 16 | err = service.Interact().Zan(ctx, req.Type, req.Id) 17 | return 18 | } 19 | 20 | func (a *cInteract) CancelZan(ctx context.Context, req *v1.InteractCancelZanReq) (res *v1.InteractCancelZanRes, err error) { 21 | err = service.Interact().CancelZan(ctx, req.Type, req.Id) 22 | return 23 | } 24 | 25 | func (a *cInteract) Cai(ctx context.Context, req *v1.InteractCaiReq) (res *v1.InteractCaiRes, err error) { 26 | err = service.Interact().Cai(ctx, req.Type, req.Id) 27 | return 28 | } 29 | 30 | func (a *cInteract) CancelCai(ctx context.Context, req *v1.InteractCancelCaiReq) (res *v1.InteractCancelCaiRes, err error) { 31 | err = service.Interact().CancelCai(ctx, req.Type, req.Id) 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /internal/controller/login.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/consts" 8 | "focus-single/internal/model" 9 | "focus-single/internal/service" 10 | "github.com/gogf/gf/v2/errors/gcode" 11 | "github.com/gogf/gf/v2/errors/gerror" 12 | "github.com/gogf/gf/v2/frame/g" 13 | ) 14 | 15 | // 登录管理 16 | var Login = cLogin{} 17 | 18 | type cLogin struct{} 19 | 20 | func (a *cLogin) Index(ctx context.Context, req *v1.LoginIndexReq) (res *v1.LoginIndexRes, err error) { 21 | service.View().Render(ctx, model.View{}) 22 | return 23 | } 24 | 25 | func (a *cLogin) Login(ctx context.Context, req *v1.LoginDoReq) (res *v1.LoginDoRes, err error) { 26 | res = &v1.LoginDoRes{} 27 | if !service.Captcha().VerifyAndClear(g.RequestFromCtx(ctx), consts.CaptchaDefaultName, req.Captcha) { 28 | return res, gerror.NewCode(gcode.CodeBusinessValidationFailed, "请输入正确的验证码") 29 | } 30 | err = service.User().Login(ctx, model.UserLoginInput{ 31 | Passport: req.Passport, 32 | Password: req.Password, 33 | }) 34 | if err != nil { 35 | return 36 | } 37 | // 识别并跳转到登录前页面 38 | loginReferer := service.Session().GetLoginReferer(ctx) 39 | if loginReferer != "" { 40 | _ = service.Session().RemoveLoginReferer(ctx) 41 | } 42 | res.Referer = loginReferer 43 | return 44 | } 45 | -------------------------------------------------------------------------------- /internal/controller/register.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/consts" 8 | "focus-single/internal/model" 9 | "focus-single/internal/service" 10 | "github.com/gogf/gf/v2/errors/gcode" 11 | "github.com/gogf/gf/v2/errors/gerror" 12 | "github.com/gogf/gf/v2/frame/g" 13 | ) 14 | 15 | // 注册控制器 16 | var Register = cRegister{} 17 | 18 | type cRegister struct{} 19 | 20 | func (a *cRegister) Index(ctx context.Context, req *v1.RegisterIndexReq) (res *v1.RegisterIndexRes, err error) { 21 | service.View().Render(ctx, model.View{}) 22 | return 23 | } 24 | 25 | func (a *cRegister) Register(ctx context.Context, req *v1.RegisterDoReq) (res *v1.RegisterDoRes, err error) { 26 | if !service.Captcha().VerifyAndClear(g.RequestFromCtx(ctx), consts.CaptchaDefaultName, req.Captcha) { 27 | return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, "请输入正确的验证码") 28 | } 29 | if err = service.User().Register(ctx, model.UserRegisterInput{ 30 | Passport: req.Passport, 31 | Password: req.Password, 32 | Nickname: req.Nickname, 33 | }); err != nil { 34 | return 35 | } 36 | 37 | // 自动登录 38 | err = service.User().Login(ctx, model.UserLoginInput{ 39 | Passport: req.Passport, 40 | Password: req.Password, 41 | }) 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /internal/controller/reply.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/model" 8 | "focus-single/internal/service" 9 | "github.com/gogf/gf/v2/frame/g" 10 | ) 11 | 12 | // Reply 回复控制器 13 | var Reply = cReply{} 14 | 15 | type cReply struct{} 16 | 17 | func (a *cReply) GetListContent(ctx context.Context, req *v1.ReplyGetListContentReq) (res *v1.ReplyGetListContentRes, err error) { 18 | out, err := service.Reply().GetList(ctx, model.ReplyGetListInput{ 19 | Page: req.Page, 20 | Size: req.Size, 21 | TargetType: req.TargetType, 22 | TargetId: req.TargetId, 23 | }) 24 | if err != nil { 25 | return nil, err 26 | } 27 | request := g.RequestFromCtx(ctx) 28 | service.View().RenderTpl(ctx, "index/reply.html", model.View{Data: out}) 29 | tplContent := request.Response.BufferString() 30 | request.Response.ClearBuffer() 31 | return &v1.ReplyGetListContentRes{Content: tplContent}, nil 32 | } 33 | 34 | func (a *cReply) Create(ctx context.Context, req *v1.ReplyCreateReq) (res *v1.ReplyCreateRes, err error) { 35 | err = service.Reply().Create(ctx, model.ReplyCreateInput{ 36 | Title: req.Title, 37 | ParentId: req.ParentId, 38 | TargetType: req.TargetType, 39 | TargetId: req.TargetId, 40 | Content: req.Content, 41 | UserId: service.Session().GetUser(ctx).Id, 42 | }) 43 | return 44 | } 45 | 46 | func (a *cReply) Delete(ctx context.Context, req *v1.ReplyDeleteReq) (res *v1.ReplyDeleteRes, err error) { 47 | err = service.Reply().Delete(ctx, req.Id) 48 | return 49 | } 50 | -------------------------------------------------------------------------------- /internal/controller/search.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/model" 8 | "focus-single/internal/service" 9 | ) 10 | 11 | // 搜索管理 12 | var Search = cSearch{} 13 | 14 | type cSearch struct{} 15 | 16 | func (a *cSearch) Index(ctx context.Context, req *v1.SearchIndexReq) (res *v1.SearchIndexRes, err error) { 17 | out, err := service.Content().Search(ctx, model.ContentSearchInput{ 18 | Key: req.Key, 19 | Type: req.Type, 20 | CategoryId: req.CategoryId, 21 | Page: req.Page, 22 | Size: req.Size, 23 | Sort: req.Sort, 24 | }) 25 | if err != nil { 26 | return nil, err 27 | } 28 | service.View().Render(ctx, model.View{ 29 | Data: out, 30 | Title: service.View().GetTitle(ctx, &model.ViewGetTitleInput{}), 31 | }) 32 | return nil, nil 33 | } 34 | -------------------------------------------------------------------------------- /internal/controller/topic.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/api/v1" 7 | "focus-single/internal/consts" 8 | "focus-single/internal/model" 9 | "focus-single/internal/service" 10 | ) 11 | 12 | // Topic 主题管理 13 | var Topic = cTopic{} 14 | 15 | type cTopic struct{} 16 | 17 | func (a *cTopic) Index(ctx context.Context, req *v1.TopicIndexReq) (res *v1.TopicIndexRes, err error) { 18 | req.Type = consts.ContentTypeTopic 19 | out, err := service.Content().GetList(ctx, model.ContentGetListInput{ 20 | Type: req.Type, 21 | CategoryId: req.CategoryId, 22 | Page: req.Page, 23 | Size: req.Size, 24 | Sort: req.Sort, 25 | }) 26 | if err != nil { 27 | return nil, err 28 | } 29 | title := service.View().GetTitle(ctx, &model.ViewGetTitleInput{ 30 | ContentType: req.Type, 31 | CategoryId: req.CategoryId, 32 | }) 33 | service.View().Render(ctx, model.View{ 34 | ContentType: req.Type, 35 | Data: out, 36 | Title: title, 37 | }) 38 | return 39 | } 40 | 41 | func (a *cTopic) Detail(ctx context.Context, req *v1.TopicDetailReq) (res *v1.TopicDetailRes, err error) { 42 | out, err := service.Content().GetDetail(ctx, req.Id) 43 | if err != nil { 44 | return nil, err 45 | } 46 | if out == nil { 47 | service.View().Render404(ctx) 48 | return 49 | } 50 | err = service.Content().AddViewCount(ctx, req.Id, 1) 51 | service.View().Render(ctx, model.View{ 52 | ContentType: consts.ContentTypeTopic, 53 | Data: out, 54 | Title: service.View().GetTitle(ctx, &model.ViewGetTitleInput{ 55 | ContentType: out.Content.Type, 56 | CategoryId: out.Content.CategoryId, 57 | CurrentName: out.Content.Title, 58 | }), 59 | BreadCrumb: service.View().GetBreadCrumb(ctx, &model.ViewGetBreadCrumbInput{ 60 | ContentId: out.Content.Id, 61 | ContentType: out.Content.Type, 62 | CategoryId: out.Content.CategoryId, 63 | }), 64 | }) 65 | return 66 | } 67 | -------------------------------------------------------------------------------- /internal/dao/category.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "focus-single/internal/dao/internal" 9 | ) 10 | 11 | // categoryDao is the data access object for table gf_category. 12 | // You can define custom methods on it to extend its functionality as you wish. 13 | type categoryDao struct { 14 | *internal.CategoryDao 15 | } 16 | 17 | var ( 18 | // Category is globally public accessible object for table gf_category operations. 19 | Category = categoryDao{ 20 | internal.NewCategoryDao(), 21 | } 22 | ) 23 | 24 | // Fill with you ideas below. 25 | -------------------------------------------------------------------------------- /internal/dao/content.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "focus-single/internal/dao/internal" 9 | ) 10 | 11 | // contentDao is the data access object for table gf_content. 12 | // You can define custom methods on it to extend its functionality as you wish. 13 | type contentDao struct { 14 | *internal.ContentDao 15 | } 16 | 17 | var ( 18 | // Content is globally public accessible object for table gf_content operations. 19 | Content = contentDao{ 20 | internal.NewContentDao(), 21 | } 22 | ) 23 | 24 | // Fill with you ideas below. 25 | -------------------------------------------------------------------------------- /internal/dao/file.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "focus-single/internal/dao/internal" 9 | ) 10 | 11 | // fileDao is the data access object for table gf_file. 12 | // You can define custom methods on it to extend its functionality as you wish. 13 | type fileDao struct { 14 | *internal.FileDao 15 | } 16 | 17 | var ( 18 | // File is globally public accessible object for table gf_file operations. 19 | File = fileDao{ 20 | internal.NewFileDao(), 21 | } 22 | ) 23 | 24 | // Fill with you ideas below. 25 | -------------------------------------------------------------------------------- /internal/dao/interact.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "focus-single/internal/dao/internal" 9 | ) 10 | 11 | // interactDao is the data access object for table gf_interact. 12 | // You can define custom methods on it to extend its functionality as you wish. 13 | type interactDao struct { 14 | *internal.InteractDao 15 | } 16 | 17 | var ( 18 | // Interact is globally public accessible object for table gf_interact operations. 19 | Interact = interactDao{ 20 | internal.NewInteractDao(), 21 | } 22 | ) 23 | 24 | // Fill with you ideas below. 25 | -------------------------------------------------------------------------------- /internal/dao/reply.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "focus-single/internal/dao/internal" 9 | ) 10 | 11 | // replyDao is the data access object for table gf_reply. 12 | // You can define custom methods on it to extend its functionality as you wish. 13 | type replyDao struct { 14 | *internal.ReplyDao 15 | } 16 | 17 | var ( 18 | // Reply is globally public accessible object for table gf_reply operations. 19 | Reply = replyDao{ 20 | internal.NewReplyDao(), 21 | } 22 | ) 23 | 24 | // Fill with you ideas below. 25 | -------------------------------------------------------------------------------- /internal/dao/setting.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "focus-single/internal/dao/internal" 9 | ) 10 | 11 | // settingDao is the data access object for table gf_setting. 12 | // You can define custom methods on it to extend its functionality as you wish. 13 | type settingDao struct { 14 | *internal.SettingDao 15 | } 16 | 17 | var ( 18 | // Setting is globally public accessible object for table gf_setting operations. 19 | Setting = settingDao{ 20 | internal.NewSettingDao(), 21 | } 22 | ) 23 | 24 | // Fill with you ideas below. 25 | -------------------------------------------------------------------------------- /internal/dao/user.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "focus-single/internal/dao/internal" 9 | ) 10 | 11 | // userDao is the data access object for table gf_user. 12 | // You can define custom methods on it to extend its functionality as you wish. 13 | type userDao struct { 14 | *internal.UserDao 15 | } 16 | 17 | var ( 18 | // User is globally public accessible object for table gf_user operations. 19 | User = userDao{ 20 | internal.NewUserDao(), 21 | } 22 | ) 23 | 24 | // Fill with you ideas below. 25 | -------------------------------------------------------------------------------- /internal/logic/bizctx/bizctx.go: -------------------------------------------------------------------------------- 1 | package bizctx 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/internal/service" 7 | "github.com/gogf/gf/v2/frame/g" 8 | "github.com/gogf/gf/v2/net/ghttp" 9 | 10 | "focus-single/internal/consts" 11 | "focus-single/internal/model" 12 | ) 13 | 14 | type sBizCtx struct{} 15 | 16 | func init() { 17 | service.RegisterBizCtx(New()) 18 | } 19 | 20 | func New() *sBizCtx { 21 | return &sBizCtx{} 22 | } 23 | 24 | // Init 初始化上下文对象指针到上下文对象中,以便后续的请求流程中可以修改。 25 | func (s *sBizCtx) Init(r *ghttp.Request, customCtx *model.Context) { 26 | r.SetCtxVar(consts.ContextKey, customCtx) 27 | } 28 | 29 | // Get 获得上下文变量,如果没有设置,那么返回nil 30 | func (s *sBizCtx) Get(ctx context.Context) *model.Context { 31 | value := ctx.Value(consts.ContextKey) 32 | if value == nil { 33 | return nil 34 | } 35 | if localCtx, ok := value.(*model.Context); ok { 36 | return localCtx 37 | } 38 | return nil 39 | } 40 | 41 | // SetUser 将上下文信息设置到上下文请求中,注意是完整覆盖 42 | func (s *sBizCtx) SetUser(ctx context.Context, ctxUser *model.ContextUser) { 43 | s.Get(ctx).User = ctxUser 44 | } 45 | 46 | // SetData 将上下文信息设置到上下文请求中,注意是完整覆盖 47 | func (s *sBizCtx) SetData(ctx context.Context, data g.Map) { 48 | s.Get(ctx).Data = data 49 | } 50 | -------------------------------------------------------------------------------- /internal/logic/captcha/captcha.go: -------------------------------------------------------------------------------- 1 | package captcha 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/internal/service" 7 | "github.com/gogf/gf/v2/frame/g" 8 | "github.com/gogf/gf/v2/net/ghttp" 9 | "github.com/gogf/gf/v2/util/guid" 10 | "github.com/mojocn/base64Captcha" 11 | ) 12 | 13 | type sCaptcha struct{} 14 | 15 | var ( 16 | captchaStore = base64Captcha.DefaultMemStore 17 | captchaDriver = newDriver() 18 | ) 19 | 20 | func init() { 21 | service.RegisterCaptcha(New()) 22 | } 23 | 24 | // Captcha 验证码管理服务 25 | func New() *sCaptcha { 26 | return &sCaptcha{} 27 | } 28 | 29 | func newDriver() *base64Captcha.DriverString { 30 | driver := &base64Captcha.DriverString{ 31 | Height: 44, 32 | Width: 126, 33 | NoiseCount: 5, 34 | ShowLineOptions: base64Captcha.OptionShowSineLine | base64Captcha.OptionShowSlimeLine | base64Captcha.OptionShowHollowLine, 35 | Length: 4, 36 | Source: "1234567890", 37 | Fonts: []string{"wqy-microhei.ttc"}, 38 | } 39 | return driver.ConvertFonts() 40 | } 41 | 42 | // NewAndStore 创建验证码,直接输出验证码图片内容到HTTP Response. 43 | func (s *sCaptcha) NewAndStore(ctx context.Context, name string) error { 44 | var ( 45 | request = g.RequestFromCtx(ctx) 46 | captcha = base64Captcha.NewCaptcha(captchaDriver, captchaStore) 47 | ) 48 | _, content, answer := captcha.Driver.GenerateIdQuestionAnswer() 49 | item, _ := captcha.Driver.DrawCaptcha(content) 50 | captchaStoreKey := guid.S() 51 | request.Session.Set(name, captchaStoreKey) 52 | captcha.Store.Set(captchaStoreKey, answer) 53 | _, err := item.WriteTo(request.Response.Writer) 54 | return err 55 | } 56 | 57 | // VerifyAndClear 校验验证码,并清空缓存的验证码信息 58 | func (s *sCaptcha) VerifyAndClear(r *ghttp.Request, name string, value string) bool { 59 | defer r.Session.Remove(name) 60 | captchaStoreKey := r.Session.MustGet(name).String() 61 | return captchaStore.Verify(captchaStoreKey, value, true) 62 | } 63 | -------------------------------------------------------------------------------- /internal/logic/file/file.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "focus-single/internal/service" 8 | "github.com/gogf/gf/v2/errors/gerror" 9 | "github.com/gogf/gf/v2/frame/g" 10 | "github.com/gogf/gf/v2/os/gfile" 11 | "github.com/gogf/gf/v2/os/gtime" 12 | 13 | "focus-single/internal/consts" 14 | "focus-single/internal/dao" 15 | "focus-single/internal/model" 16 | "focus-single/internal/model/entity" 17 | ) 18 | 19 | type sFile struct{} 20 | 21 | func init() { 22 | service.RegisterFile(New()) 23 | } 24 | 25 | func New() *sFile { 26 | return &sFile{} 27 | } 28 | 29 | // 同一上传文件 30 | func (s *sFile) Upload(ctx context.Context, in model.FileUploadInput) (*model.FileUploadOutput, error) { 31 | uploadPath := g.Cfg().MustGet(ctx, "upload.path").String() 32 | if uploadPath == "" { 33 | return nil, gerror.New("上传文件路径配置不存在") 34 | } 35 | if in.Name != "" { 36 | in.File.Filename = in.Name 37 | } 38 | // 同一用户1分钟之内只能上传10张图片 39 | count, err := dao.File.Ctx(ctx). 40 | Where(dao.File.Columns().UserId, service.BizCtx().Get(ctx).User.Id). 41 | WhereGTE(dao.File.Columns().CreatedAt, gtime.Now().Add(time.Minute)). 42 | Count() 43 | if err != nil { 44 | return nil, err 45 | } 46 | if count >= consts.FileMaxUploadCountMinute { 47 | return nil, gerror.New("您上传得太频繁,请稍后再操作") 48 | } 49 | dateDirName := gtime.Now().Format("Ymd") 50 | fileName, err := in.File.Save(gfile.Join(uploadPath, dateDirName), in.RandomName) 51 | if err != nil { 52 | return nil, err 53 | } 54 | // 记录到数据表 55 | data := entity.File{ 56 | Name: fileName, 57 | Src: gfile.Join(uploadPath, dateDirName, fileName), 58 | Url: "/upload/" + dateDirName + "/" + fileName, 59 | UserId: service.BizCtx().Get(ctx).User.Id, 60 | } 61 | result, err := dao.File.Ctx(ctx).Data(data).OmitEmpty().Insert() 62 | if err != nil { 63 | return nil, err 64 | } 65 | id, _ := result.LastInsertId() 66 | return &model.FileUploadOutput{ 67 | Id: uint(id), 68 | Name: data.Name, 69 | Path: data.Src, 70 | Url: data.Url, 71 | }, nil 72 | } 73 | -------------------------------------------------------------------------------- /internal/logic/logic.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package logic 6 | 7 | import ( 8 | _ "focus-single/internal/logic/bizctx" 9 | _ "focus-single/internal/logic/captcha" 10 | _ "focus-single/internal/logic/category" 11 | _ "focus-single/internal/logic/content" 12 | _ "focus-single/internal/logic/file" 13 | _ "focus-single/internal/logic/interact" 14 | _ "focus-single/internal/logic/menu" 15 | _ "focus-single/internal/logic/middleware" 16 | _ "focus-single/internal/logic/reply" 17 | _ "focus-single/internal/logic/session" 18 | _ "focus-single/internal/logic/setting" 19 | _ "focus-single/internal/logic/user" 20 | _ "focus-single/internal/logic/view" 21 | ) 22 | -------------------------------------------------------------------------------- /internal/logic/menu/menu.go: -------------------------------------------------------------------------------- 1 | package menu 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | 7 | "focus-single/internal/model" 8 | "focus-single/internal/service" 9 | ) 10 | 11 | type sMenu struct{} 12 | 13 | const settingTopMenusKey = "TopMenus" 14 | 15 | func init() { 16 | service.RegisterMenu(New()) 17 | } 18 | 19 | func New() *sMenu { 20 | return &sMenu{} 21 | } 22 | 23 | // 获取顶部菜单 24 | func (s *sMenu) SetTopMenus(ctx context.Context, menus []*model.MenuItem) error { 25 | b, err := json.Marshal(menus) 26 | if err != nil { 27 | return err 28 | } 29 | return service.Setting().Set(ctx, settingTopMenusKey, string(b)) 30 | } 31 | 32 | // 获取顶部菜单 33 | func (s *sMenu) GetTopMenus(ctx context.Context) ([]*model.MenuItem, error) { 34 | var topMenus []*model.MenuItem 35 | v, err := service.Setting().GetVar(ctx, settingTopMenusKey) 36 | if err != nil { 37 | return nil, err 38 | } 39 | err = v.Structs(&topMenus) 40 | return topMenus, err 41 | } 42 | 43 | // 根据给定的Url检索顶部菜单,给定的Url可能只是一个Url Path。 44 | func (s *sMenu) GetTopMenuByUrl(ctx context.Context, url string) (*model.MenuItem, error) { 45 | items, _ := s.GetTopMenus(ctx) 46 | for _, v := range items { 47 | if v.Url == url { 48 | return v, nil 49 | } 50 | } 51 | return nil, nil 52 | } 53 | -------------------------------------------------------------------------------- /internal/logic/setting/setting.go: -------------------------------------------------------------------------------- 1 | package setting 2 | 3 | import ( 4 | "context" 5 | 6 | "focus-single/internal/service" 7 | "github.com/gogf/gf/v2/frame/g" 8 | 9 | "focus-single/internal/dao" 10 | "focus-single/internal/model/entity" 11 | ) 12 | 13 | type sSetting struct{} 14 | 15 | func init() { 16 | service.RegisterSetting(New()) 17 | } 18 | 19 | func New() *sSetting { 20 | return &sSetting{} 21 | } 22 | 23 | // 设置KV。 24 | func (s *sSetting) Set(ctx context.Context, key, value string) error { 25 | _, err := dao.Setting.Ctx(ctx).Data(entity.Setting{ 26 | K: key, 27 | V: value, 28 | }).Save() 29 | return err 30 | } 31 | 32 | // 查询KV。 33 | func (s *sSetting) Get(ctx context.Context, key string) (string, error) { 34 | v, err := s.GetVar(ctx, key) 35 | return v.String(), err 36 | } 37 | 38 | // 查询KV,返回泛型,便于转换。 39 | func (s *sSetting) GetVar(ctx context.Context, key string) (*g.Var, error) { 40 | v, err := dao.Setting.Ctx(ctx).Fields(dao.Setting.Columns().V).Where(dao.Setting.Columns().K, key).Value() 41 | return v, err 42 | } 43 | -------------------------------------------------------------------------------- /internal/model/category.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // CategoryTreeItem 栏目树形列表 4 | type CategoryTreeItem struct { 5 | Id uint `json:"id"` // 分类ID,自增主键 6 | ParentId uint `json:"parent_id"` // 父级分类ID,用于层级管理 7 | Name string `json:"name"` // 分类名称 8 | Thumb string `json:"thumb"` // 封面图 9 | Brief string `json:"brief"` // 简述 10 | Content string `json:"content"` // 详细介绍 11 | Indent string `json:"indent"` // 缩进字符串,包含: , " │", " ├", " └" 12 | Items []*CategoryTreeItem `json:"items,omitempty"` // 子级数据项 13 | } 14 | -------------------------------------------------------------------------------- /internal/model/context.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "github.com/gogf/gf/v2/net/ghttp" 6 | ) 7 | 8 | // Context 请求上下文结构 9 | type Context struct { 10 | Session *ghttp.Session // 当前Session管理对象 11 | User *ContextUser // 上下文用户信息 12 | Data g.Map // 自定KV变量,业务模块根据需要设置,不固定 13 | } 14 | 15 | // ContextUser 请求上下文中的用户信息 16 | type ContextUser struct { 17 | Id uint // 用户ID 18 | Passport string // 用户账号 19 | Nickname string // 用户名称 20 | Avatar string // 用户头像 21 | IsAdmin bool // 是否是管理员 22 | } 23 | -------------------------------------------------------------------------------- /internal/model/do/category.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Category is the golang structure of table gf_category for DAO operations like Where/Data. 13 | type Category struct { 14 | g.Meta `orm:"table:gf_category, do:true"` 15 | Id interface{} // 分类ID,自增主键 16 | ContentType interface{} // 内容类型:topic, ask, article, reply 17 | Key interface{} // 栏目唯一键名,用于程序部分场景硬编码,一般不会用得到 18 | ParentId interface{} // 父级分类ID,用于层级管理 19 | UserId interface{} // 创建的用户ID 20 | Name interface{} // 分类名称 21 | Sort interface{} // 排序,数值越低越靠前,默认为添加时的时间戳,可用于置顶 22 | Thumb interface{} // 封面图 23 | Brief interface{} // 简述 24 | Content interface{} // 详细介绍 25 | CreatedAt *gtime.Time // 创建时间 26 | UpdatedAt *gtime.Time // 修改时间 27 | } 28 | -------------------------------------------------------------------------------- /internal/model/do/content.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Content is the golang structure of table gf_content for DAO operations like Where/Data. 13 | type Content struct { 14 | g.Meta `orm:"table:gf_content, do:true"` 15 | Id interface{} // 自增ID 16 | Key interface{} // 唯一键名,用于程序硬编码,一般不常用 17 | Type interface{} // 内容模型: topic, ask, article等,具体由程序定义 18 | CategoryId interface{} // 栏目ID 19 | UserId interface{} // 用户ID 20 | AdoptedReplyId interface{} // 采纳的回复ID,问答模块有效 21 | Title interface{} // 标题 22 | Content interface{} // 内容 23 | Sort interface{} // 排序,数值越低越靠前,默认为添加时的时间戳,可用于置顶 24 | Brief interface{} // 摘要 25 | Thumb interface{} // 缩略图 26 | Tags interface{} // 标签名称列表,以JSON存储 27 | Referer interface{} // 内容来源,例如github/gitee 28 | Status interface{} // 状态 0: 正常, 1: 禁用 29 | ReplyCount interface{} // 回复数量 30 | ViewCount interface{} // 浏览数量 31 | ZanCount interface{} // 赞 32 | CaiCount interface{} // 踩 33 | CreatedAt *gtime.Time // 创建时间 34 | UpdatedAt *gtime.Time // 修改时间 35 | } 36 | -------------------------------------------------------------------------------- /internal/model/do/file.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // File is the golang structure of table gf_file for DAO operations like Where/Data. 13 | type File struct { 14 | g.Meta `orm:"table:gf_file, do:true"` 15 | Id interface{} // 自增ID 16 | Name interface{} // 文件名称 17 | Src interface{} // 本地文件存储路径 18 | Url interface{} // URL地址,可能为空 19 | UserId interface{} // 操作用户 20 | CreatedAt *gtime.Time // 21 | } 22 | -------------------------------------------------------------------------------- /internal/model/do/interact.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Interact is the golang structure of table gf_interact for DAO operations like Where/Data. 13 | type Interact struct { 14 | g.Meta `orm:"table:gf_interact, do:true"` 15 | Id interface{} // 自增ID 16 | Type interface{} // 操作类型。0:赞,1:踩。 17 | UserId interface{} // 操作用户 18 | TargetId interface{} // 对应内容ID,该内容可能是content, reply 19 | TargetType interface{} // 内容模型: content, reply, 具体由程序定义 20 | Count interface{} // 操作数据值 21 | CreatedAt *gtime.Time // 22 | UpdatedAt *gtime.Time // 23 | } 24 | -------------------------------------------------------------------------------- /internal/model/do/reply.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Reply is the golang structure of table gf_reply for DAO operations like Where/Data. 13 | type Reply struct { 14 | g.Meta `orm:"table:gf_reply, do:true"` 15 | Id interface{} // 回复ID 16 | ParentId interface{} // 回复对应的上一级回复ID(没有的话默认为0) 17 | Title interface{} // 回复标题 18 | Content interface{} // 回复内容 19 | TargetType interface{} // 评论类型: content, reply 20 | TargetId interface{} // 对应内容ID,可能回复的是另一个回复,所以这里没有使用content_id 21 | UserId interface{} // 网站用户ID 22 | ZanCount interface{} // 赞 23 | CaiCount interface{} // 踩 24 | CreatedAt *gtime.Time // 创建时间 25 | UpdatedAt *gtime.Time // 26 | } 27 | -------------------------------------------------------------------------------- /internal/model/do/setting.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Setting is the golang structure of table gf_setting for DAO operations like Where/Data. 13 | type Setting struct { 14 | g.Meta `orm:"table:gf_setting, do:true"` 15 | K interface{} // 键名 16 | V interface{} // 键值 17 | CreatedAt *gtime.Time // 创建时间 18 | UpdatedAt *gtime.Time // 更新时间 19 | } 20 | -------------------------------------------------------------------------------- /internal/model/do/user.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // User is the golang structure of table gf_user for DAO operations like Where/Data. 13 | type User struct { 14 | g.Meta `orm:"table:gf_user, do:true"` 15 | Id interface{} // UID 16 | Passport interface{} // 账号 17 | Password interface{} // MD5密码 18 | Nickname interface{} // 昵称 19 | Avatar interface{} // 头像地址 20 | Status interface{} // 状态 0:启用 1:禁用 21 | Gender interface{} // 性别 0: 未设置 1: 男 2: 女 22 | CreatedAt *gtime.Time // 注册时间 23 | UpdatedAt *gtime.Time // 更新时间 24 | } 25 | -------------------------------------------------------------------------------- /internal/model/entity/category.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Category is the golang structure for table category. 12 | type Category struct { 13 | Id uint `json:"id" description:"分类ID,自增主键"` 14 | ContentType string `json:"contentType" description:"内容类型:topic, ask, article, reply"` 15 | Key string `json:"key" description:"栏目唯一键名,用于程序部分场景硬编码,一般不会用得到"` 16 | ParentId uint `json:"parentId" description:"父级分类ID,用于层级管理"` 17 | UserId uint `json:"userId" description:"创建的用户ID"` 18 | Name string `json:"name" description:"分类名称"` 19 | Sort uint `json:"sort" description:"排序,数值越低越靠前,默认为添加时的时间戳,可用于置顶"` 20 | Thumb string `json:"thumb" description:"封面图"` 21 | Brief string `json:"brief" description:"简述"` 22 | Content string `json:"content" description:"详细介绍"` 23 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 24 | UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"` 25 | } 26 | -------------------------------------------------------------------------------- /internal/model/entity/content.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Content is the golang structure for table content. 12 | type Content struct { 13 | Id uint `json:"id" description:"自增ID"` 14 | Key string `json:"key" description:"唯一键名,用于程序硬编码,一般不常用"` 15 | Type string `json:"type" description:"内容模型: topic, ask, article等,具体由程序定义"` 16 | CategoryId uint `json:"categoryId" description:"栏目ID"` 17 | UserId uint `json:"userId" description:"用户ID"` 18 | AdoptedReplyId uint `json:"adoptedReplyId" description:"采纳的回复ID,问答模块有效"` 19 | Title string `json:"title" description:"标题"` 20 | Content string `json:"content" description:"内容"` 21 | Sort uint `json:"sort" description:"排序,数值越低越靠前,默认为添加时的时间戳,可用于置顶"` 22 | Brief string `json:"brief" description:"摘要"` 23 | Thumb string `json:"thumb" description:"缩略图"` 24 | Tags string `json:"tags" description:"标签名称列表,以JSON存储"` 25 | Referer string `json:"referer" description:"内容来源,例如github/gitee"` 26 | Status uint `json:"status" description:"状态 0: 正常, 1: 禁用"` 27 | ReplyCount uint `json:"replyCount" description:"回复数量"` 28 | ViewCount uint `json:"viewCount" description:"浏览数量"` 29 | ZanCount uint `json:"zanCount" description:"赞"` 30 | CaiCount uint `json:"caiCount" description:"踩"` 31 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 32 | UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"` 33 | } 34 | -------------------------------------------------------------------------------- /internal/model/entity/file.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // File is the golang structure for table file. 12 | type File struct { 13 | Id uint `json:"id" description:"自增ID"` 14 | Name string `json:"name" description:"文件名称"` 15 | Src string `json:"src" description:"本地文件存储路径"` 16 | Url string `json:"url" description:"URL地址,可能为空"` 17 | UserId uint `json:"userId" description:"操作用户"` 18 | CreatedAt *gtime.Time `json:"createdAt" description:""` 19 | } 20 | -------------------------------------------------------------------------------- /internal/model/entity/interact.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Interact is the golang structure for table interact. 12 | type Interact struct { 13 | Id uint `json:"id" description:"自增ID"` 14 | Type int `json:"type" description:"操作类型。0:赞,1:踩。"` 15 | UserId uint `json:"userId" description:"操作用户"` 16 | TargetId uint `json:"targetId" description:"对应内容ID,该内容可能是content, reply"` 17 | TargetType string `json:"targetType" description:"内容模型: content, reply, 具体由程序定义"` 18 | Count uint `json:"count" description:"操作数据值"` 19 | CreatedAt *gtime.Time `json:"createdAt" description:""` 20 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 21 | } 22 | -------------------------------------------------------------------------------- /internal/model/entity/reply.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Reply is the golang structure for table reply. 12 | type Reply struct { 13 | Id uint `json:"id" description:"回复ID"` 14 | ParentId uint `json:"parentId" description:"回复对应的上一级回复ID(没有的话默认为0)"` 15 | Title string `json:"title" description:"回复标题"` 16 | Content string `json:"content" description:"回复内容"` 17 | TargetType string `json:"targetType" description:"评论类型: content, reply"` 18 | TargetId uint `json:"targetId" description:"对应内容ID,可能回复的是另一个回复,所以这里没有使用content_id"` 19 | UserId uint `json:"userId" description:"网站用户ID"` 20 | ZanCount uint `json:"zanCount" description:"赞"` 21 | CaiCount uint `json:"caiCount" description:"踩"` 22 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 23 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 24 | } 25 | -------------------------------------------------------------------------------- /internal/model/entity/setting.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Setting is the golang structure for table setting. 12 | type Setting struct { 13 | K string `json:"k" description:"键名"` 14 | V string `json:"v" description:"键值"` 15 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 16 | UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` 17 | } 18 | -------------------------------------------------------------------------------- /internal/model/entity/user.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // User is the golang structure for table user. 12 | type User struct { 13 | Id uint `json:"id" description:"UID"` 14 | Passport string `json:"passport" description:"账号"` 15 | Password string `json:"password" description:"MD5密码"` 16 | Nickname string `json:"nickname" description:"昵称"` 17 | Avatar string `json:"avatar" description:"头像地址"` 18 | Status int `json:"status" description:"状态 0:启用 1:禁用"` 19 | Gender int `json:"gender" description:"性别 0: 未设置 1: 男 2: 女"` 20 | CreatedAt *gtime.Time `json:"createdAt" description:"注册时间"` 21 | UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` 22 | } 23 | -------------------------------------------------------------------------------- /internal/model/file.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import "github.com/gogf/gf/v2/net/ghttp" 4 | 5 | // FileUploadInput 上传文件输入参数 6 | type FileUploadInput struct { 7 | File *ghttp.UploadFile // 上传文件对象 8 | Name string // 自定义文件名称 9 | RandomName bool // 是否随机命名文件 10 | } 11 | 12 | // FileUploadOutput 上传文件返回参数 13 | type FileUploadOutput struct { 14 | Id uint // 数据表ID 15 | Name string // 文件名称 16 | Path string // 本地路径 17 | Url string // 访问URL,可能只是URI 18 | } 19 | -------------------------------------------------------------------------------- /internal/model/menu.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // MenuItem 菜单数据结构 4 | type MenuItem struct { 5 | Name string // 显示名称 6 | Url string // 链接地址 7 | Icon string // 图标,可能是class,也可能是iconfont 8 | Target string // 打开方式: 空, _blank 9 | Active bool // 是否被选中 10 | Items []*MenuItem // 子级菜单 11 | } 12 | -------------------------------------------------------------------------------- /internal/model/reply.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/os/gtime" 5 | ) 6 | 7 | // ReplyCreateInput 创建内容 8 | type ReplyCreateInput struct { 9 | Title string 10 | ParentId uint // 回复对应的上一级回复ID(没有的话默认为0) 11 | TargetType string // 评论类型: topic, ask, article, reply 12 | TargetId uint // 对应内容ID 13 | Content string // 回复内容 14 | UserId uint 15 | } 16 | 17 | // ReplyGetListInput 查询回复列表 18 | type ReplyGetListInput struct { 19 | Page int // 分页码 20 | Size int // 分页数量 21 | TargetType string // 数据类型 22 | TargetId uint // 数据ID 23 | UserId uint // 用户ID 24 | } 25 | 26 | // ReplyGetListOutput 查询列表结果 27 | type ReplyGetListOutput struct { 28 | List []ReplyGetListOutputItem `json:"list"` // 列表 29 | Page int `json:"page"` // 分页码 30 | Size int `json:"size"` // 分页数量 31 | Total int `json:"total"` // 数据总数 32 | } 33 | 34 | // ReplyGetListOutputItem 查询列表结果项 35 | type ReplyGetListOutputItem struct { 36 | Reply *ReplyListItem `json:"reply"` 37 | User *ReplyListUserItem `json:"user"` 38 | Content *ContentListItem `json:"content"` 39 | Category *ContentListCategoryItem `json:"category"` 40 | } 41 | 42 | // ReplyListItem 评论列表项 43 | type ReplyListItem struct { 44 | Id uint `json:"id"` // 回复ID 45 | ParentId uint `json:"parent_id"` // 回复对应的上一级回复ID(没有的话默认为0) 46 | TargetType string `json:"target_type"` // 评论类型: topic, ask, article, reply 47 | TargetId uint `json:"target_id"` // 对应内容ID 48 | UserId uint `json:"user_id"` // 网站用户ID 49 | ZanCount uint `json:"zan_count"` // 赞 50 | CaiCount uint `json:"cai_count"` // 踩 51 | Title string `json:"title"` // 回复标题 52 | Content string `json:"content"` // 回复内容 53 | CreatedAt *gtime.Time `json:"created_at"` // 创建时间 54 | UpdatedAt *gtime.Time `json:"updated_at"` // 55 | } 56 | 57 | // ReplyListUserItem 绑定到Content列表中的用户信息 58 | type ReplyListUserItem struct { 59 | Id uint `json:"id"` // UID 60 | Nickname string `json:"nickname"` // 昵称 61 | Avatar string `json:"avatar"` // 头像地址 62 | } 63 | -------------------------------------------------------------------------------- /internal/model/session.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // SessionNotice 存放在Session中的提示信息,往往使用后则删除 4 | type SessionNotice struct { 5 | Type string // 消息类型 6 | Content string // 消息内容 7 | } 8 | -------------------------------------------------------------------------------- /internal/model/user.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // UserRegisterInput 创建用户 4 | type UserRegisterInput struct { 5 | Passport string // 账号 6 | Password string // 密码(明文) 7 | Nickname string // 昵称 8 | } 9 | 10 | type UserPasswordInput struct { 11 | OldPassword string // 原密码 12 | NewPassword string // 新密码 13 | } 14 | 15 | // UserLoginInput 用户登录 16 | type UserLoginInput struct { 17 | Passport string // 账号 18 | Password string // 密码(明文) 19 | } 20 | 21 | type UserGetProfileOutput struct { 22 | Id uint // 用户ID 23 | Nickname string // 昵称 24 | Avatar string // 头像地址 25 | Gender int // 性别 0: 未设置 1: 男 2: 女 26 | Stats map[string]int // 发布内容数量 27 | } 28 | 29 | type UserUpdateAvatarInput struct { 30 | UserId uint // 用户ID 31 | Avatar string // 头像地址 32 | } 33 | 34 | type UserUpdateProfileInput struct { 35 | UserId uint // 用户ID 36 | Nickname string // 昵称 37 | Avatar string // 头像地址 38 | Gender int // 性别 0: 未设置 1: 男 2: 女 39 | } 40 | 41 | // UserGetContentListInput 查询用户列表输入 42 | type UserGetContentListInput struct { 43 | ContentGetListInput 44 | } 45 | 46 | // UserGetListOutput 查询用户详情结果 47 | type UserGetListOutput struct { 48 | Content *ContentGetListOutput `json:"content"` // 查询用户 49 | User *UserGetProfileOutput `json:"user"` // 查询用户 50 | Stats map[string]int // 发布内容数量 51 | } 52 | 53 | type UserGetMessageListInput struct { 54 | Page int // 分页码 55 | Size int // 分页数量 56 | TargetType string // 数据类型 57 | TargetId uint // 数据ID 58 | UserId uint // 用户ID 59 | } 60 | 61 | // 查询用户列表查询结果 62 | type UserGetMessageListOutput struct { 63 | List []ReplyGetListOutputItem `json:"list"` // 列表 64 | Page int `json:"page"` // 分页码 65 | Size int `json:"size"` // 分页数量 66 | Total int `json:"total"` // 数据总数 67 | Stats map[string]int // 发布内容数量 68 | } 69 | -------------------------------------------------------------------------------- /internal/model/view.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // This is auto-generated by gf cli tool. Fill this file as you wish. 3 | // ========================================================================== 4 | 5 | package model 6 | 7 | // View 视图渲染内容对象 8 | type View struct { 9 | Title string // 页面标题 10 | Keywords string // 页面Keywords 11 | Description string // 页面Description 12 | Error string // 错误信息 13 | MainTpl string // 自定义MainTpl展示模板文件 14 | Redirect string // 引导页面跳转 15 | ContentType string // 内容模型 16 | BreadCrumb []ViewBreadCrumb // 面包屑 17 | Data interface{} // 页面参数 18 | } 19 | 20 | // ViewBreadCrumb 视图面包屑结构 21 | type ViewBreadCrumb struct { 22 | Name string // 显示名称 23 | Url string // 链接地址,当为空时表示被选中 24 | } 25 | 26 | // ViewGetBreadCrumbInput 获取面包屑请求 27 | type ViewGetBreadCrumbInput struct { 28 | ContentId uint // (可选)内容ID 29 | ContentType string // (可选)内容类型 30 | CategoryId uint // (可选)栏目ID 31 | } 32 | 33 | // ViewGetTitleInput 获取title请求 34 | type ViewGetTitleInput struct { 35 | ContentType string // (可选)内容类型 36 | CategoryId uint // (可选)栏目ID 37 | CurrentName string // (可选)当前名称 38 | } 39 | -------------------------------------------------------------------------------- /internal/packed/packed.go: -------------------------------------------------------------------------------- 1 | package packed 2 | -------------------------------------------------------------------------------- /internal/service/bizctx.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | 11 | "github.com/gogf/gf/v2/frame/g" 12 | "github.com/gogf/gf/v2/net/ghttp" 13 | ) 14 | 15 | type IBizCtx interface { 16 | Init(r *ghttp.Request, customCtx *model.Context) 17 | Get(ctx context.Context) *model.Context 18 | SetUser(ctx context.Context, ctxUser *model.ContextUser) 19 | SetData(ctx context.Context, data g.Map) 20 | } 21 | 22 | var localBizCtx IBizCtx 23 | 24 | func BizCtx() IBizCtx { 25 | if localBizCtx == nil { 26 | panic("implement not found for interface IBizCtx, forgot register?") 27 | } 28 | return localBizCtx 29 | } 30 | 31 | func RegisterBizCtx(i IBizCtx) { 32 | localBizCtx = i 33 | } 34 | -------------------------------------------------------------------------------- /internal/service/captcha.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/net/ghttp" 11 | ) 12 | 13 | type ICaptcha interface { 14 | NewAndStore(ctx context.Context, name string) error 15 | VerifyAndClear(r *ghttp.Request, name string, value string) bool 16 | } 17 | 18 | var localCaptcha ICaptcha 19 | 20 | func Captcha() ICaptcha { 21 | if localCaptcha == nil { 22 | panic("implement not found for interface ICaptcha, forgot register?") 23 | } 24 | return localCaptcha 25 | } 26 | 27 | func RegisterCaptcha(i ICaptcha) { 28 | localCaptcha = i 29 | } 30 | -------------------------------------------------------------------------------- /internal/service/category.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | "focus-single/internal/model/entity" 11 | ) 12 | 13 | type ICategory interface { 14 | GetTree(ctx context.Context, contentType string) ([]*model.CategoryTreeItem, error) 15 | GetSubIdList(ctx context.Context, id uint) ([]uint, error) 16 | GetList(ctx context.Context) (list []*entity.Category, err error) 17 | GetItem(ctx context.Context, id uint) (*entity.Category, error) 18 | GetMap(ctx context.Context) (map[uint]*entity.Category, error) 19 | } 20 | 21 | var localCategory ICategory 22 | 23 | func Category() ICategory { 24 | if localCategory == nil { 25 | panic("implement not found for interface ICategory, forgot register?") 26 | } 27 | return localCategory 28 | } 29 | 30 | func RegisterCategory(i ICategory) { 31 | localCategory = i 32 | } 33 | -------------------------------------------------------------------------------- /internal/service/content.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | ) 11 | 12 | type IContent interface { 13 | GetList(ctx context.Context, in model.ContentGetListInput) (out *model.ContentGetListOutput, err error) 14 | Search(ctx context.Context, in model.ContentSearchInput) (out *model.ContentSearchOutput, err error) 15 | GetDetail(ctx context.Context, id uint) (out *model.ContentGetDetailOutput, err error) 16 | Create(ctx context.Context, in model.ContentCreateInput) (out model.ContentCreateOutput, err error) 17 | Update(ctx context.Context, in model.ContentUpdateInput) error 18 | Delete(ctx context.Context, id uint) error 19 | AddViewCount(ctx context.Context, id uint, count int) error 20 | AddReplyCount(ctx context.Context, id uint, count int) error 21 | AdoptReply(ctx context.Context, id uint, replyID uint) error 22 | UnacceptedReply(ctx context.Context, id uint) error 23 | } 24 | 25 | var localContent IContent 26 | 27 | func Content() IContent { 28 | if localContent == nil { 29 | panic("implement not found for interface IContent, forgot register?") 30 | } 31 | return localContent 32 | } 33 | 34 | func RegisterContent(i IContent) { 35 | localContent = i 36 | } 37 | -------------------------------------------------------------------------------- /internal/service/file.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | ) 11 | 12 | type IFile interface { 13 | Upload(ctx context.Context, in model.FileUploadInput) (*model.FileUploadOutput, error) 14 | } 15 | 16 | var localFile IFile 17 | 18 | func File() IFile { 19 | if localFile == nil { 20 | panic("implement not found for interface IFile, forgot register?") 21 | } 22 | return localFile 23 | } 24 | 25 | func RegisterFile(i IFile) { 26 | localFile = i 27 | } 28 | -------------------------------------------------------------------------------- /internal/service/interact.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import "context" 8 | 9 | type IInteract interface { 10 | Zan(ctx context.Context, targetType string, targetId uint) error 11 | CancelZan(ctx context.Context, targetType string, targetId uint) error 12 | DidIZan(ctx context.Context, targetType string, targetId uint) (bool, error) 13 | Cai(ctx context.Context, targetType string, targetId uint) error 14 | CancelCai(ctx context.Context, targetType string, targetId uint) error 15 | DidICai(ctx context.Context, targetType string, targetId uint) (bool, error) 16 | } 17 | 18 | var localInteract IInteract 19 | 20 | func Interact() IInteract { 21 | if localInteract == nil { 22 | panic("implement not found for interface IInteract, forgot register?") 23 | } 24 | return localInteract 25 | } 26 | 27 | func RegisterInteract(i IInteract) { 28 | localInteract = i 29 | } 30 | -------------------------------------------------------------------------------- /internal/service/menu.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | ) 11 | 12 | type IMenu interface { 13 | SetTopMenus(ctx context.Context, menus []*model.MenuItem) error 14 | GetTopMenus(ctx context.Context) ([]*model.MenuItem, error) 15 | GetTopMenuByUrl(ctx context.Context, url string) (*model.MenuItem, error) 16 | } 17 | 18 | var localMenu IMenu 19 | 20 | func Menu() IMenu { 21 | if localMenu == nil { 22 | panic("implement not found for interface IMenu, forgot register?") 23 | } 24 | return localMenu 25 | } 26 | 27 | func RegisterMenu(i IMenu) { 28 | localMenu = i 29 | } 30 | -------------------------------------------------------------------------------- /internal/service/middleware.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import "github.com/gogf/gf/v2/net/ghttp" 8 | 9 | type IMiddleware interface { 10 | ResponseHandler(r *ghttp.Request) 11 | Ctx(r *ghttp.Request) 12 | Auth(r *ghttp.Request) 13 | } 14 | 15 | var localMiddleware IMiddleware 16 | 17 | func Middleware() IMiddleware { 18 | if localMiddleware == nil { 19 | panic("implement not found for interface IMiddleware, forgot register?") 20 | } 21 | return localMiddleware 22 | } 23 | 24 | func RegisterMiddleware(i IMiddleware) { 25 | localMiddleware = i 26 | } 27 | -------------------------------------------------------------------------------- /internal/service/reply.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | ) 11 | 12 | type IReply interface { 13 | Create(ctx context.Context, in model.ReplyCreateInput) error 14 | Delete(ctx context.Context, id uint) error 15 | DeleteByUserContentId(ctx context.Context, userId, contentId uint) error 16 | GetList(ctx context.Context, in model.ReplyGetListInput) (out *model.ReplyGetListOutput, err error) 17 | } 18 | 19 | var localReply IReply 20 | 21 | func Reply() IReply { 22 | if localReply == nil { 23 | panic("implement not found for interface IReply, forgot register?") 24 | } 25 | return localReply 26 | } 27 | 28 | func RegisterReply(i IReply) { 29 | localReply = i 30 | } 31 | -------------------------------------------------------------------------------- /internal/service/session.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | "focus-single/internal/model/entity" 11 | ) 12 | 13 | type ISession interface { 14 | SetUser(ctx context.Context, user *entity.User) error 15 | GetUser(ctx context.Context) *entity.User 16 | RemoveUser(ctx context.Context) error 17 | SetLoginReferer(ctx context.Context, referer string) error 18 | GetLoginReferer(ctx context.Context) string 19 | RemoveLoginReferer(ctx context.Context) error 20 | SetNotice(ctx context.Context, message *model.SessionNotice) error 21 | GetNotice(ctx context.Context) (*model.SessionNotice, error) 22 | RemoveNotice(ctx context.Context) error 23 | } 24 | 25 | var localSession ISession 26 | 27 | func Session() ISession { 28 | if localSession == nil { 29 | panic("implement not found for interface ISession, forgot register?") 30 | } 31 | return localSession 32 | } 33 | 34 | func RegisterSession(i ISession) { 35 | localSession = i 36 | } 37 | -------------------------------------------------------------------------------- /internal/service/setting.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/frame/g" 11 | ) 12 | 13 | type ISetting interface { 14 | Set(ctx context.Context, key, value string) error 15 | Get(ctx context.Context, key string) (string, error) 16 | GetVar(ctx context.Context, key string) (*g.Var, error) 17 | } 18 | 19 | var localSetting ISetting 20 | 21 | func Setting() ISetting { 22 | if localSetting == nil { 23 | panic("implement not found for interface ISetting, forgot register?") 24 | } 25 | return localSetting 26 | } 27 | 28 | func RegisterSetting(i ISetting) { 29 | localSetting = i 30 | } 31 | -------------------------------------------------------------------------------- /internal/service/user.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | "focus-single/internal/model/entity" 11 | ) 12 | 13 | type IUser interface { 14 | GetAvatarUploadPath() string 15 | GetAvatarUploadUrlPrefix() string 16 | Login(ctx context.Context, in model.UserLoginInput) error 17 | Logout(ctx context.Context) error 18 | EncryptPassword(passport, password string) string 19 | GetUserByPassportAndPassword(ctx context.Context, passport, password string) (user *entity.User, err error) 20 | CheckPassportUnique(ctx context.Context, passport string) error 21 | CheckNicknameUnique(ctx context.Context, nickname string) error 22 | Register(ctx context.Context, in model.UserRegisterInput) error 23 | UpdatePassword(ctx context.Context, in model.UserPasswordInput) error 24 | GetProfileById(ctx context.Context, userId uint) (out *model.UserGetProfileOutput, err error) 25 | GetProfile(ctx context.Context) (*model.UserGetProfileOutput, error) 26 | UpdateAvatar(ctx context.Context, in model.UserUpdateAvatarInput) error 27 | UpdateProfile(ctx context.Context, in model.UserUpdateProfileInput) error 28 | Disable(ctx context.Context, id uint) error 29 | GetList(ctx context.Context, in model.UserGetContentListInput) (out *model.UserGetListOutput, err error) 30 | GetMessageList(ctx context.Context, in model.UserGetMessageListInput) (out *model.UserGetMessageListOutput, err error) 31 | GetUserStats(ctx context.Context, userId uint) (map[string]int, error) 32 | IsCtxAdmin(ctx context.Context) bool 33 | IsAdmin(ctx context.Context, userId uint) bool 34 | } 35 | 36 | var localUser IUser 37 | 38 | func User() IUser { 39 | if localUser == nil { 40 | panic("implement not found for interface IUser, forgot register?") 41 | } 42 | return localUser 43 | } 44 | 45 | func RegisterUser(i IUser) { 46 | localUser = i 47 | } 48 | -------------------------------------------------------------------------------- /internal/service/view.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package service 6 | 7 | import ( 8 | "context" 9 | "focus-single/internal/model" 10 | ) 11 | 12 | type IView interface { 13 | GetBreadCrumb(ctx context.Context, in *model.ViewGetBreadCrumbInput) []model.ViewBreadCrumb 14 | GetTitle(ctx context.Context, in *model.ViewGetTitleInput) string 15 | RenderTpl(ctx context.Context, tpl string, data ...model.View) 16 | Render(ctx context.Context, data ...model.View) 17 | Render302(ctx context.Context, data ...model.View) 18 | Render401(ctx context.Context, data ...model.View) 19 | Render403(ctx context.Context, data ...model.View) 20 | Render404(ctx context.Context, data ...model.View) 21 | Render500(ctx context.Context, data ...model.View) 22 | } 23 | 24 | var localView IView 25 | 26 | func View() IView { 27 | if localView == nil { 28 | panic("implement not found for interface IView, forgot register?") 29 | } 30 | return localView 31 | } 32 | 33 | func RegisterView(i IView) { 34 | localView = i 35 | } 36 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "github.com/gogf/gf/contrib/drivers/mysql/v2" 5 | 6 | _ "github.com/gogf/gf/contrib/drivers/sqlite/v2" 7 | 8 | _ "focus-single/internal/packed" 9 | 10 | _ "focus-single/internal/logic" 11 | 12 | "focus-single/internal/cmd" 13 | 14 | "github.com/gogf/gf/v2/os/gctx" 15 | ) 16 | 17 | func main() { 18 | cmd.Main.Run(gctx.New()) 19 | } 20 | -------------------------------------------------------------------------------- /manifest/config/config.example.yaml: -------------------------------------------------------------------------------- 1 | # 配置文件的键名命名方式统一使用小驼峰。 2 | 3 | # HTTP Server. 4 | server: 5 | address: ":8199" 6 | serverRoot: "resource/public" 7 | dumpRouterMap: true 8 | routeOverWrite: true 9 | accessLogEnabled: false 10 | accessLogPattern: "access-{Ymd}.log" 11 | sessionPath: "temp/sessions" # Session文件存储目录 12 | openapiPath: "/api.json" 13 | swaggerPath: "/swagger" 14 | 15 | # 数据库连接配置 16 | database: 17 | logger: 18 | path: "temp/logs/sql" 19 | level: "all" 20 | stdout: true 21 | ctxKeys: ["RequestId"] 22 | 23 | default: 24 | # link: "mysql:root:12345678@tcp(127.0.0.1:3306)/focus" 25 | link: "sqlite::@file(manifest/document/sqlite/focus.db)" 26 | debug: true 27 | 28 | # 内容设置 29 | setting: 30 | title: "Focus聚焦社区 - Beta!" 31 | keywords: "Go,MVC,Cookie,Session,ORM,golang,cache,goframe,go frame,gf,go框架,web框架,高性能" 32 | description: "模块化、高性能、生产级的Go基础开发框架。实现了比较完善的基础设施建设,包括常用的核心开发组件, 如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、资源管理、数据校验、数据编码、文件监控、 定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、并发安全容器等等。 并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、Middleware、服务注册、配置管理、模板引擎等等, 支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。" 33 | adminIds: [1] # 管理员ID 34 | 35 | # 文件上传设置 36 | upload: 37 | path: "temp/upload" 38 | 39 | # Logger configurations. 40 | logger: 41 | path: "temp/logs/default" 42 | level: "all" 43 | stdout: true 44 | ctxKeys: ["RequestId"] 45 | 46 | # 模板引擎配置 47 | viewer: 48 | indexLayout: "index/index.html" 49 | adminHomeLayout: "admin/home.html" 50 | adminLayout: "admin/index.html" 51 | 52 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/base/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: focus-single 5 | labels: 6 | app: focus-single 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: focus-single 12 | template: 13 | metadata: 14 | labels: 15 | app: focus-single 16 | spec: 17 | containers: 18 | - name : main 19 | image: focus-single 20 | imagePullPolicy: Always 21 | 22 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - deployment.yaml 5 | - service.yaml 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/base/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: focus-single 5 | spec: 6 | ports: 7 | - port: 80 8 | protocol: TCP 9 | targetPort: 8000 10 | selector: 11 | app: focus-single 12 | 13 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/overlays/develop/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: focus-single-configmap 5 | data: 6 | config.yaml: | 7 | server: 8 | address: ":8000" 9 | openapiPath: "/api.json" 10 | swaggerPath: "/swagger" 11 | 12 | logger: 13 | level : "all" 14 | stdout: true 15 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/overlays/develop/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: focus-single 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name : main 10 | image: focus-single:develop -------------------------------------------------------------------------------- /manifest/deploy/kustomize/overlays/develop/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - ../../base 6 | - configmap.yaml 7 | 8 | patchesStrategicMerge: 9 | - deployment.yaml 10 | 11 | namespace: default 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifest/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM loads/alpine:3.8 2 | 3 | ############################################################################### 4 | # INSTALLATION 5 | ############################################################################### 6 | 7 | ENV WORKDIR /app 8 | ADD resource $WORKDIR/ 9 | ADD ./temp/linux_amd64/main $WORKDIR/main 10 | RUN chmod +x $WORKDIR/main 11 | 12 | ############################################################################### 13 | # START 14 | ############################################################################### 15 | WORKDIR $WORKDIR 16 | CMD ./main 17 | -------------------------------------------------------------------------------- /manifest/docker/docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This shell is executed before docker build. 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /manifest/document/design/focus-v0.1.0-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/design/focus-v0.1.0-beta.png -------------------------------------------------------------------------------- /manifest/document/design/focus-v0.2.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/design/focus-v0.2.0.png -------------------------------------------------------------------------------- /manifest/document/design/focus-v0.2.0.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/design/focus-v0.2.0.xmind -------------------------------------------------------------------------------- /manifest/document/design/focus-v1.0.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/design/focus-v1.0.xmind -------------------------------------------------------------------------------- /manifest/document/images/databases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/databases.png -------------------------------------------------------------------------------- /manifest/document/images/demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo1.png -------------------------------------------------------------------------------- /manifest/document/images/demo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo2.png -------------------------------------------------------------------------------- /manifest/document/images/demo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo3.png -------------------------------------------------------------------------------- /manifest/document/images/demo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo4.png -------------------------------------------------------------------------------- /manifest/document/images/demo5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo5.png -------------------------------------------------------------------------------- /manifest/document/images/demo6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo6.png -------------------------------------------------------------------------------- /manifest/document/images/demo7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo7.png -------------------------------------------------------------------------------- /manifest/document/images/demo8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/demo8.png -------------------------------------------------------------------------------- /manifest/document/images/plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/images/plan.png -------------------------------------------------------------------------------- /manifest/document/mwb/gf.mwb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/mwb/gf.mwb -------------------------------------------------------------------------------- /manifest/document/mwb/gf.mwb.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/mwb/gf.mwb.bak -------------------------------------------------------------------------------- /manifest/document/sqlite/focus.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/manifest/document/sqlite/focus.db -------------------------------------------------------------------------------- /resource/public/admin/css/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/admin/css/.gitkeep -------------------------------------------------------------------------------- /resource/public/admin/css/common.css: -------------------------------------------------------------------------------- 1 | 2 | .modal-body, .modal-body input { 3 | font-size:15px; 4 | } 5 | 6 | .modal-footer button { 7 | /*padding:5px 12px 5px 12px !important;*/ 8 | } 9 | 10 | .btn-gf { 11 | padding:5px 12px 5px 12px; 12 | } 13 | 14 | .required-mark{ 15 | color:red; 16 | } 17 | .nav-sidebar .nav-link p { 18 | transition: none !important; 19 | -webkit-animation-name: none !important; 20 | animation-name: none !important; 21 | -webkit-animation-fill-mode: none !important; 22 | animation-fill-mode: none !important; 23 | } 24 | 25 | .table thead th { 26 | font-size:15px; 27 | padding: .75rem .75rem .75rem 0; 28 | border-bottom: 1px solid #dee2e6 !important; 29 | } 30 | 31 | .table tbody td { 32 | font-size: 15px; 33 | padding: .75rem .75rem .75rem 0; 34 | border-top: none !important; 35 | border-bottom: 1px solid #dee2e6 !important; 36 | } 37 | 38 | .pagination { 39 | margin-top:20px; 40 | } 41 | 42 | section.content { 43 | padding-top:10px !important; 44 | } 45 | 46 | .brand-link { 47 | color: rgba(255,255,255,.9) !important; 48 | } 49 | 50 | .nav-treeview a, .nav-treeview a:visited, .nav-treeview a:active { 51 | padding-left:25px; 52 | font-size:15px; 53 | } 54 | 55 | .brand-link img { 56 | width: 34px !important; 57 | } 58 | 59 | .user-panel img { 60 | width: 34px !important; 61 | } 62 | 63 | /*************** 表单校验 *********************/ 64 | .validation-error-block { 65 | color: red; 66 | padding: 2px 0 0 12px; 67 | width: 100%; 68 | } -------------------------------------------------------------------------------- /resource/public/admin/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/admin/images/.gitkeep -------------------------------------------------------------------------------- /resource/public/admin/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/admin/js/.gitkeep -------------------------------------------------------------------------------- /resource/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/favicon.ico -------------------------------------------------------------------------------- /resource/public/images/avatar/avatar1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/avatar/avatar1.jpg -------------------------------------------------------------------------------- /resource/public/images/avatar/avatar2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/avatar/avatar2.jpg -------------------------------------------------------------------------------- /resource/public/images/avatar/avatar3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/avatar/avatar3.jpg -------------------------------------------------------------------------------- /resource/public/images/avatar/avatar4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/avatar/avatar4.jpg -------------------------------------------------------------------------------- /resource/public/images/error/error_401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/error/error_401.png -------------------------------------------------------------------------------- /resource/public/images/error/error_403.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/error/error_403.png -------------------------------------------------------------------------------- /resource/public/images/error/error_404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/error/error_404.png -------------------------------------------------------------------------------- /resource/public/images/error/error_500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/error/error_500.png -------------------------------------------------------------------------------- /resource/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/images/logo.png -------------------------------------------------------------------------------- /resource/public/plugin/bootstrap-dialog/bootstrap-dialog-common.js: -------------------------------------------------------------------------------- 1 | // 提示框 2 | dialog = { 3 | Alert: function (message, handler) { 4 | handler = handler || null; 5 | BootstrapDialog.alert({ 6 | title: '提示', 7 | message: message, 8 | callback: function () { 9 | if (handler != null) dialog.f(handler); 10 | } 11 | }); 12 | }, 13 | //成功信息SucceedInfo 14 | Succeed: function (message, handler) { 15 | handler = handler || null; 16 | BootstrapDialog.show({ 17 | type: BootstrapDialog.TYPE_SUCCESS, 18 | title: '信息', 19 | message: message, 20 | buttons: [{ 21 | label: '确认', 22 | action: function (dialog) { 23 | if (handler != null) dialog.f(handler); 24 | dialog.close(); 25 | } 26 | }] 27 | }); 28 | }, 29 | //失败信息ErrorInfo 30 | Error: function (message, handler) { 31 | handler = handler || null; 32 | BootstrapDialog.show({ 33 | type: BootstrapDialog.TYPE_DANGER, 34 | title: '信息', 35 | message: message, 36 | buttons: [{ 37 | label: '确认', 38 | action: function (dialog) { 39 | if (handler != null) dialog.f(handler); 40 | dialog.close(); 41 | } 42 | }] 43 | }); 44 | }, 45 | //询问信息 46 | Confirm: function (message, ok_fun, cancel_fun) { 47 | BootstrapDialog.confirm(message, function (result) { 48 | if (result) { 49 | dialog.f(ok_fun); 50 | } else { 51 | if (cancel_fun != null) { 52 | dialog.f(cancel_fun); 53 | } 54 | } 55 | }); 56 | }, 57 | EmptyFunc: function () { 58 | return; 59 | }, 60 | f: function (fn) { 61 | fn(); 62 | } 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /resource/public/plugin/bootstrap-dialog/bootstrap-dialog.min.css: -------------------------------------------------------------------------------- 1 | .bootstrap-dialog .modal-header{border-top-left-radius:4px;border-top-right-radius:4px}.bootstrap-dialog .bootstrap-dialog-title{color:#fff;display:inline-block;font-size:16px}.bootstrap-dialog .bootstrap-dialog-message{font-size:14px}.bootstrap-dialog .bootstrap-dialog-button-icon{margin-right:3px}.bootstrap-dialog .bootstrap-dialog-close-button{font-size:20px;float:right;opacity:.9;filter:alpha(opacity=90)}.bootstrap-dialog .bootstrap-dialog-close-button:hover{cursor:pointer;opacity:1;filter:alpha(opacity=100)}@media(min-width:1172px){.bootstrap-dialog .modal-xl{max-width:95%}}.bootstrap-dialog .modal-lg .bootstrap4-dialog-button:first-child{margin-top:8px}.bootstrap-dialog.type-default .modal-header{background-color:#fff}.bootstrap-dialog.type-default .bootstrap-dialog-title{color:#333}.bootstrap-dialog.type-info .modal-header{background-color:#17a2b8}.bootstrap-dialog.type-primary .modal-header{background-color:#007bff}.bootstrap-dialog.type-secondary .modal-header{background-color:#6c757d}.bootstrap-dialog.type-success .modal-header{background-color:#28a745}.bootstrap-dialog.type-warning .modal-header{background-color:#ffc107}.bootstrap-dialog.type-danger .modal-header{background-color:#dc3545}.bootstrap-dialog.type-light .modal-header{background-color:#f8f9fa}.bootstrap-dialog.type-dark .modal-header{background-color:#343a40}.bootstrap-dialog.size-large .bootstrap-dialog-title{font-size:24px}.bootstrap-dialog.size-large .bootstrap-dialog-close-button{font-size:30px}.bootstrap-dialog.size-large .bootstrap-dialog-message{font-size:18px}.bootstrap-dialog .icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.bootstrap-dialog-footer-buttons{display:flex}@-moz-keyframes spin{0{-moz-transform:rotate(0)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0{-o-transform:rotate(0)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0{-ms-transform:rotate(0)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0{transform:rotate(0)}100%{transform:rotate(359deg)}}.bootstrap-dialog-header{display:contents} -------------------------------------------------------------------------------- /resource/public/plugin/bootstrap-dialog/common-demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | gf bbs 23 | 24 | 25 | 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 |
34 | 35 |
36 |
37 | 38 |
39 |
40 | 43 |
44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /resource/public/plugin/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/iconfont/iconfont.eot -------------------------------------------------------------------------------- /resource/public/plugin/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /resource/public/plugin/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/iconfont/iconfont.woff -------------------------------------------------------------------------------- /resource/public/plugin/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/css/content-theme/light.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vditor - A markdown editor written in TypeScript. 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2018-present B3log 开源, b3log.org 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | * 26 | */.vditor-reset h1,.vditor-reset h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.vditor-reset hr{background-color:#eaecef}.vditor-reset blockquote{color:#6a737d;border-left:.25em solid #eaecef}.vditor-reset iframe{border:1px solid #d1d5da}.vditor-reset table tr{border-top:1px solid #c6cbd1;background-color:#fafbfc}.vditor-reset table td,.vditor-reset table th{border:1px solid #dfe2e5}.vditor-reset table tbody tr:nth-child(2n){background-color:#fff}.vditor-reset code:not(.hljs):not(.highlight-chroma){background-color:rgba(27,31,35,.05)}.vditor-reset kbd{color:#24292e;background-color:#fafbfc;border:1px solid #d1d5da;box-shadow:inset 0 -1px 0 #d1d5da}.vditor-speech{background-color:#f6f8fa;border:1px solid #d1d5da;color:#586069}.vditor-speech--current,.vditor-speech:hover{color:#4285f4}.vditor-linkcard a{background-color:#f6f8fa}.vditor-linkcard a:visited .vditor-linkcard__abstract{color:rgba(88,96,105,.36)}.vditor-linkcard__title{color:#24292e}.vditor-linkcard__abstract{color:#586069}.vditor-linkcard__site{color:#4285f4}.vditor-linkcard__image{background-color:rgba(88,96,105,.36)} -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/b3log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/b3log.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/chainbook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/chainbook.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/doge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/doge.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/hacpai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/hacpai.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/huaji.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/huaji.gif -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/latke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/latke.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/lute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/lute.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/octocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/octocat.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/pipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/pipe.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/solo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/solo.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/sym.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/sym.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/trollface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/trollface.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/vditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/vditor.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/wide.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/emoji/wulian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/emoji/wulian.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/img-loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/images/logo.png -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import VditorMethod from "./method"; 3 | declare class Vditor extends VditorMethod { 4 | readonly version: string; 5 | vditor: IVditor; 6 | /** 7 | * @param id 要挂载 Vditor 的元素或者元素 ID。 8 | * @param options Vditor 参数 9 | */ 10 | constructor(id: string | HTMLElement, options?: IOptions); 11 | /** 设置主题 */ 12 | setTheme(theme: "dark" | "classic", contentTheme?: string, codeTheme?: string, contentThemePath?: string): void; 13 | /** 获取 Markdown 内容 */ 14 | getValue(): string; 15 | /** 获取编辑器当前编辑模式 */ 16 | getCurrentMode(): "wysiwyg" | "sv" | "ir"; 17 | /** 聚焦到编辑器 */ 18 | focus(): void; 19 | /** 让编辑器失焦 */ 20 | blur(): void; 21 | /** 禁用编辑器 */ 22 | disabled(): void; 23 | /** 解除编辑器禁用 */ 24 | enable(): void; 25 | /** 返回选中的字符串 */ 26 | getSelection(): string; 27 | /** 设置预览区域内容 */ 28 | renderPreview(value?: string): void; 29 | /** 获取焦点位置 */ 30 | getCursorPosition(): { 31 | left: number; 32 | top: number; 33 | }; 34 | /** 上传是否还在进行中 */ 35 | isUploading(): boolean; 36 | /** 清除缓存 */ 37 | clearCache(): void; 38 | /** 禁用缓存 */ 39 | disabledCache(): void; 40 | /** 启用缓存 */ 41 | enableCache(): void; 42 | /** HTML 转 md */ 43 | html2md(value: string): string; 44 | /** 获取 HTML */ 45 | getHTML(): string; 46 | /** 消息提示。time 为 0 将一直显示 */ 47 | tip(text: string, time?: number): void; 48 | /** 设置预览模式 */ 49 | setPreviewMode(mode: "both" | "editor"): void; 50 | /** 删除选中内容 */ 51 | deleteValue(): void; 52 | /** 更新选中内容 */ 53 | updateValue(value: string): void; 54 | /** 在焦点处插入内容,并默认进行 Markdown 渲染 */ 55 | insertValue(value: string, render?: boolean): void; 56 | /** 设置编辑器内容 */ 57 | setValue(markdown: string, clearStack?: boolean): void; 58 | /** 清空 undo & redo 栈 */ 59 | clearStack(): void; 60 | /** 销毁编辑器 */ 61 | destroy(): void; 62 | /** 获取评论 ID */ 63 | getCommentIds(): ICommentsData[]; 64 | /** 高亮评论 */ 65 | hlCommentIds(ids: string[]): void; 66 | /** 取消评论高亮 */ 67 | unHlCommentIds(ids: string[]): void; 68 | /** 删除评论 */ 69 | removeCommentIds(removeIds: string[]): void; 70 | } 71 | export default Vditor; 72 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/highlight.js/styles/algol_nu.css: -------------------------------------------------------------------------------- 1 | .highlight-chroma{background-color:#fff}.highlight-chroma .highlight-lntd{vertical-align:top;padding:0;margin:0;border:0}.highlight-chroma .highlight-lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.highlight-chroma .highlight-hl{display:block;width:100%;background-color:#e5e5e5}.highlight-chroma .highlight-ln,.highlight-chroma .highlight-lnt{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.highlight-chroma .highlight-k,.highlight-chroma .highlight-kc{font-weight:700}.highlight-chroma .highlight-kd{font-weight:700;font-style:italic}.highlight-chroma .highlight-kn,.highlight-chroma .highlight-kp,.highlight-chroma .highlight-kr,.highlight-chroma .highlight-kt{font-weight:700}.highlight-chroma .highlight-bp,.highlight-chroma .highlight-nb{font-weight:700;font-style:italic}.highlight-chroma .highlight-nc,.highlight-chroma .highlight-nf,.highlight-chroma .highlight-nn,.highlight-chroma .highlight-no,.highlight-chroma .highlight-nv{color:#666;font-weight:700;font-style:italic}.highlight-chroma .highlight-dl,.highlight-chroma .highlight-s,.highlight-chroma .highlight-s1,.highlight-chroma .highlight-s2,.highlight-chroma .highlight-sa,.highlight-chroma .highlight-sb,.highlight-chroma .highlight-sc,.highlight-chroma .highlight-sd,.highlight-chroma .highlight-se,.highlight-chroma .highlight-sh,.highlight-chroma .highlight-si,.highlight-chroma .highlight-sr,.highlight-chroma .highlight-ss,.highlight-chroma .highlight-sx{color:#666;font-style:italic}.highlight-chroma .highlight-ow{font-weight:700}.highlight-chroma .highlight-c,.highlight-chroma .highlight-c1,.highlight-chroma .highlight-ch,.highlight-chroma .highlight-cm{color:#888;font-style:italic}.highlight-chroma .highlight-cp,.highlight-chroma .highlight-cpf,.highlight-chroma .highlight-cs{color:#888;font-weight:700}.hljs{display:block;overflow-x:auto;padding:.5em;background:#fff;color:#000}.hljs-addition,.hljs-attribute,.hljs-bullet,.hljs-link,.hljs-section,.hljs-string,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#888}.hljs-comment,.hljs-deletion,.hljs-meta,.hljs-quote{color:#ccc}.hljs-keyword,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-strong,.hljs-type{font-weight:700}.hljs-emphasis{font-style:italic} -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/highlight.js/styles/igor.css: -------------------------------------------------------------------------------- 1 | .highlight-chroma{background-color:#fff}.highlight-chroma .highlight-lntd{vertical-align:top;padding:0;margin:0;border:0}.highlight-chroma .highlight-lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.highlight-chroma .highlight-hl{display:block;width:100%;background-color:#e5e5e5}.highlight-chroma .highlight-ln,.highlight-chroma .highlight-lnt{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.highlight-chroma .highlight-k,.highlight-chroma .highlight-kc,.highlight-chroma .highlight-kd,.highlight-chroma .highlight-kn,.highlight-chroma .highlight-kp,.highlight-chroma .highlight-kr,.highlight-chroma .highlight-kt{color:#00f}.highlight-chroma .highlight-nc{color:#007575}.highlight-chroma .highlight-nd{color:#cc00a3}.highlight-chroma .highlight-nf{color:#c34e00}.highlight-chroma .highlight-dl,.highlight-chroma .highlight-s,.highlight-chroma .highlight-s1,.highlight-chroma .highlight-s2,.highlight-chroma .highlight-sa,.highlight-chroma .highlight-sb,.highlight-chroma .highlight-sc,.highlight-chroma .highlight-sd,.highlight-chroma .highlight-se,.highlight-chroma .highlight-sh,.highlight-chroma .highlight-si,.highlight-chroma .highlight-sr,.highlight-chroma .highlight-ss,.highlight-chroma .highlight-sx{color:#009c00}.highlight-chroma .highlight-c,.highlight-chroma .highlight-c1,.highlight-chroma .highlight-ch,.highlight-chroma .highlight-cm,.highlight-chroma .highlight-cp,.highlight-chroma .highlight-cpf,.highlight-chroma .highlight-cs{color:red;font-style:italic}.hljs{display:block;overflow-x:auto;padding:.5em;background:#fff}.hljs,.hljs-emphasis,.hljs-strong,.hljs-subst,.hljs-tag,.hljs-title{color:#000}.hljs-bullet,.hljs-literal,.hljs-number,.hljs-quote,.hljs-regexp{color:navy}.hljs-code .hljs-selector-class{color:purple}.hljs-emphasis,.hljs-stronge,.hljs-type{font-style:italic}.hljs-function,.hljs-keyword,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-symbol{color:olive}.hljs-attribute{color:maroon}.hljs-class .hljs-title,.hljs-params,.hljs-variable{color:#0055af}.hljs-addition,.hljs-built_in,.hljs-builtin-name,.hljs-comment,.hljs-deletion,.hljs-link,.hljs-meta,.hljs-selector-attr,.hljs-selector-id,.hljs-selector-pseudo,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-type{color:green} -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/highlight.js/styles/vs.css: -------------------------------------------------------------------------------- 1 | .highlight-chroma{background-color:#fff}.highlight-chroma .highlight-lntd{vertical-align:top;padding:0;margin:0;border:0}.highlight-chroma .highlight-lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.highlight-chroma .highlight-hl{display:block;width:100%;background-color:#e5e5e5}.highlight-chroma .highlight-ln,.highlight-chroma .highlight-lnt{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.highlight-chroma .highlight-k,.highlight-chroma .highlight-kc,.highlight-chroma .highlight-kd,.highlight-chroma .highlight-kn,.highlight-chroma .highlight-kp,.highlight-chroma .highlight-kr{color:#00f}.highlight-chroma .highlight-kt,.highlight-chroma .highlight-nc{color:#2b91af}.highlight-chroma .highlight-dl,.highlight-chroma .highlight-s,.highlight-chroma .highlight-s1,.highlight-chroma .highlight-s2,.highlight-chroma .highlight-sa,.highlight-chroma .highlight-sb,.highlight-chroma .highlight-sc,.highlight-chroma .highlight-sd,.highlight-chroma .highlight-se,.highlight-chroma .highlight-sh,.highlight-chroma .highlight-si,.highlight-chroma .highlight-sr,.highlight-chroma .highlight-ss,.highlight-chroma .highlight-sx{color:#a31515}.highlight-chroma .highlight-ow{color:#00f}.highlight-chroma .highlight-c,.highlight-chroma .highlight-c1,.highlight-chroma .highlight-ch,.highlight-chroma .highlight-cm,.highlight-chroma .highlight-cs{color:green}.highlight-chroma .highlight-cp,.highlight-chroma .highlight-cpf{color:#00f}.highlight-chroma .highlight-ge{font-style:italic}.highlight-chroma .highlight-gh,.highlight-chroma .highlight-gp,.highlight-chroma .highlight-gs,.highlight-chroma .highlight-gu{font-weight:700}.hljs{display:block;overflow-x:auto;padding:.5em;background:#fff;color:#000}.hljs-comment,.hljs-quote,.hljs-variable{color:green}.hljs-built_in,.hljs-keyword,.hljs-name,.hljs-selector-tag,.hljs-tag{color:#00f}.hljs-addition,.hljs-attribute,.hljs-literal,.hljs-section,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type{color:#a31515}.hljs-deletion,.hljs-meta,.hljs-selector-attr,.hljs-selector-pseudo{color:#2b91af}.hljs-doctag{color:grey}.hljs-attr{color:red}.hljs-bullet,.hljs-link,.hljs-symbol{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_AMS-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_AMS-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_AMS-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_AMS-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_AMS-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_AMS-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Bold.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Bold.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Bold.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Fraktur-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Bold.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Bold.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Bold.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-BoldItalic.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-BoldItalic.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-BoldItalic.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Italic.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Italic.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Italic.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Main-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-BoldItalic.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-BoldItalic.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-BoldItalic.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-Italic.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-Italic.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Math-Italic.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Bold.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Bold.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Bold.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Italic.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Italic.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Italic.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_SansSerif-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Script-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Script-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Script-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Script-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Script-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Script-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size1-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size1-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size1-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size1-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size1-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size2-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size2-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size2-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size2-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size2-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size3-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size3-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size3-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size3-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size3-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size3-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size4-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size4-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size4-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size4-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Size4-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Typewriter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Typewriter-Regular.ttf -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Typewriter-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Typewriter-Regular.woff -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Typewriter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gogf/focus-single/d9034a0b417e8cf311fae2157f08fa29b5dd9372/resource/public/plugin/vditor/dist/js/katex/fonts/KaTeX_Typewriter-Regular.woff2 -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/mathjax/input/tex/extensions/noerrors.js: -------------------------------------------------------------------------------- 1 | !function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}r.m=n,r.c=o,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=3)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isObject=MathJax._.components.global.isObject,t.combineConfig=MathJax._.components.global.combineConfig,t.combineDefaults=MathJax._.components.global.combineDefaults,t.combineWithMathJax=MathJax._.components.global.combineWithMathJax,t.MathJax=MathJax._.components.global.MathJax},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(2);t.NoErrorsConfiguration=o.Configuration.create("noerrors",{nodes:{error:function(e,t,n,o){var r=e.create("token","mtext",{},o.replace(/\n/g," "));return e.create("node","merror",[r],{"data-mjx-error":t})}}})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Configuration=MathJax._.input.tex.Configuration.Configuration,t.ConfigurationHandler=MathJax._.input.tex.Configuration.ConfigurationHandler},function(e,t,n){"use strict";n.r(t);var o=n(0),r=n(1);Object(o.combineWithMathJax)({_:{input:{tex:{noerrors:{NoErrorsConfiguration:r}}}}})}]); -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/js/mathjax/input/tex/extensions/noundefined.js: -------------------------------------------------------------------------------- 1 | !function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}r.m=n,r.c=o,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=3)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isObject=MathJax._.components.global.isObject,t.combineConfig=MathJax._.components.global.combineConfig,t.combineDefaults=MathJax._.components.global.combineDefaults,t.combineWithMathJax=MathJax._.components.global.combineWithMathJax,t.MathJax=MathJax._.components.global.MathJax},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(2);t.NoUndefinedConfiguration=o.Configuration.create("noundefined",{fallback:{macro:function(e,t){var n=e.create("text","\\"+t);e.Push(e.create("node","mtext",[],{mathcolor:"red"},n))}}})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Configuration=MathJax._.input.tex.Configuration.Configuration,t.ConfigurationHandler=MathJax._.input.tex.Configuration.ConfigurationHandler},function(e,t,n){"use strict";n.r(t);var o=n(0),r=n(1);Object(o.combineWithMathJax)({_:{input:{tex:{noundefined:{NoUndefinedConfiguration:r}}}}})}]); -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/method.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare class Vditor { 3 | /** 为 element 中的代码块添加复制按钮 */ 4 | static codeRender: (element: HTMLElement, lang?: "en_US" | "ja_JP" | "ko_KR" | "zh_CN") => void; 5 | /** 对 graphviz 进行渲染 */ 6 | static graphvizRender: (element: HTMLElement, cdn?: string) => void; 7 | /** 为 element 中的代码块进行高亮渲染 */ 8 | static highlightRender: (hljsOption?: IHljs, element?: HTMLElement | Document, cdn?: string) => void; 9 | /** 对数学公式进行渲染 */ 10 | static mathRender: (element: HTMLElement, options?: { 11 | cdn?: string; 12 | math?: IMath; 13 | }) => void; 14 | /** 流程图/时序图/甘特图渲染 */ 15 | static mermaidRender: (element: HTMLElement, cdn: string, theme: string) => void; 16 | /** flowchart.js 渲染 */ 17 | static flowchartRender: (element: HTMLElement, cdn?: string) => void; 18 | /** 图表渲染 */ 19 | static chartRender: (element: HTMLElement | Document, cdn: string, theme: string) => void; 20 | /** 五线谱渲染 */ 21 | static abcRender: (element?: HTMLElement | Document, cdn?: string) => void; 22 | /** 脑图渲染 */ 23 | static mindmapRender: (element: HTMLElement | Document, cdn: string, theme: string) => void; 24 | /** 大纲渲染 */ 25 | static outlineRender: (contentElement: HTMLElement, targetElement: Element, vditor?: IVditor) => string; 26 | /** 为[特定链接](https://github.com/Vanessa219/vditor/issues/7)分别渲染为视频、音频、嵌入的 iframe */ 27 | static mediaRender: (element: HTMLElement) => void; 28 | /** 对选中的文字进行阅读 */ 29 | static speechRender: (element: HTMLElement, lang?: "en_US" | "ja_JP" | "ko_KR" | "zh_CN") => void; 30 | /** 对图片进行懒加载 */ 31 | static lazyLoadImageRender: (element?: HTMLElement | Document) => boolean; 32 | /** Markdown 文本转换为 HTML,该方法需使用[异步编程](https://ld246.com/article/1546828434083?r=Vaness) */ 33 | static md2html: (mdText: string, options?: IPreviewOptions) => Promise; 34 | /** 页面 Markdown 文章渲染 */ 35 | static preview: (previewElement: HTMLDivElement, markdown: string, options?: IPreviewOptions) => Promise; 36 | /** 设置代码主题 */ 37 | static setCodeTheme: (codeTheme: string, cdn?: string) => void; 38 | /** 设置内容主题 */ 39 | static setContentTheme: (contentTheme: string, path: string) => void; 40 | } 41 | export default Vditor; 42 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/constants.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare const _VDITOR_VERSION: string; 3 | export { _VDITOR_VERSION as VDITOR_VERSION }; 4 | export declare abstract class Constants { 5 | static readonly ZWSP: string; 6 | static readonly MOBILE_WIDTH: number; 7 | static readonly CLASS_MENU_DISABLED: string; 8 | static readonly EDIT_TOOLBARS: string[]; 9 | static readonly CODE_THEME: string[]; 10 | static readonly CODE_LANGUAGES: string[]; 11 | static readonly CDN: string; 12 | static readonly MARKDOWN_OPTIONS: { 13 | autoSpace: boolean; 14 | chinesePunct: boolean; 15 | codeBlockPreview: boolean; 16 | fixTermTypo: boolean; 17 | footnotes: boolean; 18 | linkBase: string; 19 | linkPrefix: string; 20 | listStyle: boolean; 21 | mark: boolean; 22 | mathBlockPreview: boolean; 23 | paragraphBeginningSpace: boolean; 24 | sanitize: boolean; 25 | toc: boolean; 26 | }; 27 | static readonly HLJS_OPTIONS: { 28 | enable: boolean; 29 | lineNumber: boolean; 30 | style: string; 31 | }; 32 | static readonly MATH_OPTIONS: IMath; 33 | static readonly THEME_OPTIONS: { 34 | current: string; 35 | list: { 36 | "ant-design": string; 37 | dark: string; 38 | light: string; 39 | wechat: string; 40 | }; 41 | path: string; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/devtools/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class DevTools { 3 | element: HTMLDivElement; 4 | private ASTChart; 5 | constructor(); 6 | renderEchart(vditor: IVditor): void; 7 | } 8 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/export/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const download: (vditor: IVditor, content: string, filename: string) => void; 3 | export declare const exportMarkdown: (vditor: IVditor) => void; 4 | export declare const exportPDF: (vditor: IVditor) => void; 5 | export declare const exportHTML: (vditor: IVditor) => void; 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/hint/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class Hint { 3 | timeId: number; 4 | element: HTMLDivElement; 5 | recentLanguage: string; 6 | private splitChar; 7 | private lastIndex; 8 | constructor(hintExtends: IHintExtend[]); 9 | render(vditor: IVditor): void; 10 | genHTML(data: IHintData[], key: string, vditor: IVditor): void; 11 | fillEmoji: (element: HTMLElement, vditor: IVditor) => void; 12 | select(event: KeyboardEvent, vditor: IVditor): boolean; 13 | private getKey; 14 | } 15 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/i18n/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const i18n: II18n; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ir/expandMarker.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const expandMarker: (range: Range, vditor: IVditor) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ir/highlightToolbarIR.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const highlightToolbarIR: (vditor: IVditor) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ir/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare class IR { 3 | element: HTMLPreElement; 4 | processTimeoutId: number; 5 | hlToolbarTimeoutId: number; 6 | composingLock: boolean; 7 | preventInput: boolean; 8 | constructor(vditor: IVditor); 9 | private copy; 10 | private bindEvent; 11 | } 12 | export { IR }; 13 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ir/input.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const input: (vditor: IVditor, range: Range, ignoreSpace?: boolean, event?: InputEvent) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ir/process.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const processHint: (vditor: IVditor) => void; 3 | export declare const processAfterRender: (vditor: IVditor, options?: { 4 | enableAddUndoStack: boolean; 5 | enableHint: boolean; 6 | enableInput: boolean; 7 | }) => void; 8 | export declare const processHeading: (vditor: IVditor, value: string) => void; 9 | export declare const processToolbar: (vditor: IVditor, actionBtn: Element, prefix: string, suffix: string) => void; 10 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ir/processKeydown.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const processKeydown: (vditor: IVditor, event: KeyboardEvent) => boolean; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/abcRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const abcRender: (element?: (HTMLElement | Document), cdn?: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/anchorRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const anchorRender: (type: number) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/chartRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const chartRender: (element: (HTMLElement | Document), cdn: string, theme: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/codeRender.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const codeRender: (element: HTMLElement, lang?: keyof II18n) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/flowchartRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const flowchartRender: (element: HTMLElement, cdn?: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/getHTML.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const getHTML: (vditor: IVditor) => string; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/getMarkdown.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const getMarkdown: (vditor: IVditor) => string; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/graphvizRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const graphvizRender: (element: HTMLElement, cdn?: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/highlightRender.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const highlightRender: (hljsOption?: IHljs, element?: HTMLElement | Document, cdn?: string) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/lazyLoadImageRender.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | interface Window { 3 | vditorImageIntersectionObserver: IntersectionObserver; 4 | } 5 | } 6 | export declare const lazyLoadImageRender: (element?: (HTMLElement | Document)) => boolean; 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/mathRender.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare global { 3 | interface Window { 4 | MathJax: any; 5 | } 6 | } 7 | export declare const mathRender: (element: HTMLElement, options?: { 8 | cdn?: string; 9 | math?: IMath; 10 | }) => void; 11 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/mediaRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const mediaRender: (element: HTMLElement) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/mermaidRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const mermaidRender: (element: HTMLElement, cdn: string, theme: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/mindmapRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare const mindmapRender: (element: (HTMLElement | Document), cdn: string, theme: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/outlineRender.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const outlineRender: (contentElement: HTMLElement, targetElement: Element, vditor?: IVditor) => string; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/previewRender.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const md2html: (mdText: string, options?: IPreviewOptions) => Promise; 3 | export declare const previewRender: (previewElement: HTMLDivElement, markdown: string, options?: IPreviewOptions) => Promise; 4 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/setLute.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const setLute: (options: ILuteOptions) => Lute; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/markdown/speechRender.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare global { 3 | interface Window { 4 | vditorSpeechRange: Range; 5 | } 6 | } 7 | export declare const speechRender: (element: HTMLElement, lang?: keyof II18n) => void; 8 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/outline/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class Outline { 3 | element: HTMLElement; 4 | constructor(outlineLabel: string); 5 | render(vditor: IVditor): string; 6 | toggle(vditor: IVditor, show?: boolean): void; 7 | } 8 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/preview/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class Preview { 3 | element: HTMLElement; 4 | private mdTimeoutId; 5 | constructor(vditor: IVditor); 6 | render(vditor: IVditor, value?: string): void; 7 | private afterRender; 8 | private copyToX; 9 | } 10 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/resize/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class Resize { 3 | element: HTMLElement; 4 | constructor(vditor: IVditor); 5 | private bindEvent; 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/sv/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare class Editor { 3 | element: HTMLPreElement; 4 | composingLock: boolean; 5 | processTimeoutId: number; 6 | hlToolbarTimeoutId: number; 7 | preventInput: boolean; 8 | constructor(vditor: IVditor); 9 | private copy; 10 | private bindEvent; 11 | } 12 | export { Editor }; 13 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/sv/inputEvent.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const inputEvent: (vditor: IVditor, event?: InputEvent) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/sv/process.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const processPaste: (vditor: IVditor, text: string) => void; 3 | export declare const getSideByType: (spanNode: Node, type: string, isPrevious?: boolean) => false | Element; 4 | export declare const processSpinVditorSVDOM: (html: string, vditor: IVditor) => string; 5 | export declare const processPreviousMarkers: (spanElement: HTMLElement) => string; 6 | export declare const processAfterRender: (vditor: IVditor, options?: { 7 | enableAddUndoStack: boolean; 8 | enableHint: boolean; 9 | enableInput: boolean; 10 | }) => void; 11 | export declare const processHeading: (vditor: IVditor, value: string) => void; 12 | export declare const processToolbar: (vditor: IVditor, actionBtn: Element, prefix: string, suffix: string) => void; 13 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/sv/processKeydown.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const processKeydown: (vditor: IVditor, event: KeyboardEvent) => boolean; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/tip/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare class Tip { 2 | element: HTMLElement; 3 | constructor(); 4 | show(text: string, time?: number): void; 5 | hide(): void; 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Both.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Both extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Br.d.ts: -------------------------------------------------------------------------------- 1 | export declare class Br { 2 | element: HTMLElement; 3 | constructor(); 4 | } 5 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/CodeTheme.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class CodeTheme extends MenuItem { 4 | element: HTMLElement; 5 | constructor(vditor: IVditor, menuItem: IMenuItem); 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/ContentTheme.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class ContentTheme extends MenuItem { 4 | element: HTMLElement; 5 | constructor(vditor: IVditor, menuItem: IMenuItem); 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Counter.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class Counter { 3 | element: HTMLElement; 4 | constructor(vditor: IVditor); 5 | render(vditor: IVditor, mdText: string): void; 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Custom.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Custom extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Devtools.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Devtools extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Divider.d.ts: -------------------------------------------------------------------------------- 1 | export declare class Divider { 2 | element: HTMLElement; 3 | constructor(); 4 | } 5 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/EditMode.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare const setEditMode: (vditor: IVditor, type: string, event: Event | string) => void; 4 | export declare class EditMode extends MenuItem { 5 | element: HTMLElement; 6 | constructor(vditor: IVditor, menuItem: IMenuItem); 7 | _bindEvent(vditor: IVditor, panelElement: HTMLElement, menuItem: IMenuItem): void; 8 | } 9 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Emoji.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Emoji extends MenuItem { 4 | element: HTMLElement; 5 | constructor(vditor: IVditor, menuItem: IMenuItem); 6 | _bindEvent(vditor: IVditor, panelElement: HTMLElement): void; 7 | } 8 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Export.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Export extends MenuItem { 4 | element: HTMLElement; 5 | constructor(vditor: IVditor, menuItem: IMenuItem); 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Fullscreen.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Fullscreen extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | _bindEvent(vditor: IVditor, menuItem: IMenuItem): void; 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Headings.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Headings extends MenuItem { 4 | element: HTMLElement; 5 | constructor(vditor: IVditor, menuItem: IMenuItem); 6 | _bindEvent(vditor: IVditor, panelElement: HTMLElement): void; 7 | } 8 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Help.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Help extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Indent.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Indent extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Info.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Info extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/InsertAfter.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class InsertAfter extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/InsertBefore.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class InsertBefore extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/MenuItem.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class MenuItem { 3 | element: HTMLElement; 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Outdent.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Outdent extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Outline.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Outline extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Preview.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Preview extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | _bindEvent(vditor: IVditor): void; 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Record.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Record extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | _bindEvent(vditor: IVditor): void; 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Redo.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Redo extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Undo.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Undo extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | } 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/Upload.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { MenuItem } from "./MenuItem"; 3 | export declare class Upload extends MenuItem { 4 | constructor(vditor: IVditor, menuItem: IMenuItem); 5 | _bindEvent(vditor: IVditor): void; 6 | } 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class Toolbar { 3 | elements: { 4 | [key: string]: HTMLElement; 5 | }; 6 | element: HTMLElement; 7 | constructor(vditor: IVditor); 8 | private genItem; 9 | } 10 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/toolbar/setToolbar.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const removeCurrentToolbar: (toolbar: { 3 | [key: string]: HTMLElement; 4 | }, names: string[]) => void; 5 | export declare const setCurrentToolbar: (toolbar: { 6 | [key: string]: HTMLElement; 7 | }, names: string[]) => void; 8 | export declare const enableToolbar: (toolbar: { 9 | [key: string]: HTMLElement; 10 | }, names: string[]) => void; 11 | export declare const disableToolbar: (toolbar: { 12 | [key: string]: HTMLElement; 13 | }, names: string[]) => void; 14 | export declare const hideToolbar: (toolbar: { 15 | [key: string]: HTMLElement; 16 | }, names: string[]) => void; 17 | export declare const showToolbar: (toolbar: { 18 | [key: string]: HTMLElement; 19 | }, names: string[]) => void; 20 | export declare const hidePanel: (vditor: IVditor, panels: string[], exceptElement?: HTMLElement) => void; 21 | export declare const toggleSubMenu: (vditor: IVditor, panelElement: HTMLElement, actionBtn: Element, level: number) => void; 22 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ui/initUI.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare global { 3 | interface Window { 4 | visualViewport: HTMLElement; 5 | } 6 | } 7 | export declare const initUI: (vditor: IVditor) => void; 8 | export declare const setPadding: (vditor: IVditor) => void; 9 | export declare const setTypewriterPosition: (vditor: IVditor) => void; 10 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ui/setCodeTheme.d.ts: -------------------------------------------------------------------------------- 1 | export declare const setCodeTheme: (codeTheme: string, cdn?: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ui/setContentTheme.d.ts: -------------------------------------------------------------------------------- 1 | export declare const setContentTheme: (contentTheme: string, path: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ui/setPreviewMode.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const setPreviewMode: (mode: "both" | "editor", vditor: IVditor) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/ui/setTheme.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const setTheme: (vditor: IVditor) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/undo/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare class Undo { 3 | private stackSize; 4 | private dmp; 5 | private wysiwyg; 6 | private ir; 7 | private sv; 8 | constructor(); 9 | clearStack(vditor: IVditor): void; 10 | resetIcon(vditor: IVditor): void; 11 | undo(vditor: IVditor): void; 12 | redo(vditor: IVditor): void; 13 | recordFirstPosition(vditor: IVditor, event: KeyboardEvent): void; 14 | addToUndoStack(vditor: IVditor): void; 15 | private renderDiff; 16 | private resetStack; 17 | private addCaret; 18 | } 19 | export { Undo }; 20 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/Options.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare class Options { 3 | options: IOptions; 4 | private defaultOptions; 5 | constructor(options: IOptions); 6 | merge(): IOptions; 7 | private mergeToolbar; 8 | } 9 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/RecordMedia.d.ts: -------------------------------------------------------------------------------- 1 | export declare class RecordMedia { 2 | SAMPLE_RATE: number; 3 | DEFAULT_SAMPLE_RATE: number; 4 | isRecording: boolean; 5 | readyFlag: boolean; 6 | leftChannel: Float32List[]; 7 | rightChannel: Float32List[]; 8 | recordingLength: number; 9 | recorder: ScriptProcessorNode; 10 | constructor(e: MediaStream); 11 | cloneChannelData(leftChannelData: Float32List, rightChannelData: Float32List): void; 12 | startRecordingNewWavFile(): void; 13 | stopRecording(): void; 14 | buildWavFileBlob(): Blob; 15 | private downSampleBuffer; 16 | private mergeBuffers; 17 | private writeUTFBytes; 18 | } 19 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/addScript.d.ts: -------------------------------------------------------------------------------- 1 | export declare const addScriptSync: (path: string, id: string) => boolean; 2 | export declare const addScript: (path: string, id: string) => Promise; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/addStyle.d.ts: -------------------------------------------------------------------------------- 1 | export declare const addStyle: (url: string, id: string) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/code160to32.d.ts: -------------------------------------------------------------------------------- 1 | export declare const code160to32: (text: string) => string; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/compatibility.d.ts: -------------------------------------------------------------------------------- 1 | export declare const isSafari: () => boolean; 2 | export declare const isFirefox: () => boolean; 3 | export declare const accessLocalStorage: () => boolean; 4 | export declare const getEventName: () => "click" | "touchstart"; 5 | export declare const isCtrl: (event: KeyboardEvent) => boolean; 6 | export declare const updateHotkeyTip: (hotkey: string) => string; 7 | export declare const isChrome: () => boolean; 8 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/editorCommonEvent.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const focusEvent: (vditor: IVditor, editorElement: HTMLElement) => void; 3 | export declare const blurEvent: (vditor: IVditor, editorElement: HTMLElement) => void; 4 | export declare const dropEvent: (vditor: IVditor, editorElement: HTMLElement) => void; 5 | export declare const copyEvent: (vditor: IVditor, editorElement: HTMLElement, copy: (event: ClipboardEvent, vditor: IVditor) => void) => void; 6 | export declare const cutEvent: (vditor: IVditor, editorElement: HTMLElement, copy: (event: ClipboardEvent, vditor: IVditor) => void) => void; 7 | export declare const scrollCenter: (vditor: IVditor) => void; 8 | export declare const hotkeyEvent: (vditor: IVditor, editorElement: HTMLElement) => void; 9 | export declare const selectEvent: (vditor: IVditor, editorElement: HTMLElement) => void; 10 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/getSelectText.d.ts: -------------------------------------------------------------------------------- 1 | export declare const getSelectText: (editor: HTMLElement, range?: Range) => string; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/hasClosest.d.ts: -------------------------------------------------------------------------------- 1 | export declare const hasTopClosestByClassName: (element: Node, className: string) => false | HTMLElement; 2 | export declare const hasTopClosestByAttribute: (element: Node, attr: string, value: string) => false | HTMLElement; 3 | export declare const hasTopClosestByTag: (element: Node, nodeName: string) => false | HTMLElement; 4 | export declare const getTopList: (element: Node) => false | HTMLElement; 5 | export declare const hasClosestByAttribute: (element: Node, attr: string, value: string) => false | HTMLElement; 6 | export declare const hasClosestBlock: (element: Node) => false | HTMLElement; 7 | export declare const hasClosestByMatchTag: (element: Node, nodeName: string) => false | HTMLElement; 8 | export declare const hasClosestByClassName: (element: Node, className: string) => false | HTMLElement; 9 | export declare const getLastNode: (node: Node) => Node; 10 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/hasClosestByHeadings.d.ts: -------------------------------------------------------------------------------- 1 | export declare const hasClosestByTag: (element: Node, nodeName: string) => false | HTMLElement; 2 | export declare const hasClosestByHeadings: (element: Node) => false | HTMLElement; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/highlightToolbar.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const highlightToolbar: (vditor: IVditor) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/hotKey.d.ts: -------------------------------------------------------------------------------- 1 | export declare const matchHotKey: (hotKey: string, event: KeyboardEvent) => boolean; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/log.d.ts: -------------------------------------------------------------------------------- 1 | export declare const log: (method: string, content: string, type: string, print: boolean) => void; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/merge.d.ts: -------------------------------------------------------------------------------- 1 | export declare const merge: (...options: any[]) => any; 2 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/processCode.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const processPasteCode: (html: string, text: string, type?: string) => string | false; 3 | export declare const processCodeRender: (previewPanel: HTMLElement, vditor: IVditor) => void; 4 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/selection.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const getEditorRange: (element: HTMLElement) => Range; 3 | export declare const getCursorPosition: (editor: HTMLElement) => { 4 | left: number; 5 | top: number; 6 | }; 7 | export declare const selectIsEditor: (editor: HTMLElement, range?: Range) => boolean; 8 | export declare const setSelectionFocus: (range: Range) => void; 9 | export declare const getSelectPosition: (selectElement: HTMLElement, editorElement: HTMLElement, range?: Range) => { 10 | end: number; 11 | start: number; 12 | }; 13 | export declare const setSelectionByPosition: (start: number, end: number, editor: HTMLElement) => Range; 14 | export declare const setRangeByWbr: (element: HTMLElement, range: Range) => void; 15 | export declare const insertHTML: (html: string, vditor: IVditor) => void; 16 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/util/toc.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const renderToc: (vditor: IVditor) => void; 3 | export declare const clickToc: (event: MouseEvent & { 4 | target: HTMLElement; 5 | }, vditor: IVditor) => void; 6 | export declare const keydownToc: (blockElement: HTMLElement, vditor: IVditor, event: KeyboardEvent, range: Range) => boolean; 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/afterRenderEvent.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const afterRenderEvent: (vditor: IVditor, options?: { 3 | enableAddUndoStack: boolean; 4 | enableHint: boolean; 5 | enableInput: boolean; 6 | }) => void; 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/highlightToolbarWYSIWYG.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const highlightToolbarWYSIWYG: (vditor: IVditor) => void; 3 | export declare const genLinkRefPopover: (vditor: IVditor, linkRefElement: HTMLElement) => void; 4 | export declare const genAPopover: (vditor: IVditor, aElement: HTMLElement) => void; 5 | export declare const genImagePopover: (event: Event, vditor: IVditor) => void; 6 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare class WYSIWYG { 3 | element: HTMLPreElement; 4 | popover: HTMLDivElement; 5 | selectPopover: HTMLDivElement; 6 | afterRenderTimeoutId: number; 7 | hlToolbarTimeoutId: number; 8 | preventInput: boolean; 9 | composingLock: boolean; 10 | commentIds: string[]; 11 | constructor(vditor: IVditor); 12 | getComments(vditor: IVditor, getData?: boolean): ICommentsData[]; 13 | triggerRemoveComment(vditor: IVditor): void; 14 | showComment(): void; 15 | hideComment(): void; 16 | private copy; 17 | private bindEvent; 18 | } 19 | export { WYSIWYG }; 20 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/inlineTag.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const previoueIsEmptyA: (node: Node) => false | HTMLElement; 3 | export declare const nextIsCode: (range: Range) => boolean; 4 | export declare const getNextHTML: (node: Node) => string; 5 | export declare const getPreviousHTML: (node: Node) => string; 6 | export declare const getRenderElementNextNode: (blockCodeElement: HTMLElement) => ChildNode; 7 | export declare const splitElement: (range: Range) => { 8 | afterHTML: string; 9 | beforeHTML: string; 10 | }; 11 | export declare const modifyPre: (vditor: IVditor, range: Range) => void; 12 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/input.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const input: (vditor: IVditor, range: Range, event?: InputEvent) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/processKeydown.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const processKeydown: (vditor: IVditor, event: KeyboardEvent) => boolean; 3 | export declare const removeBlockElement: (vditor: IVditor, event: KeyboardEvent) => boolean; 4 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/renderDomByMd.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const renderDomByMd: (vditor: IVditor, md: string, options?: { 3 | enableAddUndoStack: boolean; 4 | enableHint: boolean; 5 | enableInput: boolean; 6 | }) => void; 7 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/setHeading.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const setHeading: (vditor: IVditor, tagName: string) => void; 3 | export declare const removeHeading: (vditor: IVditor) => void; 4 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/showCode.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const showCode: (previewElement: HTMLElement, vditor: IVditor, first?: boolean) => void; 3 | -------------------------------------------------------------------------------- /resource/public/plugin/vditor/dist/ts/wysiwyg/toolbarEvent.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const toolbarEvent: (vditor: IVditor, actionBtn: Element, event: Event) => void; 3 | -------------------------------------------------------------------------------- /resource/template/admin/index.html: -------------------------------------------------------------------------------- 1 | 后台页面 -------------------------------------------------------------------------------- /resource/template/index/article/detail.html: -------------------------------------------------------------------------------- 1 | {{include "index/content/detail.html" .}} -------------------------------------------------------------------------------- /resource/template/index/article/index.html: -------------------------------------------------------------------------------- 1 | {{include "index/content/index.html" .}} -------------------------------------------------------------------------------- /resource/template/index/ask/detail.html: -------------------------------------------------------------------------------- 1 | {{include "index/content/detail.html" .}} -------------------------------------------------------------------------------- /resource/template/index/ask/index.html: -------------------------------------------------------------------------------- 1 | {{include "index/content/index.html" .}} -------------------------------------------------------------------------------- /resource/template/index/footer.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | Powered By GoFrame 5 |
6 |
-------------------------------------------------------------------------------- /resource/template/index/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {{.Title}} 29 | 30 | -------------------------------------------------------------------------------- /resource/template/index/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{include "index/header.html" .}} 6 | 7 | 8 | 9 |
10 | 11 | {{include "index/navbar.html" .}} 12 | 13 | 14 |
15 | {{include "index/message.html" .}} 16 | {{include .MainTpl .}} 17 |
18 | 19 | 20 | {{include "index/footer.html" .}} 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /resource/template/index/index/page_link.html: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /resource/template/index/message.html: -------------------------------------------------------------------------------- 1 | {{if .Notice}} 2 |
3 |
4 | {{.Notice.Content}} 5 | 8 |
9 |
10 | {{end}} -------------------------------------------------------------------------------- /resource/template/index/pages/401.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
-------------------------------------------------------------------------------- /resource/template/index/pages/403.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
-------------------------------------------------------------------------------- /resource/template/index/pages/404.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
-------------------------------------------------------------------------------- /resource/template/index/pages/500.html: -------------------------------------------------------------------------------- 1 | 27 |
28 | 29 |
30 |
31 |
32 |

{{ .Error}}

33 |
34 |
-------------------------------------------------------------------------------- /resource/template/index/topic/detail.html: -------------------------------------------------------------------------------- 1 | {{include "index/content/detail.html" .}} -------------------------------------------------------------------------------- /resource/template/index/topic/index.html: -------------------------------------------------------------------------------- 1 | {{include "index/content/index.html" .}} -------------------------------------------------------------------------------- /resource/template/index/user/article.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{include "index/user/user_menu.html" .}} 4 |
5 |
6 |
7 |
8 | 我的文章 9 |
10 |
11 | 20 |
21 |
22 |
23 | 24 |
25 | -------------------------------------------------------------------------------- /resource/template/index/user/ask.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{include "index/user/user_menu.html" .}} 4 |
5 |
6 |
7 |
8 | 我的问答 9 |
10 |
11 | 20 |
21 |
22 |
23 | 24 |
25 | -------------------------------------------------------------------------------- /resource/template/index/user/topic.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{include "index/user/user_menu.html" .}} 4 |
5 |
6 |
7 |
8 | 我的主题 9 |
10 |
11 | 20 |
21 |
22 |
23 | 24 |
25 | -------------------------------------------------------------------------------- /resource/template/index/user/user_menu.html: -------------------------------------------------------------------------------- 1 |
2 |
我的资料
3 | 30 |
-------------------------------------------------------------------------------- /utility/response/response.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "github.com/gogf/gf/v2/net/ghttp" 6 | ) 7 | 8 | // JsonRes 数据返回通用JSON数据结构 9 | type JsonRes struct { 10 | Code int `json:"code"` // 错误码((0:成功, 1:失败, >1:错误码)) 11 | Message string `json:"message"` // 提示信息 12 | Data interface{} `json:"data"` // 返回数据(业务接口定义具体数据结构) 13 | Redirect string `json:"redirect"` // 引导客户端跳转到指定路由 14 | } 15 | 16 | // Json 返回标准JSON数据。 17 | func Json(r *ghttp.Request, code int, message string, data ...interface{}) { 18 | var responseData interface{} 19 | if len(data) > 0 { 20 | responseData = data[0] 21 | } else { 22 | responseData = g.Map{} 23 | } 24 | r.Response.WriteJson(JsonRes{ 25 | Code: code, 26 | Message: message, 27 | Data: responseData, 28 | }) 29 | } 30 | 31 | // JsonExit 返回标准JSON数据并退出当前HTTP执行函数。 32 | func JsonExit(r *ghttp.Request, code int, message string, data ...interface{}) { 33 | Json(r, code, message, data...) 34 | r.Exit() 35 | } 36 | 37 | // JsonRedirect 返回标准JSON数据引导客户端跳转。 38 | func JsonRedirect(r *ghttp.Request, code int, message, redirect string, data ...interface{}) { 39 | responseData := interface{}(nil) 40 | if len(data) > 0 { 41 | responseData = data[0] 42 | } 43 | r.Response.WriteJson(JsonRes{ 44 | Code: code, 45 | Message: message, 46 | Data: responseData, 47 | Redirect: redirect, 48 | }) 49 | } 50 | 51 | // JsonRedirectExit 返回标准JSON数据引导客户端跳转,并退出当前HTTP执行函数。 52 | func JsonRedirectExit(r *ghttp.Request, code int, message, redirect string, data ...interface{}) { 53 | JsonRedirect(r, code, message, redirect, data...) 54 | r.Exit() 55 | } 56 | -------------------------------------------------------------------------------- /utility/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/russross/blackfriday/v2" 5 | ) 6 | 7 | // MarkdownToHtml 解析markdown为html 8 | func MarkdownToHtml(mdContent string) string { 9 | return string(blackfriday.Run([]byte(mdContent))) 10 | } 11 | -------------------------------------------------------------------------------- /utility/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gogf/gf/v2/frame/g" 7 | "github.com/gogf/gf/v2/test/gtest" 8 | ) 9 | 10 | func TestMarkdownToHtml(t *testing.T) { 11 | gtest.C(t, func(t *gtest.T) { 12 | content := ` 13 | ## 参与贡献 14 | 15 | 1. 框架代码:参与框架功能开发、单元测试、ISSUE提交、反馈建议等等,https://github.com/gogf/gf 16 | 2. 开发文档:参与开发文档的撰写,便于更多的人了解、热爱并加入团队,https://github.com/gogf/gf-doc 17 | 18 | ` 19 | g.Dump(MarkdownToHtml(content)) 20 | }) 21 | } 22 | --------------------------------------------------------------------------------