mirror of https://github.com/mindoc-org/mindoc.git
Merge remote-tracking branch 'upstream/master'
commit
0d0582c37c
186
Dockerfile
186
Dockerfile
|
@ -1,95 +1,135 @@
|
|||
FROM golang:1.11.4-alpine3.8 AS build
|
||||
FROM amd64/golang:1.13 AS build
|
||||
|
||||
#新增 GLIBC
|
||||
ENV GLIBC_VERSION "2.28-r0"
|
||||
ARG TAG=0.0.1
|
||||
|
||||
# Download and install glibc
|
||||
RUN apk add --update && \
|
||||
apk add --no-cache --upgrade \
|
||||
ca-certificates \
|
||||
gcc \
|
||||
g++ \
|
||||
make \
|
||||
curl \
|
||||
git
|
||||
|
||||
RUN curl -Lo /etc/apk/keys/sgerrand.rsa.pub "https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub" && \
|
||||
curl -Lo /var/glibc.apk "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk" && \
|
||||
curl -Lo /var/glibc-bin.apk "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk" && \
|
||||
apk add /var/glibc-bin.apk /var/glibc.apk && \
|
||||
/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
|
||||
|
||||
#掛載 calibre 最新3.x
|
||||
|
||||
ENV LD_LIBRARY_PATH $LD_LIBRARY_PATH:/opt/calibre/lib
|
||||
ENV PATH $PATH:/opt/calibre/bin
|
||||
|
||||
RUN curl -Lo /var/linux-installer.py https://download.calibre-ebook.com/linux-installer.py
|
||||
|
||||
#RUN mkdir -p /go/src/github.com/lifei6671/ && cd /go/src/github.com/lifei6671/ && git clone https://github.com/mindoc-org/mindoc.git && cd mindoc
|
||||
# 编译-环境变量
|
||||
ENV GO111MODULE=on
|
||||
ENV GOPROXY=https://goproxy.cn,direct
|
||||
ENV CGO_ENABLED=1
|
||||
ENV GOARCH=amd64
|
||||
ENV GOOS=linux
|
||||
|
||||
# 工作目录
|
||||
ADD . /go/src/github.com/mindoc-org/mindoc
|
||||
|
||||
WORKDIR /go/src/github.com/mindoc-org/mindoc
|
||||
|
||||
RUN go get -u github.com/golang/dep/cmd/dep && dep ensure && \
|
||||
CGO_ENABLE=1 go build -v -a -o mindoc_linux_amd64 -ldflags="-w -s -X main.VERSION=$TAG -X 'main.BUILD_TIME=`date`' -X 'main.GO_VERSION=`go version`'" && \
|
||||
rm -rf commands controllers models modules routers tasks vendor docs search data utils graphics .git Godeps uploads/* .gitignore .travis.yml Dockerfile gide.yaml LICENSE main.go README.md conf/enumerate.go conf/mail.go install.lock simsun.ttc
|
||||
# 编译
|
||||
RUN go env
|
||||
RUN go mod tidy -v
|
||||
RUN go build -o mindoc_linux_amd64 -ldflags "-w -s -X 'main.VERSION=$TAG' -X 'main.BUILD_TIME=`date`' -X 'main.GO_VERSION=`go version`'"
|
||||
RUN cp conf/app.conf.example conf/app.conf
|
||||
# 清理不需要的文件
|
||||
RUN rm appveyor.yml docker-compose.yml Dockerfile .travis.yml .gitattributes .gitignore go.mod go.sum main.go README.md simsun.ttc start.sh conf/*.go
|
||||
RUN rm -rf cache commands controllers converter .git .github graphics mail models routers utils
|
||||
|
||||
ADD start.sh /go/src/github.com/mindoc-org/mindoc
|
||||
# 测试编译的mindoc是否ok
|
||||
RUN ./mindoc_linux_amd64 version
|
||||
|
||||
# 必要的文件复制
|
||||
ADD simsun.ttc /usr/share/fonts/win/
|
||||
ADD start.sh /go/src/github.com/mindoc-org/mindoc
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
LABEL maintainer="longfei6671@163.com"
|
||||
# Ubuntu 20.04
|
||||
FROM ubuntu:focal
|
||||
|
||||
RUN apk add --update && \
|
||||
apk add --no-cache --upgrade \
|
||||
tzdata \
|
||||
mesa-gl \
|
||||
python \
|
||||
qt5-qtbase-x11 \
|
||||
xdg-utils \
|
||||
libxrender \
|
||||
libxcomposite \
|
||||
xz \
|
||||
imagemagick \
|
||||
imagemagick-dev \
|
||||
msttcorefonts-installer \
|
||||
fontconfig && \
|
||||
update-ms-fonts && \
|
||||
fc-cache -f
|
||||
# 切换默认shell为bash
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
COPY --from=build /var/glibc.apk .
|
||||
COPY --from=build /var/glibc-bin.apk .
|
||||
COPY --from=build /etc/apk/keys/sgerrand.rsa.pub /etc/apk/keys/sgerrand.rsa.pub
|
||||
COPY --from=build /var/linux-installer.py .
|
||||
COPY --from=build /usr/share/fonts/win/simsun.ttc /usr/share/fonts/win/
|
||||
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=build /go/src/github.com/mindoc-org/mindoc /mindoc
|
||||
|
||||
RUN apk add glibc-bin.apk glibc.apk && \
|
||||
/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
rm -rf glibc.apk glibc-bin.apk /var/cache/apk/* && \
|
||||
chmod a+r /usr/share/fonts/win/simsun.ttc
|
||||
|
||||
|
||||
ENV LD_LIBRARY_PATH $LD_LIBRARY_PATH:/opt/calibre/lib
|
||||
ENV PATH $PATH:/opt/calibre/bin
|
||||
|
||||
RUN cat linux-installer.py | python -c "import sys; main=lambda x,y:sys.stderr.write('Download failed\n'); exec(sys.stdin.read()); main(install_dir='/opt', isolated=True)" && \
|
||||
rm -rf /tmp/* linux-installer.py
|
||||
|
||||
WORKDIR /mindoc
|
||||
RUN chmod a+r /usr/share/fonts/win/simsun.ttc
|
||||
|
||||
# 备份原有源
|
||||
RUN mv /etc/apt/sources.list /etc/apt/sources.list-backup
|
||||
# 最小化源,缩短apt update时间(ca-certificates必须先安装才支持换tsinghua源)
|
||||
RUN echo 'deb http://archive.ubuntu.com/ubuntu/ focal main restricted' > /etc/apt/sources.list
|
||||
RUN apt-get update
|
||||
RUN apt install -y ca-certificates
|
||||
# 更换aliyun源(echo多行内容不能以#开头,会被docker误判为注释行,所以采用\n#开头)
|
||||
RUN echo $'\
|
||||
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\
|
||||
\n# deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\n\
|
||||
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\
|
||||
\n# deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\n\
|
||||
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\
|
||||
\n# deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\n\
|
||||
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\
|
||||
\n# deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\n\
|
||||
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\
|
||||
\n# deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse'\
|
||||
> /etc/apt/sources.list
|
||||
|
||||
# 时区设置
|
||||
# 更新软件包信息
|
||||
RUN apt-get update
|
||||
# 安装必要的系统工具
|
||||
RUN apt install -y apt-transport-https ca-certificates curl wget xz-utils
|
||||
|
||||
# 时区设置(如果不设置, calibre依赖的tzdata在安装过程中会要求选择时区)
|
||||
ENV TZ=Asia/Shanghai
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
# tzdata的前端类型默认为readline(Shell情况下)或dialog(支持GUI的情况下)
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
# 安装时区信息
|
||||
RUN apt install -y --no-install-recommends tzdata
|
||||
# 重新配置tzdata软件包,使得时区设置生效
|
||||
RUN dpkg-reconfigure --frontend noninteractive tzdata
|
||||
|
||||
# 安装 calibre 依赖的包
|
||||
RUN apt install -y libgl-dev libnss3-dev libxcomposite-dev libxrandr-dev libxi-dev
|
||||
# 安装文泉驿字体
|
||||
RUN apt install -y fonts-wqy-microhei fonts-wqy-zenhei
|
||||
# 安装中文语言包
|
||||
RUN apt-get install -y locales language-pack-zh-hans language-pack-zh-hans-base
|
||||
# 设置默认编码
|
||||
RUN locale-gen "zh_CN.UTF-8"
|
||||
RUN update-locale LANG=zh_CN.UTF-8
|
||||
ENV LANG=zh_CN.UTF-8
|
||||
ENV LANGUAGE=zh_CN:en
|
||||
ENV LC_ALL=zh_CN.UTF-8
|
||||
# 安装-calibre
|
||||
# RUN apt-get install -y calibre # 此种方式安装省事,但会安装很多额外不需要的软件包,导致体积过大
|
||||
RUN mkdir -p /tmp/calibre-cache
|
||||
# 获取最新版本号
|
||||
RUN curl -s http://code.calibre-ebook.com/latest>/tmp/calibre-cache/version
|
||||
# 下载最新版本
|
||||
# RUN wget -O /tmp/calibre-cache/calibre-x86_64.txz -c https://download.calibre-ebook.com/`cat /tmp/calibre-cache/version`/calibre-`cat /tmp/calibre-cache/version`-x86_64.txz
|
||||
# 使用 download.fastgit.org 替换 github 实现加速
|
||||
RUN wget -O /tmp/calibre-cache/calibre-x86_64.txz -c https://download.fastgit.org/kovidgoyal/calibre/releases/download/v`cat /tmp/calibre-cache/version`/calibre-`cat /tmp/calibre-cache/version`-x86_64.txz
|
||||
# 注: 调试阶段,下载alibre-5.22.1-x86_64.txz到本地(使用 python -m http.server),加速构建
|
||||
# RUN wget -O /tmp/calibre-cache/calibre-x86_64.txz -c http://10.96.8.252:8000/calibre-5.22.1-x86_64.txz
|
||||
# 解压
|
||||
RUN mkdir -p /opt/calibre
|
||||
# RUN tar --extract --file=/tmp/calibre-cache/calibre-x86_64.txz --directory /opt/calibre
|
||||
RUN tar xJof /tmp/calibre-cache/calibre-x86_64.txz -C /opt/calibre
|
||||
ENV PATH=$PATH:/opt/calibre
|
||||
# 设置calibre相关环境变量
|
||||
ENV QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox"
|
||||
ENV QT_QPA_PLATFORM='offscreen'
|
||||
# 测试 calibre 可正常使用
|
||||
RUN ebook-convert --version
|
||||
# 清理calibre缓存
|
||||
RUN rm -rf /tmp/calibre-cache
|
||||
|
||||
# refer: https://docs.docker.com/engine/reference/builder/#volume
|
||||
# 数据同步目录
|
||||
VOLUME /mindoc-sync-host
|
||||
|
||||
# refer: https://docs.docker.com/engine/reference/builder/#expose
|
||||
EXPOSE 8181/tcp
|
||||
|
||||
# 如果配置文件不存在就复制
|
||||
RUN cp --no-clobber /mindoc/conf/app.conf.example /mindoc/conf/app.conf
|
||||
|
||||
ENV ZONEINFO=/mindoc/lib/time/zoneinfo.zip
|
||||
RUN chmod +x start.sh
|
||||
RUN chmod +x /mindoc/start.sh
|
||||
|
||||
CMD ["./start.sh"]
|
||||
ENTRYPOINT ["/bin/bash", "/mindoc/start.sh"]
|
||||
|
||||
# https://docs.docker.com/engine/reference/commandline/build/#options
|
||||
# docker build --progress plain --rm --build-arg TAG=2.0.1 --tag gsw945/mindoc:2.0.1 .
|
||||
# https://docs.docker.com/engine/reference/commandline/run/#options
|
||||
# set MINDOC=//d/mindoc # windows
|
||||
# export MINDOC=/home/ubuntu/mindoc-docker # linux
|
||||
# docker run --rm -it -p 8181:8181 -v "%MINDOC%":"/mindoc-sync-host" --name mindoc -e MINDOC_ENABLE_EXPORT=true -d gsw945/mindoc:2.0.1
|
||||
|
|
76
README.md
76
README.md
|
@ -11,7 +11,9 @@ MinDoc 的前身是 [SmartWiki](https://github.com/lifei6671/SmartWiki) 文档
|
|||
|
||||
可以用来储存日常接口文档,数据库字典,手册说明等文档。内置项目管理,用户管理,权限管理等功能,能够满足大部分中小团队的文档管理需求。
|
||||
|
||||
演示站点: [https://www.iminho.me/wiki/](https://www.iminho.me/wiki/)
|
||||
##### 演示站点&文档:
|
||||
- https://www.iminho.me/wiki/docs/mindoc/
|
||||
- https://doc.gsw945.com/docs/mindoc-docs/
|
||||
|
||||
---
|
||||
|
||||
|
@ -24,6 +26,11 @@ MinDoc 的前身是 [SmartWiki](https://github.com/lifei6671/SmartWiki) 文档
|
|||
遇到问题请提 [Issues](https://github.com/mindoc-org/mindoc/issues ),欢迎使用者和贡献者加入QQ群 `1051164153`
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=bHFR7P3Qp1nsSPbsTw4KN_ZpFLUAblIU&jump_from=webapi"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="MinDoc使用&开发交流群" title="MinDoc使用&开发交流群"></a>
|
||||
|
||||
对开发感兴趣请关注 [Development](https://github.com/mindoc-org/mindoc/projects/1):
|
||||
- [Todo List](https://github.com/mindoc-org/mindoc/projects/1#column-13554511)
|
||||
- [Work in progress](https://github.com/mindoc-org/mindoc/projects/1#column-13554512)
|
||||
- [Review in progress](https://github.com/mindoc-org/mindoc/projects/1#column-13554513)
|
||||
|
||||
---
|
||||
|
||||
# 安装与使用
|
||||
|
@ -35,7 +42,9 @@ MinDoc 的前身是 [SmartWiki](https://github.com/lifei6671/SmartWiki) 文档
|
|||
对于没有Golang使用经验的用户,可以从 [https://github.com/mindoc-org/mindoc/releases](https://github.com/mindoc-org/mindoc/releases) 这里下载编译完的程序。
|
||||
|
||||
如果有Golang开发经验,建议通过编译安装,要求golang版本不小于1.13(需支持`CGO`和`go mod`)。
|
||||
> 注意: CentOS7上GLibC版本低,需要源码编译, 编译好的二进制文件无法运行。
|
||||
|
||||
## 常规编译
|
||||
```bash
|
||||
# 克隆源码
|
||||
git clone https://github.com/mindoc-org/mindoc.git
|
||||
|
@ -47,7 +56,6 @@ go build -ldflags "-w"
|
|||
./mindoc install
|
||||
# 执行
|
||||
./mindoc
|
||||
|
||||
```
|
||||
|
||||
MinDoc 如果使用MySQL储存数据,则编码必须是`utf8mb4_general_ci`。请在安装前,把数据库配置填充到项目目录下的 `conf/app.conf` 中。
|
||||
|
@ -58,6 +66,31 @@ MinDoc 如果使用MySQL储存数据,则编码必须是`utf8mb4_general_ci`。
|
|||
|
||||
**默认程序会自动初始化一个超级管理员用户:admin 密码:123456 。请登录后重新设置密码。**
|
||||
|
||||
## Linux系统中不依赖gLibC的编译方式
|
||||
|
||||
### 安装 musl-gcc
|
||||
```bash
|
||||
wget -c http://www.musl-libc.org/releases/musl-1.2.2.tar.gz
|
||||
tar -xvf musl-1.2.2.tar.gz
|
||||
cd musl-1.2.2
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
### 使用 musl-gcc 编译 mindoc
|
||||
```bash
|
||||
go mod tidy -v
|
||||
export GOARCH=amd64
|
||||
export GOOS=linux
|
||||
# 设置使用musl-gcc
|
||||
export CC=/usr/local/musl/bin/musl-gcc
|
||||
# 设置版本
|
||||
export TRAVIS_TAG=temp-musl-v`date +%y%m%d`
|
||||
go build -o mindoc_linux_musl_amd64 --ldflags="-linkmode external -extldflags '-static' -w -X 'github.com/mindoc-org/mindoc/conf.VERSION=$TRAVIS_TAG' -X 'github.com/mindoc-org/mindoc/conf.BUILD_TIME=`date`' -X 'github.com/mindoc-org/mindoc/conf.GO_VERSION=`go version`'"
|
||||
# 验证
|
||||
./mindoc_linux_amd64 version
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
|
||||
|
@ -80,26 +113,42 @@ mail_expired=30
|
|||
|
||||
|
||||
# 使用Docker部署
|
||||
如果是Docker用户,可参考项目内置的Dockerfile文件编译镜像。
|
||||
|
||||
在启动镜像时需要提供如下的环境变量:
|
||||
如果是Docker用户,可参考项目内置的Dockerfile文件自行编译镜像(编译命令见Dockerfile文件底部注释,仅供参考)。
|
||||
|
||||
在启动镜像时需要提供如下的常用环境变量(全部支持的环境变量请参考: [`conf/app.conf.example`](https://github.com/mindoc-org/mindoc/blob/master/conf/app.conf.example)):
|
||||
```ini
|
||||
DB_ADAPTER 指定 DB
|
||||
DB_ADAPTER 指定DB类型(默认为sqlite)
|
||||
MYSQL_PORT_3306_TCP_ADDR MySQL地址
|
||||
MYSQL_PORT_3306_TCP_PORT MySQL端口号
|
||||
MYSQL_INSTANCE_NAME MySQL数据库名称
|
||||
MYSQL_USERNAME MySQL账号
|
||||
MYSQL_PASSWORD MySQL密码
|
||||
HTTP_PORT 程序监听的端口号
|
||||
MINDOC_ENABLE_EXPORT 开启导出(默认为false)
|
||||
```
|
||||
|
||||
举个栗子
|
||||
|
||||
### 举个栗子-当前(公开)镜像(信息页面: https://cr.console.aliyun.com/images/cn-hangzhou/mindoc-org/mindoc/detail , 需要登录阿里云账号才可访问列表)
|
||||
##### Windows
|
||||
```bash
|
||||
set MINDOC=//d/mindoc
|
||||
docker run -it --name=mindoc --restart=always -v "%MINDOC%":"/mindoc-sync-host" -p 8181:8181 -e MINDOC_ENABLE_EXPORT=true -d registry.cn-hangzhou.aliyuncs.com/mindoc-org/mindoc:v2.1-beta.5
|
||||
```
|
||||
|
||||
##### Linux、Mac
|
||||
```bash
|
||||
export MINDOC=/home/ubuntu/mindoc-docker
|
||||
docker run -it --name=mindoc --restart=always -v "${MINDOC}":"/mindoc-sync-host" -p 8181:8181 -e MINDOC_ENABLE_EXPORT=true -d registry.cn-hangzhou.aliyuncs.com/mindoc-org/mindoc:v2.1-beta.5
|
||||
```
|
||||
|
||||
##### 举个栗子-更多环境变量示例(镜像已过期,仅供参考,请以当前镜像为准)
|
||||
```bash
|
||||
# TODO: 新版docker镜像将使用阿里云,配置中
|
||||
docker run -p 8181:8181 --name mindoc -e DB_ADAPTER=mysql -e MYSQL_PORT_3306_TCP_ADDR=10.xxx.xxx.xxx -e MYSQL_PORT_3306_TCP_PORT=3306 -e MYSQL_INSTANCE_NAME=mindoc -e MYSQL_USERNAME=root -e MYSQL_PASSWORD=123456 -e httpport=8181 -d daocloud.io/lifei6671/mindoc:latest
|
||||
```
|
||||
|
||||
#### dockerfile内容参考
|
||||
- [无需代理直接加速各种 GitHub 资源拉取 | 国内镜像赋能 | 助力开发](https://blog.frytea.com/archives/504/)
|
||||
- [阿里云 - Ubuntu 镜像](https://developer.aliyun.com/mirror/ubuntu)
|
||||
|
||||
### docker-compose 一键安装
|
||||
|
||||
1. 修改配置文件
|
||||
|
@ -176,7 +225,7 @@ docker run -p 8181:8181 --name mindoc -e DB_ADAPTER=mysql -e MYSQL_PORT_3306_TCP
|
|||
- MySQL 5.6
|
||||
- [editor.md](https://github.com/pandao/editor.md) Markdown 编辑器
|
||||
- [Bootstrap](https://github.com/twbs/bootstrap) 3.2
|
||||
- jQuery(https://github.com/jquery/jquery) 库
|
||||
- [jQuery](https://github.com/jquery/jquery) 库
|
||||
- [WebUploader](https://github.com/fex-team/webuploader) 文件上传框架
|
||||
- [NProgress](https://github.com/rstacruz/nprogress) 库
|
||||
- [jsTree](https://github.com/vakata/jstree) 树状结构库
|
||||
|
@ -187,6 +236,10 @@ docker run -p 8181:8181 --name mindoc -e DB_ADAPTER=mysql -e MYSQL_PORT_3306_TCP
|
|||
- ~~to-markdown~~[Turndown](https://github.com/domchristie/turndown) HTML转Markdown库
|
||||
- ~~quill 富文本编辑器~~
|
||||
- [wangEditor](https://github.com/wangeditor-team/wangEditor) 富文本编辑器
|
||||
- 参考
|
||||
- [wangEditor v4.7 富文本编辑器教程](https://www.bookstack.cn/books/wangeditor-4.7-zh)
|
||||
- [扩展菜单注册太过繁琐 #2493](https://github.com/wangeditor-team/wangEditor/issues/2493)
|
||||
- 工具: `https://babeljs.io/repl` + `@babel/plugin-transform-classes`
|
||||
- [Vue.js](https://github.com/vuejs/vue) 框架
|
||||
|
||||
|
||||
|
@ -210,6 +263,3 @@ docker run -p 8181:8181 --name mindoc -e DB_ADAPTER=mysql -e MYSQL_PORT_3306_TCP
|
|||
|
||||
一个不纯粹的PHPer,一个不自由的 gopher 。
|
||||
|
||||
# 支持 MinDoc
|
||||
|
||||
![支付宝](https://raw.githubusercontent.com/lifei6671/mindoc/master/static/images/alipay.png) ![微信支付](https://raw.githubusercontent.com/lifei6671/mindoc/master/static/images/weixin.png)
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/client/cache"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
)
|
||||
|
||||
var bm cache.Cache
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -22,6 +23,7 @@ import (
|
|||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/howeyc/fsnotify"
|
||||
"github.com/lifei6671/gocaptcha"
|
||||
"github.com/mindoc-org/mindoc/cache"
|
||||
|
@ -262,6 +264,12 @@ func RegisterFunction() {
|
|||
logs.Error("注册函数 urlfor 出错 ->", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
//读取配置值(未作任何转换)
|
||||
err = web.AddFuncMap("conf", conf.CONF)
|
||||
if err != nil {
|
||||
logs.Error("注册函数 conf 出错 ->", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
err = web.AddFuncMap("date_format", func(t time.Time, format string) string {
|
||||
return t.Local().Format(format)
|
||||
})
|
||||
|
@ -269,6 +277,19 @@ func RegisterFunction() {
|
|||
logs.Error("注册函数 date_format 出错 ->", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
err = web.AddFuncMap("i18n", i18n.Tr)
|
||||
if err != nil {
|
||||
logs.Error("注册函数 i18n 出错 ->", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
langs := strings.Split("en-us|zh-cn", "|")
|
||||
for _, lang := range langs {
|
||||
if err := i18n.SetMessage(lang, "conf/lang/"+lang+".ini"); err != nil {
|
||||
logs.Error("Fail to set message file: " + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//解析命令
|
||||
|
@ -385,15 +406,15 @@ func RegisterCache() {
|
|||
var redisConfig struct {
|
||||
Conn string `json:"conn"`
|
||||
Password string `json:"password"`
|
||||
DbNum int `json:"dbNum"`
|
||||
DbNum string `json:"dbNum"`
|
||||
}
|
||||
redisConfig.DbNum = 0
|
||||
redisConfig.DbNum = "0"
|
||||
redisConfig.Conn = web.AppConfig.DefaultString("cache_redis_host", "")
|
||||
if pwd := web.AppConfig.DefaultString("cache_redis_password", ""); pwd != "" {
|
||||
redisConfig.Password = pwd
|
||||
}
|
||||
if dbNum := web.AppConfig.DefaultInt("cache_redis_db", 0); dbNum > 0 {
|
||||
redisConfig.DbNum = dbNum
|
||||
redisConfig.DbNum = strconv.Itoa(dbNum)
|
||||
}
|
||||
|
||||
bc, err := json.Marshal(&redisConfig)
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
"github.com/mindoc-org/mindoc/utils"
|
||||
|
@ -96,11 +98,16 @@ func ModifyPassword() {
|
|||
func initialization() {
|
||||
|
||||
err := models.NewOption().Init()
|
||||
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
lang, _ := web.AppConfig.String("default_lang")
|
||||
err = i18n.SetMessage(lang, "conf/lang/"+lang+".ini")
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("initialize locale error: %s", err))
|
||||
}
|
||||
|
||||
member, err := models.NewMember().FindByFieldFirst("account", "admin")
|
||||
if errors.Is(err, orm.ErrNoRows) {
|
||||
|
||||
|
@ -122,10 +129,10 @@ func initialization() {
|
|||
book := models.NewBook()
|
||||
|
||||
book.MemberId = member.MemberId
|
||||
book.BookName = "MinDoc演示项目"
|
||||
book.BookName = i18n.Tr(lang, "init.default_proj_name") //"MinDoc演示项目"
|
||||
book.Status = 0
|
||||
book.ItemId = 1
|
||||
book.Description = "这是一个MinDoc演示项目,该项目是由系统初始化时自动创建。"
|
||||
book.Description = i18n.Tr(lang, "init.default_proj_desc") //"这是一个MinDoc演示项目,该项目是由系统初始化时自动创建。"
|
||||
book.CommentCount = 0
|
||||
book.PrivatelyOwned = 0
|
||||
book.CommentStatus = "closed"
|
||||
|
@ -137,7 +144,7 @@ func initialization() {
|
|||
book.Editor = "markdown"
|
||||
book.Theme = "default"
|
||||
|
||||
if err := book.Insert(); err != nil {
|
||||
if err := book.Insert(lang); err != nil {
|
||||
panic("初始化项目失败 -> " + err.Error())
|
||||
}
|
||||
} else if err != nil {
|
||||
|
@ -146,7 +153,7 @@ func initialization() {
|
|||
|
||||
if !models.NewItemsets().Exist(1) {
|
||||
item := models.NewItemsets()
|
||||
item.ItemName = "默认项目空间"
|
||||
item.ItemName = i18n.Tr(lang, "init.default_proj_space") //"默认项目空间"
|
||||
item.MemberId = 1
|
||||
if err := item.Save(); err != nil {
|
||||
panic("初始化项目空间失败 -> " + err.Error())
|
||||
|
|
|
@ -14,7 +14,9 @@ import (
|
|||
//检查最新版本.
|
||||
func CheckUpdate() {
|
||||
|
||||
resp, err := http.Get("https://api.github.com/repos/lifei6671/mindoc/tags")
|
||||
fmt.Println("MinDoc current version => ", conf.VERSION)
|
||||
|
||||
resp, err := http.Get("https://api.github.com/repos/mindoc-org/mindoc/tags")
|
||||
|
||||
if err != nil {
|
||||
logs.Error("CheckUpdate => ", err)
|
||||
|
@ -33,7 +35,6 @@ func CheckUpdate() {
|
|||
}
|
||||
|
||||
err = json.Unmarshal(body, &result)
|
||||
fmt.Println("MinDoc current version => ", conf.VERSION)
|
||||
if err != nil {
|
||||
logs.Error("CheckUpdate => ", err)
|
||||
os.Exit(0)
|
||||
|
|
|
@ -8,6 +8,7 @@ sessionon = true
|
|||
sessionname = mindoc_id
|
||||
copyrequestbody = true
|
||||
enablexsrf = "${MINDOC_ENABLE_XSRF||false}"
|
||||
enable_iframe = "${MINDOC_ENABLE_IFRAME||false}"
|
||||
|
||||
#系统完整URL(http://doc.iminho.me),如果该项不设置,会从请求头中获取地址。
|
||||
baseurl="${MINDOC_BASE_URL}"
|
||||
|
@ -230,6 +231,7 @@ dingtalk_qr_key="${MINDOC_DINGTALK_QRKEY}"
|
|||
# 钉钉扫码登录Secret
|
||||
dingtalk_qr_secret="${MINDOC_DINGTALK_QRSECRET}"
|
||||
|
||||
|
||||
# i18n config
|
||||
default_lang="zh-cn"
|
||||
|
||||
|
||||
|
|
|
@ -152,6 +152,11 @@ func GetEnableExport() bool {
|
|||
return web.AppConfig.DefaultBool("enable_export", true)
|
||||
}
|
||||
|
||||
//是否启用iframe
|
||||
func GetEnableIframe() bool {
|
||||
return web.AppConfig.DefaultBool("enable_iframe", false)
|
||||
}
|
||||
|
||||
//同一项目导出线程的并发数
|
||||
func GetExportProcessNum() int {
|
||||
exportProcessNum := web.AppConfig.DefaultInt("export_process_num", 1)
|
||||
|
@ -208,6 +213,15 @@ func IsAllowUploadFileExt(ext string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
//读取配置文件值
|
||||
func CONF(key string, value ...string) string {
|
||||
defaultValue := ""
|
||||
if len(value) > 0 {
|
||||
defaultValue = value[0]
|
||||
}
|
||||
return web.AppConfig.DefaultString(key, defaultValue)
|
||||
}
|
||||
|
||||
//重写生成URL的方法,加上完整的域名
|
||||
func URLFor(endpoint string, values ...interface{}) string {
|
||||
baseUrl := web.AppConfig.DefaultString("baseurl", "")
|
||||
|
|
|
@ -0,0 +1,570 @@
|
|||
[common]
|
||||
title = mindoc
|
||||
home = Home
|
||||
blog = Blog
|
||||
project_space = Project Space
|
||||
person_center = Personal Center
|
||||
my_project = My Project
|
||||
my_blog = My Article
|
||||
manage = Management
|
||||
login = Log In
|
||||
logout = Log Out
|
||||
official_website = Official Website
|
||||
feedback = Feedback
|
||||
source_code = Source Code
|
||||
manual = Manual
|
||||
username = Username
|
||||
account = Account
|
||||
email = Email
|
||||
password = Password
|
||||
role = Role
|
||||
captcha = Captcha
|
||||
keep_login = Stay signed in
|
||||
forgot_password = Forgot password?
|
||||
register = Create New Account
|
||||
dingtalk_login = DingTalk QrCode login
|
||||
account_recovery = Account recovery
|
||||
new_password = New password
|
||||
confirm_password = Confirm password
|
||||
new_account = Create New Account
|
||||
setting = Setting
|
||||
save = Save
|
||||
edit = Edit
|
||||
delete = Delete
|
||||
cancel = Cancel
|
||||
create = Create
|
||||
confirm_delete = Confirm
|
||||
upload_lang = en
|
||||
js_lang = en
|
||||
remove = Remove
|
||||
operate = Operate
|
||||
confirm = Confirm
|
||||
creator = Creator
|
||||
administrator = Administrator
|
||||
editor = Editor
|
||||
observer = Observer
|
||||
back = Back
|
||||
detail = Detail
|
||||
admin_right = Reading, writing and management
|
||||
editor_right = Reading and writing
|
||||
observer_right = Reading only
|
||||
yes = yes
|
||||
no = no
|
||||
read = Read
|
||||
generate = Generate
|
||||
|
||||
[init]
|
||||
default_proj_name = MinDoc Demo Project
|
||||
default_proj_desc = This is a MinDoc demo project, which is automatically created when the system is initialized.
|
||||
default_proj_space = Default Project Space
|
||||
blank_doc = Blank document
|
||||
|
||||
[message]
|
||||
tips = Tips
|
||||
page_not_existed = The page does not exist
|
||||
no_permission = No enough permissions
|
||||
keyword_placeholder = input keyword please...
|
||||
wrong_account_password = Incorrect username or password
|
||||
wrong_password = Wrong password
|
||||
click_to_change = Click to change one
|
||||
logging_in = logging in...
|
||||
need_relogin = Relogin please.
|
||||
return_account_login = Return account password login
|
||||
no_account_yet = No account yet?
|
||||
has_account = Already have an account?
|
||||
account_empty = Account cannot be empty
|
||||
email_empty = Email cannot be empty
|
||||
password_empty = Password cannot be empty
|
||||
captcha_empty = Captcha cannot be empty
|
||||
system_error = System error
|
||||
processing = Processing...
|
||||
email_sent = The email is sent successfully, please log in to check it.
|
||||
confirm_password_empty = Confirm password cannot be empty
|
||||
incorrect_confirm_password = Incorrect confirm password
|
||||
illegal_request = Illegal request
|
||||
account_or_password_empty = Account or Password cannot be empty
|
||||
captcha_wrong = Incorrect captcha
|
||||
password_length_invalid = The password cannot be empty and must be between 6-50 characters
|
||||
mail_expired = Mail has expired
|
||||
captcha_expired = The verification code has expired, please try again.
|
||||
user_not_existed = User does not exist
|
||||
email_not_exist = Email does not exist
|
||||
failed_save_password = Failed to save password
|
||||
mail_service_not_enable = Mail service is not enabled
|
||||
account_disable = Account has been disabled
|
||||
failed_send_mail = Failed to send mail
|
||||
sent_too_many_times = Send too many times, please try again later
|
||||
account_not_support_retrieval = The current user does not support password retrieval
|
||||
username_invalid_format = The account number can only be composed of English alphanumerics and 3-50 characters
|
||||
email_invalid_format = Email format is incorrect
|
||||
account_existed = Username already existed
|
||||
failed_register = Registration failed, please contact the system administrator
|
||||
failed_obtain_user_info = Failed to obtain identity information
|
||||
dingtalk_auto_login_not_enable = DingTalk automatic login function is not enabled
|
||||
failed_auto_login = Automatic login failed
|
||||
no_project = No Project
|
||||
item_not_exist = Item does not exist or has been deleted
|
||||
item_not_exist_or_no_permit = Item does not exist or has insufficient permissions
|
||||
doc_not_exist = Document does not exist or has been deleted
|
||||
doc_not_exist_or_no_permit = Document does not exist or has insufficient permissions
|
||||
unknown_exception = Unknown Exception
|
||||
no_data = No Data
|
||||
project_must_belong_space = Project must belong to a project space, and the administrator can manage it
|
||||
project_title_placeholder = Title (limit in 30 words)
|
||||
project_title_tips = Project name cannot exceed 100 characters
|
||||
project_id_placeholder = Project ID (limit in 30 characters)
|
||||
project_id_tips = The ID can only contain lowercase letters, numbers, and "-", "." and "_" symbols.
|
||||
project_desc_placeholder = Project description cannot exceed 500 characters
|
||||
project_public_desc = (Anyone can access)
|
||||
project_private_desc = (Only participants or use tokens can access)
|
||||
project_cover_desc = The Cover can be edit in the settings
|
||||
confirm_delete_project = Are you sure you want to delete the project?
|
||||
warning_delete_project = Remove items will not be retrieved.
|
||||
project_space_empty = Please select project space
|
||||
project_title_empty = Project title cannot be empty
|
||||
project_id_empty = Project ID cannot be empty
|
||||
project_id_existed = Project ID already in use
|
||||
project_id_error = Project ID error
|
||||
project_id_length = Project ID must be less than 50 characters
|
||||
import_file_empty = Please select the file to upload
|
||||
file_type_placeholder = Please select a Zip file
|
||||
publish_to_queue = The publish task has been pushed to the task queue and will be executed soon.
|
||||
team_name_empty = Team name cannot be empty
|
||||
operate_failed = Operation failed
|
||||
project_id_desc = The project ID is used to mark the uniqueness of the item and cannot be modified.
|
||||
history_record_amount_desc = When document history enabled, this value limits the number of history saved per document
|
||||
corp_id_desc = The footer that appears when the document PDF document is exported
|
||||
project_desc_desc = The description information is no more than 500 characters, supports markdown syntax
|
||||
project_desc_tips = The description information is no more than 500 characters
|
||||
access_pass_desc = The password that needs to be provided to access the project without permit
|
||||
auto_publish_desc = Enable for each save is automatically published to the latest version
|
||||
enable_export_desc = Configure the exporter before you start the export, also enable the export function in the profile
|
||||
enable_share_desc = Sharing is only available for public projects, and private projects do not support sharing
|
||||
auto_save_desc = Save automatically every 30 seconds
|
||||
confirm_into_private = Are you sure you want to make your project private?
|
||||
into_private_notice = Private project need provide access token
|
||||
confirm_into_public = Are you sure you want to make your project public?
|
||||
into_public_notice = Public project could be visit by anyone
|
||||
project_name_empty = Project name cannot be empty
|
||||
success = Success
|
||||
failed = Failed
|
||||
receive_account_empty = The recipient account cannot be empty
|
||||
receive_account_not_exist = The recipient account not exist
|
||||
receive_account_disabled = The recipient account disable
|
||||
cannot_preview = Cannot preview
|
||||
upload_failed = Upload failed
|
||||
upload_file_size_limit = The file must be less than 2MB
|
||||
upload_file_empty = Upload file is empty
|
||||
uploda_file_type_error = upload file type is wrong
|
||||
choose_pic_file = Please select a picture
|
||||
no_doc_in_cur_proj = No documents for the current project
|
||||
build_doc_tree_error = There was an error building the project document tree
|
||||
param_error = Parameter error
|
||||
doc_name_empty = Document name cannot empty
|
||||
parent_id_not_existed = Parent ID not existed
|
||||
doc_not_belong_project = The document does not belong to the specified project`
|
||||
attachment_not_exist = Attachment does not exist
|
||||
read_file_error = Load file error
|
||||
confirm_override_doc = The document has been modified, are you sure to override it?
|
||||
doc_auto_published = The document was automatically published
|
||||
export_func_disable = The export function is disable
|
||||
cur_project_export_func_disable = The export function is disable for current Project
|
||||
cur_project_not_support_md = The Markdown editor is not supported for the current project
|
||||
export_failed = The export failed, check the system logs
|
||||
file_converting = The document is being converted in the background, please download it later
|
||||
unsupport_file_type = Unsupport file type
|
||||
no_exportable_file = The project has no exportable file
|
||||
gen_qrcode_failed = Generate QrCode failed
|
||||
search_result_error = Search error
|
||||
get_doc_his_failed = Fail to get document history
|
||||
project_space_not_exist = Project space does not exist
|
||||
search_placeholder = input keyword please
|
||||
no_search_result = No search results!
|
||||
user_exist_in_proj = The user already exists in the project
|
||||
cannot_change_own_priv = Cannot change own permissions
|
||||
cannot_delete_self = Cannot delete myself
|
||||
cannot_handover_myself = Cannot handover to myself
|
||||
confirm_delete_blog = Confirm delete blog?
|
||||
delete_blog_tips = Deleted blog cannot be retrieved.
|
||||
input_proj_id_pls = input project ID please
|
||||
input_doc_id_pls = input document ID please
|
||||
blog_digest_tips = blog digest cannot exceed 500 characters
|
||||
blog_title_empty = blog title cannot be empty
|
||||
blog_not_exist = Blog does not exist or has been deleted
|
||||
blog_pwd_incorrect = Access password incorrect
|
||||
set_pwd_pls = please set password for encrypt blog
|
||||
unknown_blog_type = unknown blog type
|
||||
blog_title_tips = blog title cannot exceed 200 characters
|
||||
ref_doc_prj_not_existed = The Project of reference document not existed
|
||||
query_ref_doc_error = query reference document failed
|
||||
ref_doc_not_exist_or_no_permit = reference document does not exist or has insufficient permissions
|
||||
blog_id_existed = blog id already existed
|
||||
query_failed = query failed
|
||||
blog_has_modified = The article has been modified
|
||||
cur_user_cannot_change_pwd = The current user does not support changing the password
|
||||
origin_pwd_empty = The origin password cannot be empty
|
||||
new_pwd_empty = The new password cannot be empty
|
||||
confirm_pwd_empty = The confirm password cannot be empty
|
||||
pwd_length = Password must be between 6-18 characters
|
||||
pwd_length_tips = Password must be between 6-50 characters
|
||||
wrong_origin_pwd = The origin password incorrect
|
||||
wrong_confirm_pwd = The confirm passwrod incorrect
|
||||
same_pwd = The new password must different from the origin
|
||||
pwd_encrypt_failed = Password encryption failed
|
||||
team_name_empty = Team name cannot be emtpy
|
||||
proj_empty = Project cannot be empty
|
||||
site_name_empty = Site name cannot be empty
|
||||
proj_space_name_empty = Project space name cannot be empty
|
||||
proj_space_id_empty = Project space id cannot be empty
|
||||
proj_space_id_tips = The project space id can only consist of letters and numbers and be between 2-100 characters
|
||||
project_order_desc = Number only, sort from largest to smallest
|
||||
project_label_desc = Allows up to 10 labels, use ";" to separate multiple tags
|
||||
cannot_change_own_status = Cannot change own status
|
||||
cannot_change_super_status = Cannot change super administrator status
|
||||
cannot_change_super_priv = Cannot change super administrator permissions
|
||||
|
||||
[blog]
|
||||
author = Author
|
||||
project_list = Project List
|
||||
add_project = Add Project
|
||||
import_project = Import Project
|
||||
delete_project = Delete Project
|
||||
project_summary = Project summary
|
||||
read = Read
|
||||
edit = Edit
|
||||
delete = Delete
|
||||
copy = Copy
|
||||
view = View
|
||||
publish = Publish
|
||||
edit_doc = Edit Document
|
||||
default_cover = Default Cover
|
||||
create_time = Create Time
|
||||
update_time = Update Time
|
||||
creator = Creator
|
||||
doc_amount = Number of documents
|
||||
doc_unit =
|
||||
project_role = Project Role
|
||||
last_edit = Last Edited
|
||||
project_title = Project Title
|
||||
project_id = Project ID
|
||||
project_desc = Project description
|
||||
public = Public
|
||||
private = Private
|
||||
public_project = Public Project
|
||||
private_project = Private Project
|
||||
summary = Summary
|
||||
member = Member
|
||||
team = Team
|
||||
comment_amount = Number of comments
|
||||
comment_unit =
|
||||
member_manage = Member Manage
|
||||
add_member = Add Member
|
||||
administrator = Administrator
|
||||
editor = Editor
|
||||
observer = Observer
|
||||
team_manage = Team Manage
|
||||
add_team = Add Team
|
||||
team_name = Team name
|
||||
member_amount = Number of members
|
||||
join_time = Join Time
|
||||
project_setting = Project setting
|
||||
handover_project = Hanover
|
||||
make_public = Into Public
|
||||
make_private = Into Privete
|
||||
history_record_amount = Number of history records
|
||||
corp_id = corp name
|
||||
text_editor = editor
|
||||
project_label = Project Label
|
||||
project_order = Project Order
|
||||
access_pass = Access Password
|
||||
access_token = Access Token
|
||||
auto_publish = Auto publish
|
||||
enable_export = Enable Export
|
||||
enable_share = Enable Share
|
||||
set_first_as_home = Set the first document as the default homepage
|
||||
auto_save = Auto Save
|
||||
cover = Cover
|
||||
click_change_cover = Click to change the cover
|
||||
change_cover = Change Cover
|
||||
preview = Preview
|
||||
choose = Choose
|
||||
upload = Upload
|
||||
recipient_account = Recipient
|
||||
blog_list = Blog List
|
||||
add_blog = Add Blog
|
||||
encryption = encryption
|
||||
encrypt = encrypt
|
||||
edit_blog = Edit blog
|
||||
delete_blog = Delete blog
|
||||
setting_blog = Setting Blog
|
||||
no_blog = No Blog
|
||||
blog_setting = Blog Setting
|
||||
title = Blog Title
|
||||
type = Blog Type
|
||||
normal_blog = Normal Blog
|
||||
link_blog = Link Blog
|
||||
ref_doc = Reference Document
|
||||
blog_status = Blog Status
|
||||
blog_pwd = Blog Password
|
||||
blog_digest = Blog Digest
|
||||
posted_on = Posted on
|
||||
modified_on = Modified on
|
||||
prev = prev
|
||||
next = next
|
||||
no = no
|
||||
edit_title = Edit Blog
|
||||
|
||||
[doc]
|
||||
modify_doc = Modify Document
|
||||
comparison = Comparison
|
||||
save_merge = Save Merge
|
||||
prev_diff = Previous difference
|
||||
next_diff = Next difference
|
||||
merge_to_left = Merge to left
|
||||
merge_to_right = Merge to right
|
||||
exchange_left_right = Exchange left and right
|
||||
print = Print
|
||||
download = Download
|
||||
share = Share
|
||||
share_project = Share project
|
||||
share_url = Project URL
|
||||
contents = Contents
|
||||
search = Search
|
||||
expand = Unfold
|
||||
fold = Fold
|
||||
close = Close
|
||||
doc_publish_by = Document is Published by
|
||||
doc_publish =
|
||||
edit_doc = Edit Document
|
||||
backward = backward
|
||||
save = save
|
||||
save_as_tpl = save as template
|
||||
undo = undo
|
||||
redo = redo
|
||||
bold = bold
|
||||
italic = italic
|
||||
strikethrough = strikethrough
|
||||
h1 = head 1
|
||||
h2 = head 2
|
||||
h3 = head 3
|
||||
h4 = head 4
|
||||
h5 = head 5
|
||||
h6 = head 6
|
||||
unorder_list = disorder list
|
||||
order_list = order list
|
||||
hline = horizontal line
|
||||
link = link
|
||||
ref_link = reference link
|
||||
add_pic = add picture
|
||||
code = code
|
||||
code_block = code block
|
||||
table = add table
|
||||
quote = quote
|
||||
gfm_task = GFM task
|
||||
attachment = attachment
|
||||
json_to_table = Json converted to table
|
||||
template = template
|
||||
close_preview = disable preview
|
||||
modify_history = modify history
|
||||
sidebar = sidebar
|
||||
help = help
|
||||
publish = publish
|
||||
document = document
|
||||
create_doc = create document
|
||||
attachments = attachments
|
||||
doc_name = Document name
|
||||
doc_name_tips = Right-click on the document name of the directory to delete and modify the document name and add subordinate documents
|
||||
doc_id = Document ID
|
||||
doc_id_tips = The document ID can only contain lowercase letters, numbers, and "-" and "_" symbols, and can only start with a lowercase letter
|
||||
expand_desc = (Expand nodes when reading)
|
||||
fold_desc = (Fold nodes when reading)
|
||||
empty_contents = Empty contents
|
||||
empty_contents_desc = Click to expand the subordinate nodes
|
||||
upload_attachment = Upload attachment
|
||||
doc_history = Document history
|
||||
choose_template_type = Choose template type please
|
||||
normal_tpl = Normal
|
||||
api_tpl = API
|
||||
data_dict = Data Dictionary
|
||||
custom_tpl = Custom
|
||||
tpl_default_type = Default type
|
||||
tpl_plain_text = Plain Text
|
||||
for_api_doc = Used for API Document
|
||||
code_highlight = support code highlighting
|
||||
for_data_dict = Used for data dictionary
|
||||
form_support = Form Support
|
||||
any_type_doc = Support any type of document
|
||||
as_global_tpl = Can be set as a global template
|
||||
tpl_name = Template name
|
||||
tpl_type = Template type
|
||||
creator = Creator
|
||||
create_time = Create time
|
||||
operation = Operation
|
||||
global_tpl = Global
|
||||
global_tpl_desc = (Any Project is available)
|
||||
project_tpl = Project
|
||||
project_tpl_desc = (Only the current Project is available)
|
||||
insert = insert
|
||||
uploading = Uploading
|
||||
his_ver = Historic version
|
||||
update_time = Update time
|
||||
updater = Updater
|
||||
version = Version
|
||||
delete = Delete
|
||||
recover = Recover
|
||||
merge = Merge
|
||||
comparison_title = Document comparison [the left is the historical document, the right is the current document, please merge the documents to the right]
|
||||
font_size = font size
|
||||
underscore = underscore
|
||||
right_intent = right intent
|
||||
left_intent = left intent
|
||||
subscript = subscript
|
||||
superscript = superscript
|
||||
clean_format = clear format
|
||||
add_video = add video
|
||||
formula = formula
|
||||
font_color = font color
|
||||
bg_color = background color
|
||||
input_pwd = input password please
|
||||
read_pwd = read password
|
||||
commit = commit
|
||||
ft_author = Author:
|
||||
ft_last_editor = Last editor:
|
||||
ft_create_time = Create time:
|
||||
ft_update_time = Update time:
|
||||
view_count = Number of views
|
||||
|
||||
[project]
|
||||
prj_space_list = Project Space List
|
||||
prj_space_list_of = List of Project Space %s
|
||||
search_title = Show Items of Project Space "%s"
|
||||
author = Author
|
||||
no_project = No Project
|
||||
prj_amount = Project Count
|
||||
creator = Creator
|
||||
create_time = Create time
|
||||
no_project_space = No Project Space
|
||||
|
||||
[search]
|
||||
title = Search
|
||||
search_title = Show search result for %s
|
||||
doc = document
|
||||
prj = project
|
||||
blog = blog
|
||||
from_proj = from project
|
||||
from_blog = from blog
|
||||
author = author
|
||||
update_time = update time
|
||||
no_result = No search result
|
||||
|
||||
[page]
|
||||
first = first
|
||||
last = last
|
||||
prev = prev
|
||||
next = next
|
||||
|
||||
[uc]
|
||||
user_center = User Center
|
||||
base_info = Basic Info
|
||||
change_pwd = Change Password
|
||||
username = Username
|
||||
nickname = Nickname
|
||||
realname = Real name
|
||||
email = Email
|
||||
mobile = Mobile
|
||||
description = Description
|
||||
description_tips = Description cannot exceed 500 characters
|
||||
avatar = Avatar
|
||||
change_avatar = Change avatar
|
||||
password = Password
|
||||
origin_pwd = Origin password
|
||||
new_pwd = New password
|
||||
confirm_pwd = Confirm password
|
||||
role = Role
|
||||
type = Type
|
||||
status = Status
|
||||
super_admin = Super administrator
|
||||
admin = Administrator
|
||||
user = User
|
||||
normal = Normal
|
||||
disable = Disable
|
||||
enable = Enable
|
||||
create_user = Create User
|
||||
edit_user = Edit User
|
||||
pwd_tips = Please leave it blank if you do not change the password, only local users can change the password
|
||||
|
||||
[mgr]
|
||||
dashboard_menu = Dashboard
|
||||
user_menu = User
|
||||
team_menu = Team
|
||||
project_menu = Project
|
||||
project_space_menu = Project Space
|
||||
comment_menu = Comment
|
||||
config_menu = Configure
|
||||
attachment_menu = Attachment
|
||||
label_menu = Label
|
||||
dashboard_mgr = Dashboard
|
||||
user_mgr = User Management
|
||||
team_mgr = Team Management
|
||||
project_mgr = Project Management
|
||||
project_space_mgr = Project Space Management
|
||||
comment_mgr = Comment Management
|
||||
config_mgr = Configure Management
|
||||
config_file = Configure File
|
||||
attachment_mgr = Attachment Management
|
||||
label_mgr = Label Management
|
||||
label_name = Label name
|
||||
used_quantity = Used Quantity
|
||||
proj_amount = Number Of Project
|
||||
blog_amount = Number Of Blog
|
||||
member_amount = Number Of Member
|
||||
comment_amount = Number Of Comment
|
||||
attachment_amount = Number Of Attachment
|
||||
member_mgr = Member Management
|
||||
add_member = Add Member
|
||||
create_team = Create Team
|
||||
team_name = Team Name
|
||||
proj = Project
|
||||
member = Member
|
||||
edit_team = Edit Team
|
||||
team_member_mgr = Team Member Management
|
||||
team_proj = Team Project
|
||||
add_proj = Add Project
|
||||
proj_name = Project name
|
||||
proj_author = Project author
|
||||
join_time = Join Time
|
||||
join_proj = Join
|
||||
file_name = File name
|
||||
is_exist = Is Exist
|
||||
exist = Exist
|
||||
deleted = Deleted
|
||||
proj_blog_name = Project/Blog name
|
||||
doc_name = Document name
|
||||
file_path = File path
|
||||
download_url = Download URL
|
||||
file_size = File size
|
||||
upload_time = Upload time
|
||||
download = Download
|
||||
download_title = Download to local
|
||||
attachment_name = Attachment name
|
||||
site_name = Site Name
|
||||
domain_icp = Domain ICP
|
||||
site_desc = Site Description
|
||||
site_desc_tips = Description cannot exceed 500 characters
|
||||
enable_anonymous_access = Enable anonymous access
|
||||
enable = Enable
|
||||
disable = Disable
|
||||
enable_register = Enable Registration
|
||||
enable_captcha = Enable Captcha
|
||||
enable_doc_his = Enable Document Historic
|
||||
proj_space_name = Project space name
|
||||
proj_space_id = Project space ID
|
||||
create_proj_space = Create Project Space
|
||||
edit_proj_space = Edit Project Space
|
||||
proj_list = Project List
|
||||
edit_proj = Edit Project
|
||||
create_time = Create Time
|
||||
creator = Creator
|
||||
doc_amount = Number of Document
|
||||
last_edit = Last Edit
|
||||
delete_project = Delete Project
|
|
@ -0,0 +1,570 @@
|
|||
[common]
|
||||
title = 文档在线管理系统
|
||||
home = 首页
|
||||
blog = 文章
|
||||
project_space = 项目空间
|
||||
person_center = 个人中心
|
||||
my_project = 我的项目
|
||||
my_blog = 我的文章
|
||||
manage = 管理后台
|
||||
login = 登录
|
||||
logout = 退出登录
|
||||
official_website = 官方网站
|
||||
feedback = 意见反馈
|
||||
source_code = 项目源码
|
||||
manual = 使用手册
|
||||
username = 用户名
|
||||
account = 账号
|
||||
email = 邮箱
|
||||
password = 密码
|
||||
role = 角色
|
||||
captcha = 验证码
|
||||
keep_login = 保持登录
|
||||
forgot_password = 忘记密码?
|
||||
register = 立即注册
|
||||
dingtalk_login = 扫码登录
|
||||
account_recovery = 找回密码
|
||||
new_password = 新密码
|
||||
confirm_password = 确认密码
|
||||
new_account = 用户注册
|
||||
setting = 设置
|
||||
save = 保存
|
||||
edit = 编辑
|
||||
delete = 删除
|
||||
cancel = 取消
|
||||
create = 创建
|
||||
confirm_delete = 确定删除
|
||||
upload_lang = zh
|
||||
js_lang = zh-CN
|
||||
remove = 移除
|
||||
operate = 操作
|
||||
confirm = 确定
|
||||
creator = 创始人
|
||||
administrator = 管理员
|
||||
editor = 编辑者
|
||||
observer = 观察者
|
||||
back = 返回
|
||||
detail = 详情
|
||||
admin_right = 拥有阅读、写作和管理权限
|
||||
editor_right = 拥有阅读和写作权限
|
||||
observer_right = 拥有阅读权限
|
||||
yes = 是
|
||||
no = 否
|
||||
read = 阅读
|
||||
generate = 生成
|
||||
|
||||
[init]
|
||||
default_proj_name = MinDoc演示项目
|
||||
default_proj_desc = 这是一个MinDoc演示项目,该项目是由系统初始化时自动创建。
|
||||
default_proj_space = 默认项目空间
|
||||
blank_doc = 空白文档
|
||||
|
||||
[message]
|
||||
tips = 友情提示
|
||||
page_not_existed = 页面不存在
|
||||
no_permission = 权限不足
|
||||
keyword_placeholder = 请输入关键词...
|
||||
wrong_account_password = 账号或密码错误
|
||||
wrong_password = 密码错误
|
||||
click_to_change = 点击换一张
|
||||
logging_in = 正在登录...
|
||||
need_relogin = 请重新登录。
|
||||
return_account_login = 返回账号密码登录
|
||||
no_account_yet = 还没有账号?
|
||||
has_account = 已有账号?
|
||||
account_empty = 账号不能为空
|
||||
email_empty = 邮箱不能为空
|
||||
password_empty = 密码不能为空
|
||||
captcha_empty = 验证码不能为空
|
||||
system_error = 系统错误
|
||||
processing = 正在处理...
|
||||
email_sent = 邮件发送成功,请登录邮箱查看。
|
||||
confirm_password_empty = 确认密码不能为空
|
||||
incorrect_confirm_password = 确认密码输入不正确
|
||||
illegal_request = 非法请求
|
||||
account_or_password_empty = 账号或密码不能为空
|
||||
captcha_wrong = 验证码不正确
|
||||
password_length_invalid = 密码不能为空且必须在6-50个字符之间
|
||||
mail_expired = 邮件已失效
|
||||
captcha_expired = 验证码已过期,请重新操作。
|
||||
user_not_existed = 用户不存在
|
||||
email_not_exist = 邮箱不存在
|
||||
failed_save_password = 保存密码失败
|
||||
mail_service_not_enable = 未启用邮件服务
|
||||
account_disable = 账号已被禁用
|
||||
failed_send_mail = 发送邮件失败
|
||||
sent_too_many_times = 发送次数太多,请稍候再试
|
||||
account_not_support_retrieval = 当前用户不支持找回密码
|
||||
username_invalid_format = 账号只能由英文字母数字组成,且在3-50个字符
|
||||
email_invalid_format = 邮箱格式不正确
|
||||
account_existed = 账号已存在
|
||||
failed_register = 注册失败,请联系管理员
|
||||
failed_obtain_user_info = 获取身份信息失败
|
||||
dingtalk_auto_login_not_enable = 未开启钉钉自动登录功能
|
||||
failed_auto_login = 自动登录失败
|
||||
no_project = 暂无项目
|
||||
item_not_exist = 项目不存在或已删除
|
||||
item_not_exist_or_no_permit = 项目不存在或权限不足
|
||||
doc_not_exist = 文档不存在或已删除
|
||||
doc_not_exist_or_no_permit = 文档不存在或权限不足
|
||||
unknown_exception = 未知异常
|
||||
no_data = 暂无数据
|
||||
project_must_belong_space = 每个项目必须归属一个项目空间,超级管理员可在后台管理和维护
|
||||
project_title_placeholder = 项目标题(不超过100字)
|
||||
project_title_tips = 项目标题不能超过100字符
|
||||
project_id_placeholder = 项目唯一标识(不超过50字)
|
||||
project_id_tips = 文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号.
|
||||
project_desc_placeholder = 描述信息不超过500个字符
|
||||
project_public_desc = (任何人都可以访问)
|
||||
project_private_desc = (只有参与者或使用令牌才能访问)
|
||||
project_cover_desc = 项目图片可在项目设置中修改
|
||||
confirm_delete_project = 确定删除项目吗?
|
||||
warning_delete_project = 删除项目后将无法找回。
|
||||
project_space_empty = 请选择项目空间
|
||||
project_title_empty = 项目标题不能为空
|
||||
project_id_empty = 项目标识不能为空
|
||||
project_id_existed = 文档标识已被使用
|
||||
project_id_error = 项目标识有误
|
||||
project_id_length = 项目标识必须小于50字符
|
||||
import_file_empty = 请选择需要上传的文件
|
||||
file_type_placeholder = 请选择Zip或Docx文件
|
||||
publish_to_queue = 发布任务已推送到任务队列,稍后将在后台执行。
|
||||
team_name_empty = 团队名称不能为空
|
||||
operate_failed = 操作失败
|
||||
project_id_desc = 项目标识用来标记项目的唯一性,不可修改。
|
||||
history_record_amount_desc = 当开启文档历史时,该值会限制每个文档保存的历史数量
|
||||
corp_id_desc = 导出文档PDF文档时显示的页脚
|
||||
project_desc_desc = 描述信息不超过500个字符,支持Markdown语法
|
||||
project_desc_tips = 项目描述不能大于500字
|
||||
access_pass_desc = 没有访问权限访问项目时需要提供的密码
|
||||
auto_publish_desc = 开启后,每次保存会自动发布到最新版本
|
||||
enable_export_desc = 开启导出前请先配置导出程序,并在配置文件中同时开启导出功能
|
||||
enable_share_desc = 分享只对公开项目生效,私有项目不支持分享
|
||||
auto_save_desc = 开启后每隔30秒会自动保存
|
||||
confirm_into_private = 确定将项目转为私有吗?
|
||||
into_private_notice = 转为私有后需要通过阅读令牌才能访问该项目。
|
||||
confirm_into_public = 确定将项目转为公有吗?
|
||||
into_public_notice = 转为公有后所有人都可以访问该项目。
|
||||
project_name_empty = 项目名称不能为空
|
||||
success = 成功
|
||||
failed = 失败
|
||||
receive_account_empty = 接受者账号不能为空
|
||||
receive_account_not_exist = 接受用户不存在
|
||||
receive_account_disabled = 接受用户已被禁用
|
||||
cannot_preview = 不能预览
|
||||
upload_failed = 上传失败
|
||||
upload_file_size_limit = 文件必须小于2MB
|
||||
upload_file_empty = 上传文件为空
|
||||
uploda_file_type_error = 文件类型有误
|
||||
choose_pic_file = 请选择图片
|
||||
no_doc_in_cur_proj = 当前项目没有文档
|
||||
build_doc_tree_error = 生成项目文档树时出错
|
||||
param_error = 参数错误
|
||||
doc_name_empty = 文档名称不能为空
|
||||
parent_id_not_existed = 父分类不存在
|
||||
doc_not_belong_project = 文档不属于指定的项目
|
||||
attachment_not_exist = 附件不存在或已删除
|
||||
read_file_error = 读取文档错误
|
||||
confirm_override_doc = 文档已被修改确定要覆盖吗?
|
||||
doc_auto_published = 文档自动发布成功
|
||||
export_func_disable = 系统没有开启导出功能
|
||||
cur_project_export_func_disable = 当前项目没有开启导出功能
|
||||
cur_project_not_support_md = 当前项目不支持Markdown编辑器
|
||||
export_failed = 导出失败,请查看系统日志
|
||||
file_converting = 文档正在后台转换,请稍后再下载
|
||||
unsupport_file_type = 不支持的文件格式
|
||||
no_exportable_file = 项目没有导出文件
|
||||
gen_qrcode_failed = 生成二维码失败
|
||||
search_result_error = 搜索结果错误
|
||||
get_doc_his_failed = 获取历史失败
|
||||
project_space_not_exist = 项目空间不存在
|
||||
search_placeholder = 请输入搜索关键字
|
||||
no_search_result = 暂无相关搜索结果!
|
||||
user_exist_in_proj = 用户已存在该项目中
|
||||
cannot_change_own_priv = 不能变更自己的权限
|
||||
cannot_delete_self = 不能删除自己
|
||||
cannot_handover_myself = 不能转让给自己
|
||||
confirm_delete_blog = 确定删除文章吗?
|
||||
delete_blog_tips = 删除文章后将无法找回。
|
||||
input_proj_id_pls = 请输入项目标识
|
||||
input_doc_id_pls = 请输入文档标识
|
||||
blog_digest_tips = 文章摘要不超过500个字符
|
||||
blog_title_empty = 文章标题不能为空
|
||||
blog_not_exist = 文章不存在或已删除
|
||||
blog_pwd_incorrect = 文章密码不正确
|
||||
set_pwd_pls = 加密文章请设置密码
|
||||
unknown_blog_type = 未知的文章类型
|
||||
blog_title_tips = 文章标题不能大于200个字符
|
||||
ref_doc_prj_not_existed = 关联文档的项目不存在
|
||||
query_ref_doc_error = 查询关联项目文档时出错
|
||||
ref_doc_not_exist_or_no_permit = 关联文档不存在或权限不足
|
||||
blog_id_existed = 文章标识已存在
|
||||
query_failed = 查询失败
|
||||
blog_has_modified = 文章已被修改
|
||||
cur_user_cannot_change_pwd = 当前用户不支持修改密码
|
||||
origin_pwd_empty = 原密码不能为空
|
||||
new_pwd_empty = 新密码不能为空
|
||||
confirm_pwd_empty = 确认密码不能为空
|
||||
pwd_length = 密码必须在6-18字之间
|
||||
pwd_length_tips = 密码必须在6-50个字符之间
|
||||
wrong_origin_pwd = 原始密码不正确
|
||||
wrong_confirm_pwd = 确认密码不正确
|
||||
same_pwd = 新密码不能和原始密码相同
|
||||
pwd_encrypt_failed = 密码加密失败
|
||||
team_name_empty = 团队名称不能为空
|
||||
proj_empty = 项目不能为空
|
||||
site_name_empty = 网站标题不能为空
|
||||
proj_space_name_empty = 项目空间名称不能为空
|
||||
proj_space_id_empty = 项目空间标识不能为空
|
||||
proj_space_id_tips = 项目空间标识只能由字母和数字组成且在2-100字符之间
|
||||
project_order_desc = 只能是数字,序号越大排序越靠前
|
||||
project_label_desc = 最多允许添加10个标签,多个标签请用“;”分割
|
||||
cannot_change_own_status = 不能变更自己的状态
|
||||
cannot_change_super_status = 不能变更超级管理员的状态
|
||||
cannot_change_super_priv = 不能变更超级管理员的权限
|
||||
|
||||
[blog]
|
||||
author = 作者
|
||||
project_list = 项目列表
|
||||
add_project = 添加项目
|
||||
import_project = 导入项目
|
||||
delete_project = 删除项目
|
||||
project_summary = 项目概要
|
||||
read = 阅读
|
||||
edit = 编辑
|
||||
delete = 删除
|
||||
copy = 复制
|
||||
view = 查看文档
|
||||
publish = 发布
|
||||
edit_doc = 编辑文档
|
||||
default_cover = 默认封面
|
||||
create_time = 创建时间
|
||||
update_time = 修改时间
|
||||
creator = 创建者
|
||||
doc_amount = 文档数量
|
||||
doc_unit = 篇
|
||||
project_role = 项目角色
|
||||
last_edit = 最后编辑
|
||||
project_title = 项目标题
|
||||
project_id = 项目标识
|
||||
project_desc = 项目描述
|
||||
public = 公开
|
||||
private = 私有
|
||||
public_project = 公开项目
|
||||
private_project = 私有项目
|
||||
summary = 概要
|
||||
member = 成员
|
||||
team = 团队
|
||||
comment_amount = 评论数量
|
||||
comment_unit = 条
|
||||
member_manage = 成员管理
|
||||
add_member = 添加成员
|
||||
administrator = 管理员
|
||||
editor = 编辑者
|
||||
observer = 观察者
|
||||
team_manage = 团队管理
|
||||
add_team = 添加团队
|
||||
team_name = 团队名称
|
||||
member_amount = 成员数量
|
||||
join_time = 加入时间
|
||||
project_setting = 项目设置
|
||||
handover_project = 转让项目
|
||||
make_public = 转为公有
|
||||
make_private = 转为私有
|
||||
history_record_amount = 历史记录数量
|
||||
corp_id = 公司名称
|
||||
text_editor = 编辑器
|
||||
project_label = 项目标签
|
||||
project_order = 项目排序
|
||||
access_pass = 访问密码
|
||||
access_token = 访问令牌
|
||||
auto_publish = 自动发布
|
||||
enable_export = 开启导出
|
||||
enable_share = 开启分享
|
||||
set_first_as_home = 设置第一篇文档为默认首页
|
||||
auto_save = 自动保存
|
||||
cover = 封面
|
||||
click_change_cover = 点击图片可修改项目封面
|
||||
change_cover = 修改封面
|
||||
preview = 预览
|
||||
choose = 选择
|
||||
upload = 上传
|
||||
recipient_account = 接收者账号
|
||||
blog_list = 文章列表
|
||||
add_blog = 添加文章
|
||||
encryption = 加密
|
||||
encrypt = 密
|
||||
edit_blog = 文章编辑
|
||||
delete_blog = 删除文章
|
||||
setting_blog = 文章设置
|
||||
no_blog = 暂无文章
|
||||
blog_setting = 文章设置
|
||||
title = 文章标题
|
||||
type = 文章类型
|
||||
normal_blog = 普通文章
|
||||
link_blog = 链接文章
|
||||
ref_doc = 关联文档
|
||||
blog_status = 文章状态
|
||||
blog_pwd = 文章密码
|
||||
blog_digest = 文章摘要
|
||||
posted_on = 发布于
|
||||
modified_on = 修改于
|
||||
prev = 上一篇
|
||||
next = 下一篇
|
||||
no = 无
|
||||
edit_title = 编辑文章
|
||||
|
||||
[doc]
|
||||
modify_doc = 修改文档
|
||||
comparison = 文档比较
|
||||
save_merge = 保存合并
|
||||
prev_diff = 上一处差异
|
||||
next_diff = 下一处差异
|
||||
merge_to_left = 合并到左侧
|
||||
merge_to_right = 合并到右侧
|
||||
exchange_left_right = 左右切换
|
||||
print = 打印
|
||||
download = 下载
|
||||
share = 分享
|
||||
share_project = 项目分享
|
||||
share_url = 项目地址
|
||||
contents = 目录
|
||||
search = 搜索
|
||||
expand = 展开
|
||||
fold = 收起
|
||||
close = 关闭
|
||||
doc_publish_by = 本文档使用
|
||||
doc_publish = 发布
|
||||
edit_doc = 编辑文档
|
||||
backward = 返回
|
||||
save = 保存
|
||||
save_as_tpl = 保存为模板
|
||||
undo = 撤销
|
||||
redo = 重做
|
||||
bold = 粗体
|
||||
italic = 斜体
|
||||
strikethrough = 删除线
|
||||
h1 = 标题一
|
||||
h2 = 标题二
|
||||
h3 = 标题三
|
||||
h4 = 标题四
|
||||
h5 = 标题五
|
||||
h6 = 标题六
|
||||
unorder_list = 无序列表
|
||||
order_list = 有序列表
|
||||
hline = Horizontal line
|
||||
link = 链接
|
||||
ref_link = 引用链接
|
||||
add_pic = 添加图片
|
||||
code = 行内代码
|
||||
code_block = 代码块
|
||||
table = 添加表格
|
||||
quote = 引用
|
||||
gfm_task = GFM 任务列表
|
||||
attachment = 附件
|
||||
json_to_table = Json转换为表格
|
||||
template = 模板
|
||||
close_preview = 关闭实时预览
|
||||
modify_history = 修改历史
|
||||
sidebar = 边栏
|
||||
help = 使用帮助
|
||||
publish = 发布
|
||||
document = 文档
|
||||
create_doc = 创建文档
|
||||
attachments = 个附件
|
||||
doc_name = 文档名称
|
||||
doc_name_tips = 在目录的文档名上右键可以删除和修改文档名称以及添加下级文档
|
||||
doc_id = 文档标识
|
||||
doc_id_tips = 文档标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头
|
||||
expand_desc = (在阅读时会自动展开节点)
|
||||
fold_desc = (在阅读时会关闭节点)
|
||||
empty_contents = 空目录
|
||||
empty_contents_desc = (单击时会展开下级节点)
|
||||
upload_attachment = 上传附件
|
||||
doc_history = 文档历史记录
|
||||
choose_template_type = 请选择模板类型
|
||||
normal_tpl = 普通文档
|
||||
api_tpl = API文档
|
||||
data_dict = 数据字典
|
||||
custom_tpl = 自定义模板
|
||||
tpl_default_type = 默认类型
|
||||
tpl_plain_text = 简单的文本文档
|
||||
for_api_doc = 用于API文档速写
|
||||
code_highlight = 支持代码高亮
|
||||
for_data_dict = 用于数据字典显示
|
||||
form_support = 表格支持
|
||||
any_type_doc = 支持任意类型文档
|
||||
as_global_tpl = 可以设置为全局模板
|
||||
tpl_name = 模板名称
|
||||
tpl_type = 模板类型
|
||||
creator = 创建人
|
||||
create_time = 创建时间
|
||||
operation = 操作
|
||||
global_tpl = 全局
|
||||
global_tpl_desc = (任何项目都可用)
|
||||
project_tpl = 项目
|
||||
project_tpl_desc = (只有当前项目可用)
|
||||
insert = 插入
|
||||
uploading = 正在上传
|
||||
his_ver = 历史版本
|
||||
update_time = 修改时间
|
||||
updater = 修改人
|
||||
version = 版本
|
||||
delete = 删除
|
||||
recover = 恢复
|
||||
merge = 合并
|
||||
comparison_title = 文档比较【左侧为历史文档,右侧为当前文档,请将文档合并到右侧】
|
||||
font_size = 字号
|
||||
underscore = 下划线
|
||||
right_intent = 右缩进
|
||||
left_intent = 左缩进
|
||||
subscript = 下标
|
||||
superscript = 上标
|
||||
clean_format = 清空格式
|
||||
add_video = 添加视频
|
||||
formula = 公式
|
||||
font_color = 字体颜色
|
||||
bg_color = 背景颜色
|
||||
input_pwd = 请输入密码
|
||||
read_pwd = 浏览密码
|
||||
commit = 提交
|
||||
ft_author = 作者:
|
||||
ft_last_editor = 最后编辑:
|
||||
ft_create_time = 创建时间:
|
||||
ft_update_time = 更新时间:
|
||||
view_count = 阅读次数
|
||||
|
||||
[project]
|
||||
prj_space_list = 项目空间列表
|
||||
prj_space_list_of = 项目空间%s的项目列表
|
||||
search_title = 显示项目空间为"%s"的项目
|
||||
author = 作者
|
||||
no_project = 暂无项目
|
||||
prj_amount = 项目数量
|
||||
creator = 创建人
|
||||
create_time = 创建时间
|
||||
no_project_space = 没有项目空间
|
||||
|
||||
[search]
|
||||
title = 搜索
|
||||
search_title = 显示"%s"的搜索结果
|
||||
doc = 文档
|
||||
prj = 项目
|
||||
blog = 文章
|
||||
from_proj = 来自项目
|
||||
from_blog = 来自文章
|
||||
author = 作者
|
||||
update_time = 更新时间
|
||||
no_result = 暂无相关搜索结果
|
||||
|
||||
[page]
|
||||
first = 首页
|
||||
last = 末页
|
||||
prev = 上一页
|
||||
next = 下一页
|
||||
|
||||
[uc]
|
||||
user_center = 用户中心
|
||||
base_info = 基本信息
|
||||
change_pwd = 修改密码
|
||||
username = 用户名
|
||||
nickname = 昵称
|
||||
realname = 真实姓名
|
||||
email = 邮箱
|
||||
mobile = 手机号
|
||||
description = 描述
|
||||
description_tips = 描述不能超过500字
|
||||
avatar = 头像
|
||||
change_avatar = 修改头像
|
||||
password = 密码
|
||||
origin_pwd = 原始密码
|
||||
new_pwd = 新密码
|
||||
confirm_pwd = 确认密码
|
||||
role = 角色
|
||||
type = 类型
|
||||
status = 状态
|
||||
super_admin = 超级管理员
|
||||
admin = 管理员
|
||||
user = 普通用户
|
||||
normal = 正常
|
||||
disable = 禁用
|
||||
enable = 启用
|
||||
create_user = 创建用户
|
||||
edit_user = 编辑用户
|
||||
pwd_tips = 不修改密码请留空,只支持本地用户修改密码
|
||||
|
||||
[mgr]
|
||||
dashboard_menu = 仪表盘
|
||||
user_menu = 用户管理
|
||||
team_menu = 团队管理
|
||||
project_menu = 项目管理
|
||||
project_space_menu = 项目空间管理
|
||||
comment_menu = 评论管理
|
||||
config_menu = 配置管理
|
||||
attachment_menu = 附件管理
|
||||
label_menu = 标签管理
|
||||
dashboard_mgr = 仪表盘
|
||||
user_mgr = 用户管理
|
||||
team_mgr = 团队管理
|
||||
project_mgr = 项目管理
|
||||
project_space_mgr = 项目空间管理
|
||||
comment_mgr = 评论管理
|
||||
config_mgr = 配置管理
|
||||
config_file = 配置文件
|
||||
attachment_mgr = 附件管理
|
||||
label_mgr = 标签管理
|
||||
label_name = 标签名称
|
||||
used_quantity = 使用数量
|
||||
proj_amount = 项目数量
|
||||
blog_amount = 文章数量
|
||||
member_amount = 成员数量
|
||||
comment_amount = 评论数量
|
||||
attachment_amount = 附件数量
|
||||
member_mgr = 成员管理
|
||||
add_member = 添加成员
|
||||
create_team = 创建团队
|
||||
team_name = 团队名称
|
||||
proj = 项目
|
||||
member = 成员
|
||||
edit_team = 编辑团队
|
||||
team_member_mgr = 团队用户管理
|
||||
team_proj = 团队项目
|
||||
add_proj = 添加项目
|
||||
proj_name = 项目名称
|
||||
proj_author = 项目作者
|
||||
join_time = 加入时间
|
||||
join_proj = 加入项目
|
||||
file_name = 文件名称
|
||||
is_exist = 是否存在
|
||||
exist = 存在
|
||||
deleted = 已删除
|
||||
proj_blog_name = 项目/文章名称
|
||||
doc_name = 文档名称
|
||||
file_path = 文件路径
|
||||
download_url = 下载路径
|
||||
file_size = 文件大小
|
||||
upload_time = 上传时间
|
||||
download = 下载
|
||||
download_title = 下载到本地
|
||||
attachment_name = 附件名称
|
||||
site_name = 网站标题
|
||||
domain_icp = 域名备案
|
||||
site_desc = 网站描述
|
||||
site_desc_tips = 描述信息不超过500个字符
|
||||
enable_anonymous_access = 启用匿名访问
|
||||
enable = 开启
|
||||
disable = 关闭
|
||||
enable_register = 启用注册
|
||||
enable_captcha = 启用验证码
|
||||
enable_doc_his = 启用文档历史
|
||||
proj_space_name = 项目空间名称
|
||||
proj_space_id = 项目空间标识
|
||||
create_proj_space = 创建项目空间
|
||||
edit_proj_space = 编辑项目空间
|
||||
proj_list = 项目列表
|
||||
edit_proj = 编辑项目
|
||||
create_time = 创建时间
|
||||
creator = 创建者
|
||||
doc_amount = 文档数量
|
||||
last_edit = 最后编辑
|
||||
delete_project = 删除项目
|
|
@ -1,6 +1,7 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/beego/i18n"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
@ -55,17 +56,17 @@ func (c *AccountController) Prepare() {
|
|||
}
|
||||
if token == "" {
|
||||
if c.IsAjax() {
|
||||
c.JsonResult(403, "非法请求")
|
||||
c.JsonResult(403, i18n.Tr(c.Lang, "message.illegal_request"))
|
||||
} else {
|
||||
c.ShowErrorPage(403, "非法请求")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.illegal_request"))
|
||||
}
|
||||
}
|
||||
xsrfToken := c.XSRFToken()
|
||||
if xsrfToken != token {
|
||||
if c.IsAjax() {
|
||||
c.JsonResult(403, "非法请求")
|
||||
c.JsonResult(403, i18n.Tr(c.Lang, "message.illegal_request"))
|
||||
} else {
|
||||
c.ShowErrorPage(403, "非法请求")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.illegal_request"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,12 +110,12 @@ func (c *AccountController) Login() {
|
|||
if v, ok := c.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") {
|
||||
v, ok := c.GetSession(conf.CaptchaSessionName).(string)
|
||||
if !ok || !strings.EqualFold(v, captcha) {
|
||||
c.JsonResult(6001, "验证码不正确")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong"))
|
||||
}
|
||||
}
|
||||
|
||||
if account == "" || password == "" {
|
||||
c.JsonResult(6002, "账号或密码不能为空")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.account_or_password_empty"))
|
||||
}
|
||||
|
||||
member, err := models.NewMember().Login(account, password)
|
||||
|
@ -137,7 +138,7 @@ func (c *AccountController) Login() {
|
|||
c.JsonResult(0, "ok", c.referer())
|
||||
} else {
|
||||
logs.Error("用户登录 ->", err)
|
||||
c.JsonResult(500, "账号或密码错误", nil)
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.wrong_account_password"), nil)
|
||||
}
|
||||
} else {
|
||||
c.Data["url"] = c.referer()
|
||||
|
@ -150,7 +151,7 @@ func (c *AccountController) DingTalkLogin() {
|
|||
|
||||
code := c.GetString("dingtalk_code")
|
||||
if code == "" {
|
||||
c.JsonResult(500, "获取身份信息失败", nil)
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_obtain_user_info"), nil)
|
||||
}
|
||||
|
||||
appKey, _ := web.AppConfig.String("dingtalk_app_key")
|
||||
|
@ -158,7 +159,7 @@ func (c *AccountController) DingTalkLogin() {
|
|||
tmpReader, _ := web.AppConfig.String("dingtalk_tmp_reader")
|
||||
|
||||
if appKey == "" || appSecret == "" || tmpReader == "" {
|
||||
c.JsonResult(500, "未开启钉钉自动登录功能", nil)
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.dingtalk_auto_login_not_enable"), nil)
|
||||
c.StopRun()
|
||||
}
|
||||
|
||||
|
@ -166,21 +167,21 @@ func (c *AccountController) DingTalkLogin() {
|
|||
err := dingtalkAgent.GetAccesstoken()
|
||||
if err != nil {
|
||||
logs.Warn("获取钉钉临时Token失败 ->", err)
|
||||
c.JsonResult(500, "自动登录失败", nil)
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_auto_login"), nil)
|
||||
c.StopRun()
|
||||
}
|
||||
|
||||
userid, err := dingtalkAgent.GetUserIDByCode(code)
|
||||
if err != nil {
|
||||
logs.Warn("获取钉钉用户ID失败 ->", err)
|
||||
c.JsonResult(500, "自动登录失败", nil)
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_auto_login"), nil)
|
||||
c.StopRun()
|
||||
}
|
||||
|
||||
username, avatar, err := dingtalkAgent.GetUserNameAndAvatarByUserID(userid)
|
||||
if err != nil {
|
||||
logs.Warn("获取钉钉用户信息失败 ->", err)
|
||||
c.JsonResult(500, "自动登录失败", nil)
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_auto_login"), nil)
|
||||
c.StopRun()
|
||||
}
|
||||
|
||||
|
@ -309,29 +310,29 @@ func (c *AccountController) Register() {
|
|||
captcha := c.GetString("code")
|
||||
|
||||
if ok, err := regexp.MatchString(conf.RegexpAccount, account); account == "" || !ok || err != nil {
|
||||
c.JsonResult(6001, "账号只能由英文字母数字组成,且在3-50个字符")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.username_invalid_format"))
|
||||
}
|
||||
if l := strings.Count(password1, ""); password1 == "" || l > 50 || l < 6 {
|
||||
c.JsonResult(6002, "密码必须在6-50个字符之间")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.password_length_invalid"))
|
||||
}
|
||||
if password1 != password2 {
|
||||
c.JsonResult(6003, "确认密码不正确")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.incorrect_confirm_password"))
|
||||
}
|
||||
if ok, err := regexp.MatchString(conf.RegexpEmail, email); !ok || err != nil || email == "" {
|
||||
c.JsonResult(6004, "邮箱格式不正确")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.email_invalid_format"))
|
||||
}
|
||||
// 如果开启了验证码
|
||||
if v, ok := c.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") {
|
||||
v, ok := c.GetSession(conf.CaptchaSessionName).(string)
|
||||
if !ok || !strings.EqualFold(v, captcha) {
|
||||
c.JsonResult(6001, "验证码不正确")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong"))
|
||||
}
|
||||
}
|
||||
|
||||
member := models.NewMember()
|
||||
|
||||
if _, err := member.FindByAccount(account); err == nil && member.MemberId > 0 {
|
||||
c.JsonResult(6005, "账号已存在")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.account_existed"))
|
||||
}
|
||||
|
||||
member.Account = account
|
||||
|
@ -342,7 +343,7 @@ func (c *AccountController) Register() {
|
|||
member.Email = email
|
||||
member.Status = 0
|
||||
if err := member.Add(); err != nil {
|
||||
c.JsonResult(6006, "注册失败,请联系系统管理员处理")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed_register"))
|
||||
}
|
||||
|
||||
c.JsonResult(0, "ok", member)
|
||||
|
@ -360,39 +361,39 @@ func (c *AccountController) FindPassword() {
|
|||
captcha := c.GetString("code")
|
||||
|
||||
if email == "" {
|
||||
c.JsonResult(6005, "邮箱地址不能为空")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.email_empty"))
|
||||
}
|
||||
if !mailConf.EnableMail {
|
||||
c.JsonResult(6004, "未启用邮件服务")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.mail_service_not_enable"))
|
||||
}
|
||||
|
||||
// 如果开启了验证码
|
||||
if v, ok := c.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") {
|
||||
v, ok := c.GetSession(conf.CaptchaSessionName).(string)
|
||||
if !ok || !strings.EqualFold(v, captcha) {
|
||||
c.JsonResult(6001, "验证码不正确")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong"))
|
||||
}
|
||||
}
|
||||
|
||||
member, err := models.NewMember().FindByFieldFirst("email", email)
|
||||
if err != nil {
|
||||
c.JsonResult(6006, "邮箱不存在")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.email_not_exist"))
|
||||
}
|
||||
if member.Status != 0 {
|
||||
c.JsonResult(6007, "账号已被禁用")
|
||||
if member == nil || member.Status != 0 {
|
||||
c.JsonResult(6007, i18n.Tr(c.Lang, "message.account_disable"))
|
||||
}
|
||||
if member.AuthMethod == conf.AuthMethodLDAP {
|
||||
c.JsonResult(6011, "当前用户不支持找回密码")
|
||||
if member == nil || member.AuthMethod == conf.AuthMethodLDAP {
|
||||
c.JsonResult(6011, i18n.Tr(c.Lang, "message.account_not_support_retrieval"))
|
||||
}
|
||||
|
||||
count, err := models.NewMemberToken().FindSendCount(email, time.Now().Add(-1*time.Hour), time.Now())
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6008, "发送邮件失败")
|
||||
c.JsonResult(6008, i18n.Tr(c.Lang, "message.failed_send_mail"))
|
||||
}
|
||||
if count > mailConf.MailNumber {
|
||||
c.JsonResult(6008, "发送次数太多,请稍候再试")
|
||||
c.JsonResult(6008, i18n.Tr(c.Lang, "message.sent_too_many_times"))
|
||||
}
|
||||
|
||||
memberToken := models.NewMemberToken()
|
||||
|
@ -402,7 +403,7 @@ func (c *AccountController) FindPassword() {
|
|||
memberToken.MemberId = member.MemberId
|
||||
memberToken.IsValid = false
|
||||
if _, err := memberToken.InsertOrUpdate(); err != nil {
|
||||
c.JsonResult(6009, "邮件发送失败")
|
||||
c.JsonResult(6009, i18n.Tr(c.Lang, "message.failed_send_mail"))
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
|
@ -414,7 +415,7 @@ func (c *AccountController) FindPassword() {
|
|||
body, err := c.ExecuteViewPathTemplate("account/mail_template.tpl", data)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6003, "邮件发送失败")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed_send_mail"))
|
||||
}
|
||||
|
||||
go func(mailConf *conf.SmtpConf, email string, body string) {
|
||||
|
@ -473,17 +474,16 @@ func (c *AccountController) FindPassword() {
|
|||
|
||||
if token != "" && email != "" {
|
||||
memberToken, err := models.NewMemberToken().FindByFieldFirst("token", token)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.Data["ErrorMessage"] = "邮件已失效"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.mail_expired")
|
||||
c.TplName = "errors/error.tpl"
|
||||
return
|
||||
}
|
||||
subTime := time.Until(memberToken.SendTime)
|
||||
|
||||
if !strings.EqualFold(memberToken.Email, email) || subTime.Minutes() > float64(mailConf.MailExpired) || !memberToken.ValidTime.IsZero() {
|
||||
c.Data["ErrorMessage"] = "验证码已过期,请重新操作。"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.captcha_expired")
|
||||
c.TplName = "errors/error.tpl"
|
||||
return
|
||||
}
|
||||
|
@ -504,48 +504,46 @@ func (c *AccountController) ValidEmail() {
|
|||
email := c.GetString("mail")
|
||||
|
||||
if password1 == "" {
|
||||
c.JsonResult(6001, "密码不能为空")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.password_empty"))
|
||||
}
|
||||
if l := strings.Count(password1, ""); l < 6 || l > 50 {
|
||||
c.JsonResult(6001, "密码不能为空且必须在6-50个字符之间")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.password_length_invalid"))
|
||||
}
|
||||
if password2 == "" {
|
||||
c.JsonResult(6002, "确认密码不能为空")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.confirm_password_empty"))
|
||||
}
|
||||
if password1 != password2 {
|
||||
c.JsonResult(6003, "确认密码输入不正确")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.incorrect_confirm_password"))
|
||||
}
|
||||
if captcha == "" {
|
||||
c.JsonResult(6004, "验证码不能为空")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.captcha_empty"))
|
||||
}
|
||||
v, ok := c.GetSession(conf.CaptchaSessionName).(string)
|
||||
if !ok || !strings.EqualFold(v, captcha) {
|
||||
c.JsonResult(6001, "验证码不正确")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong"))
|
||||
}
|
||||
|
||||
mailConf := conf.GetMailConfig()
|
||||
memberToken, err := models.NewMemberToken().FindByFieldFirst("token", token)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6007, "邮件已失效")
|
||||
c.JsonResult(6007, i18n.Tr(c.Lang, "message.mail_expired"))
|
||||
}
|
||||
subTime := time.Until(memberToken.SendTime)
|
||||
|
||||
if !strings.EqualFold(memberToken.Email, email) || subTime.Minutes() > float64(mailConf.MailExpired) || !memberToken.ValidTime.IsZero() {
|
||||
|
||||
c.JsonResult(6008, "验证码已过期,请重新操作。")
|
||||
c.JsonResult(6008, i18n.Tr(c.Lang, "message.captcha_expired"))
|
||||
}
|
||||
member, err := models.NewMember().Find(memberToken.MemberId)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6005, "用户不存在")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.user_not_existed"))
|
||||
}
|
||||
hash, err := utils.PasswordHash(password1)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6006, "保存密码失败")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed_save_password"))
|
||||
}
|
||||
|
||||
member.Password = hash
|
||||
|
@ -557,7 +555,7 @@ func (c *AccountController) ValidEmail() {
|
|||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6006, "保存密码失败")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed_save_password"))
|
||||
}
|
||||
c.JsonResult(0, "ok", conf.URLFor("AccountController.Login"))
|
||||
}
|
||||
|
@ -565,11 +563,8 @@ func (c *AccountController) ValidEmail() {
|
|||
// Logout 退出登录
|
||||
func (c *AccountController) Logout() {
|
||||
c.SetMember(models.Member{})
|
||||
|
||||
c.SetSecureCookie(conf.GetAppKey(), "login", "", -3600)
|
||||
|
||||
u := c.Ctx.Request.Header.Get("Referer")
|
||||
|
||||
c.Redirect(conf.URLFor("AccountController.Login", "url", u), 302)
|
||||
}
|
||||
|
||||
|
@ -579,11 +574,6 @@ func (c *AccountController) Captcha() {
|
|||
|
||||
captchaImage := gocaptcha.NewCaptchaImage(140, 40, gocaptcha.RandLightColor())
|
||||
|
||||
//if err != nil {
|
||||
// logs.Error(err)
|
||||
// c.Abort("500")
|
||||
//}
|
||||
|
||||
captchaImage.DrawNoise(gocaptcha.CaptchaComplexLower)
|
||||
|
||||
// captchaImage.DrawTextNoise(gocaptcha.CaptchaComplexHigh)
|
||||
|
|
|
@ -2,7 +2,6 @@ package controllers
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strings"
|
||||
|
@ -14,6 +13,7 @@ import (
|
|||
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
"github.com/mindoc-org/mindoc/utils"
|
||||
|
@ -25,6 +25,7 @@ type BaseController struct {
|
|||
Option map[string]string
|
||||
EnableAnonymous bool
|
||||
EnableDocumentHistory bool
|
||||
Lang string
|
||||
}
|
||||
|
||||
type CookieRemember struct {
|
||||
|
@ -46,7 +47,6 @@ func (c *BaseController) Prepare() {
|
|||
c.EnableDocumentHistory = false
|
||||
|
||||
if member, ok := c.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0 {
|
||||
|
||||
c.Member = &member
|
||||
c.Data["Member"] = c.Member
|
||||
} else {
|
||||
|
@ -80,6 +80,7 @@ func (c *BaseController) Prepare() {
|
|||
c.Data["Scripts"] = template.HTML(string(b))
|
||||
}
|
||||
|
||||
c.SetLang()
|
||||
}
|
||||
|
||||
//判断用户是否登录.
|
||||
|
@ -112,14 +113,16 @@ func (c *BaseController) JsonResult(errCode int, errMsg string, data ...interfac
|
|||
}
|
||||
|
||||
returnJSON, err := json.Marshal(jsonData)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
|
||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache, no-store")
|
||||
io.WriteString(c.Ctx.ResponseWriter, string(returnJSON))
|
||||
_, err = io.WriteString(c.Ctx.ResponseWriter, string(returnJSON))
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
|
||||
c.StopRun()
|
||||
}
|
||||
|
@ -136,14 +139,16 @@ func (c *BaseController) CheckJsonError(code int, err error) {
|
|||
jsonData["message"] = err.Error()
|
||||
|
||||
returnJSON, err := json.Marshal(jsonData)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
|
||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache, no-store")
|
||||
io.WriteString(c.Ctx.ResponseWriter, string(returnJSON))
|
||||
_, err = io.WriteString(c.Ctx.ResponseWriter, string(returnJSON))
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
|
||||
c.StopRun()
|
||||
}
|
||||
|
@ -201,3 +206,21 @@ func (c *BaseController) CheckErrorResult(code int, err error) {
|
|||
c.ShowErrorPage(code, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *BaseController) SetLang() {
|
||||
hasCookie := false
|
||||
lang := c.GetString("lang")
|
||||
if len(lang) == 0 {
|
||||
lang = c.Ctx.GetCookie("lang")
|
||||
hasCookie = true
|
||||
}
|
||||
if len(lang) == 0 ||
|
||||
!i18n.IsExist(lang) {
|
||||
lang, _ = web.AppConfig.String("default_lang")
|
||||
}
|
||||
if !hasCookie {
|
||||
c.Ctx.SetCookie("lang", lang, 1<<31-1, "/")
|
||||
}
|
||||
c.Data["Lang"] = lang
|
||||
c.Lang = lang
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
"github.com/mindoc-org/mindoc/utils"
|
||||
|
@ -40,20 +41,20 @@ func (c *BlogController) Index() {
|
|||
blogId, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
|
||||
if blogId <= 0 {
|
||||
c.ShowErrorPage(404, "页面不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.page_not_existed"))
|
||||
}
|
||||
blogReadSession := fmt.Sprintf("blog:read:%d", blogId)
|
||||
|
||||
blog, err := models.NewBlog().FindFromCache(blogId)
|
||||
|
||||
if err != nil {
|
||||
c.ShowErrorPage(404, "文章不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.blog_not_existed"))
|
||||
}
|
||||
|
||||
if c.Ctx.Input.IsPost() {
|
||||
password := c.GetString("password")
|
||||
if blog.BlogStatus == "password" && password != blog.Password {
|
||||
c.JsonResult(6001, "文章密码不正确")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.blog_pwd_incorrect"))
|
||||
} else if blog.BlogStatus == "password" && password == blog.Password {
|
||||
//如果密码输入正确,则存入session中
|
||||
_ = c.CruSession.Set(context.TODO(), blogReadSession, blogId)
|
||||
|
@ -160,33 +161,33 @@ func (c *BlogController) ManageSetting() {
|
|||
documentId := 0
|
||||
|
||||
if blogTitle == "" {
|
||||
c.JsonResult(6001, "文章标题不能为空")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.blog_title_empty"))
|
||||
}
|
||||
if strings.Count(blogExcerpt, "") > 500 {
|
||||
c.JsonResult(6008, "文章摘要必须小于500字符")
|
||||
c.JsonResult(6008, i18n.Tr(c.Lang, "message.blog_digest_tips"))
|
||||
}
|
||||
if blogStatus != "public" && blogStatus != "password" && blogStatus != "draft" {
|
||||
blogStatus = "public"
|
||||
}
|
||||
if blogStatus == "password" && blogPassword == "" {
|
||||
c.JsonResult(6010, "加密文章请设置密码")
|
||||
c.JsonResult(6010, i18n.Tr(c.Lang, "message.set_pwd_pls"))
|
||||
}
|
||||
if blogType != 0 && blogType != 1 {
|
||||
c.JsonResult(6005, "未知的文章类型")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.unknown_blog_type"))
|
||||
}
|
||||
if strings.Count(blogTitle, "") > 200 {
|
||||
c.JsonResult(6002, "文章标题不能大于200个字符")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.blog_title_tips"))
|
||||
}
|
||||
//如果是关联文章,需要同步关联的文档
|
||||
if blogType == 1 {
|
||||
book, err := models.NewBook().FindByIdentify(bookIdentify)
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(6011, "关联文档的项目不存在")
|
||||
c.JsonResult(6011, i18n.Tr(c.Lang, "message.ref_doc_not_exist_or_no_permit"))
|
||||
}
|
||||
doc, err := models.NewDocument().FindByIdentityFirst(documentIdentify, book.BookId)
|
||||
if err != nil {
|
||||
c.JsonResult(6003, "查询关联项目文档时出错")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.query_failed"))
|
||||
}
|
||||
documentId = doc.DocumentId
|
||||
|
||||
|
@ -195,7 +196,7 @@ func (c *BlogController) ManageSetting() {
|
|||
bookResult, err := models.NewBookResult().FindByIdentify(book.Identify, c.Member.MemberId)
|
||||
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
c.JsonResult(6002, "关联文档不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.ref_doc_not_exist_or_no_permit"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -211,13 +212,13 @@ func (c *BlogController) ManageSetting() {
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(6003, "文章不存在")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.blog_not_exist"))
|
||||
}
|
||||
//如果设置了文章标识
|
||||
if blogIdentify != "" {
|
||||
//如果查询到的文章标识存在并且不是当前文章的id
|
||||
if b, err := models.NewBlog().FindByIdentify(blogIdentify); err == nil && b.BlogId != blogId {
|
||||
c.JsonResult(6004, "文章标识已存在")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.blog_id_existed"))
|
||||
}
|
||||
}
|
||||
blog.Modified = time.Now()
|
||||
|
@ -226,7 +227,7 @@ func (c *BlogController) ManageSetting() {
|
|||
//如果设置了文章标识
|
||||
if blogIdentify != "" {
|
||||
if models.NewBlog().IsExist(blogIdentify) {
|
||||
c.JsonResult(6004, "文章标识已存在")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.blog_id_existed"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +254,7 @@ func (c *BlogController) ManageSetting() {
|
|||
|
||||
if err := blog.Save(); err != nil {
|
||||
logs.Error("保存文章失败 -> ", err)
|
||||
c.JsonResult(6011, "保存文章失败")
|
||||
c.JsonResult(6011, i18n.Tr(c.Lang, "message.failed"))
|
||||
} else {
|
||||
c.JsonResult(0, "ok", blog)
|
||||
}
|
||||
|
@ -287,7 +288,7 @@ func (c *BlogController) ManageEdit() {
|
|||
blogId, _ := c.GetInt("blogId", 0)
|
||||
|
||||
if blogId <= 0 {
|
||||
c.JsonResult(6001, "文章参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
blogContent := c.GetString("content", "")
|
||||
blogHtml := c.GetString("htmlContent", "")
|
||||
|
@ -304,21 +305,21 @@ func (c *BlogController) ManageEdit() {
|
|||
}
|
||||
if err != nil {
|
||||
logs.Error("查询文章失败 ->", err)
|
||||
c.JsonResult(6002, "查询文章失败")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.query_failed"))
|
||||
}
|
||||
if version > 0 && blog.Version != version && cover != "yes" {
|
||||
c.JsonResult(6005, "文章已被修改")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.blog_has_modified"))
|
||||
}
|
||||
//如果是关联文章,需要同步关联的文档
|
||||
if blog.BlogType == 1 {
|
||||
doc, err := models.NewDocument().Find(blog.DocumentId)
|
||||
if err != nil {
|
||||
logs.Error("查询关联项目文档时出错 ->", err)
|
||||
c.JsonResult(6003, "查询关联项目文档时出错")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.query_failed"))
|
||||
}
|
||||
book, err := models.NewBook().Find(doc.BookId)
|
||||
if err != nil {
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
// 如果不是超级管理员,则校验权限
|
||||
|
@ -327,7 +328,7 @@ func (c *BlogController) ManageEdit() {
|
|||
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("FindByIdentify => ", err)
|
||||
c.JsonResult(6002, "关联文档不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.ref_doc_not_exist_or_no_permit"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,7 +339,7 @@ func (c *BlogController) ManageEdit() {
|
|||
doc.ModifyAt = c.Member.MemberId
|
||||
if err := doc.InsertOrUpdate("markdown", "release", "content", "modify_time", "modify_at"); err != nil {
|
||||
logs.Error("保存关联文档时出错 ->", err)
|
||||
c.JsonResult(6004, "保存关联文档时出错")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,7 +350,7 @@ func (c *BlogController) ManageEdit() {
|
|||
|
||||
if err := blog.Save("blog_content", "blog_release", "modify_at", "modify_time", "version"); err != nil {
|
||||
logs.Error("保存文章失败 -> ", err)
|
||||
c.JsonResult(6011, "保存文章失败")
|
||||
c.JsonResult(6011, i18n.Tr(c.Lang, "message.failed"))
|
||||
} else {
|
||||
c.JsonResult(0, "ok", blog)
|
||||
}
|
||||
|
@ -358,7 +359,7 @@ func (c *BlogController) ManageEdit() {
|
|||
blogId, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
|
||||
if blogId <= 0 {
|
||||
c.ShowErrorPage(500, "参数错误")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
var blog *models.Blog
|
||||
var err error
|
||||
|
@ -369,7 +370,7 @@ func (c *BlogController) ManageEdit() {
|
|||
blog, err = models.NewBlog().FindByIdAndMemberId(blogId, c.Member.MemberId)
|
||||
}
|
||||
if err != nil {
|
||||
c.ShowErrorPage(404, "文章不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.blog_not_exist"))
|
||||
}
|
||||
blog.LinkAttach()
|
||||
|
||||
|
@ -397,7 +398,7 @@ func (c *BlogController) ManageDelete() {
|
|||
blogId, _ := c.GetInt("blog_id", 0)
|
||||
|
||||
if blogId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
var blog *models.Blog
|
||||
var err error
|
||||
|
@ -408,13 +409,13 @@ func (c *BlogController) ManageDelete() {
|
|||
blog, err = models.NewBlog().FindByIdAndMemberId(blogId, c.Member.MemberId)
|
||||
}
|
||||
if err != nil {
|
||||
c.JsonResult(6002, "文章不存在或已删除")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.blog_not_exist"))
|
||||
}
|
||||
|
||||
if err := blog.Delete(blogId); err != nil {
|
||||
c.JsonResult(6003, "删除失败")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed"))
|
||||
} else {
|
||||
c.JsonResult(0, "删除成功")
|
||||
c.JsonResult(0, i18n.Tr(c.Lang, "message.success"))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -425,16 +426,16 @@ func (c *BlogController) Upload() {
|
|||
blogId, _ := c.GetInt("blogId")
|
||||
|
||||
if blogId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
blog, err := models.NewBlog().Find(blogId)
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(6010, "文章不存在")
|
||||
c.JsonResult(6010, i18n.Tr(c.Lang, "message.blog_not_exist"))
|
||||
}
|
||||
if !c.Member.IsAdministrator() && blog.MemberId != c.Member.MemberId {
|
||||
c.JsonResult(6011, "没有文章的访问权限")
|
||||
c.JsonResult(6011, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
name := "editormd-file-file"
|
||||
|
@ -444,7 +445,7 @@ func (c *BlogController) Upload() {
|
|||
name = "editormd-image-file"
|
||||
file, moreFile, err = c.GetFile(name)
|
||||
if err == http.ErrMissingFile {
|
||||
c.JsonResult(6003, "没有发现需要上传的图片")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_empty"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,18 +460,18 @@ func (c *BlogController) Upload() {
|
|||
}
|
||||
|
||||
if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() {
|
||||
c.JsonResult(6009, "查过文件允许的上传最大值")
|
||||
c.JsonResult(6009, i18n.Tr(c.Lang, "message.upload_file_size_limit"))
|
||||
}
|
||||
|
||||
ext := filepath.Ext(moreFile.Filename)
|
||||
|
||||
if ext == "" {
|
||||
c.JsonResult(6003, "无法解析文件的格式")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_type_error"))
|
||||
}
|
||||
//如果文件类型设置为 * 标识不限制文件类型
|
||||
if web.AppConfig.DefaultString("upload_file_ext", "") != "*" {
|
||||
if !conf.IsAllowUploadFileExt(ext) {
|
||||
c.JsonResult(6004, "不允许的文件类型")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.upload_file_type_error"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,7 +480,7 @@ func (c *BlogController) Upload() {
|
|||
_, err := models.NewBlog().Find(blogId)
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(6006, "文档不存在或权限不足")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.doc_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -488,7 +489,7 @@ func (c *BlogController) Upload() {
|
|||
if err != nil {
|
||||
logs.Error("查询文章时出错 -> ", err)
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(6006, "权限不足")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
c.JsonResult(6001, err.Error())
|
||||
|
@ -507,7 +508,7 @@ func (c *BlogController) Upload() {
|
|||
|
||||
if err != nil {
|
||||
logs.Error("SaveToFile => ", err)
|
||||
c.JsonResult(6005, "保存文件失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
var httpPath string
|
||||
|
@ -540,14 +541,14 @@ func (c *BlogController) Upload() {
|
|||
if err := attachment.Insert(); err != nil {
|
||||
os.Remove(filePath)
|
||||
logs.Error("保存文件附件失败 -> ", err)
|
||||
c.JsonResult(6006, "文件保存失败")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
if attachment.HttpPath == "" {
|
||||
attachment.HttpPath = conf.URLForNotHost("BlogController.Download", ":id", blogId, ":attach_id", attachment.AttachmentId)
|
||||
|
||||
if err := attachment.Update(); err != nil {
|
||||
logs.Error("保存文件失败 -> ", attachment.FilePath, err)
|
||||
c.JsonResult(6005, "保存文件失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
}
|
||||
result["attach"] = attachment
|
||||
|
@ -570,21 +571,21 @@ func (c *BlogController) RemoveAttachment() {
|
|||
blogId, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
|
||||
if attachId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
blog, err := models.NewBlog().Find(blogId)
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(500, "文档不存在")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
} else {
|
||||
c.ShowErrorPage(500, "查询文章时异常")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.query_failed"))
|
||||
}
|
||||
}
|
||||
attach, err := models.NewAttachment().Find(attachId)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6002, "附件不存在")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
}
|
||||
|
||||
if !c.Member.IsAdministrator() {
|
||||
|
@ -592,19 +593,19 @@ func (c *BlogController) RemoveAttachment() {
|
|||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6003, "文档不存在")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
}
|
||||
}
|
||||
|
||||
if blog.BlogType == 1 && attach.BookId != blog.BookId && attach.DocumentId != blog.DocumentId {
|
||||
c.ShowErrorPage(404, "附件不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
} else if attach.BookId != 0 || attach.DocumentId != blogId {
|
||||
c.ShowErrorPage(404, "附件不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
}
|
||||
|
||||
if err := attach.Delete(); err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6005, "删除失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
os.Remove(filepath.Join(conf.WorkingDirectory, attach.FilePath))
|
||||
|
@ -623,15 +624,15 @@ func (c *BlogController) Download() {
|
|||
blog, err := models.NewBlog().Find(blogId)
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(500, "文档不存在")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
} else {
|
||||
c.ShowErrorPage(500, "查询文章时异常")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.query_failed"))
|
||||
}
|
||||
}
|
||||
blogReadSession := fmt.Sprintf("blog:read:%d", blogId)
|
||||
//如果没有启动匿名访问,或者设置了访问密码
|
||||
if (c.Member == nil && !c.EnableAnonymous) || (blog.BlogStatus == "password" && password != blog.Password && c.CruSession.Get(context.TODO(), blogReadSession) == nil) {
|
||||
c.ShowErrorPage(403, "没有下载权限")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
// 查找附件
|
||||
|
@ -639,18 +640,18 @@ func (c *BlogController) Download() {
|
|||
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(404, "附件不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
} else {
|
||||
logs.Error("查询附件时出现异常 -> ", err)
|
||||
c.ShowErrorPage(500, "查询附件时出现异常")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.query_failed"))
|
||||
}
|
||||
}
|
||||
|
||||
//如果是链接的文章,需要校验文档ID是否一致,如果不是,需要保证附件的项目ID为0且文档的ID等于博文ID
|
||||
if blog.BlogType == 1 && attachment.DocumentId != blog.DocumentId {
|
||||
c.ShowErrorPage(404, "附件不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
} else if blog.BlogType != 1 && (attachment.BookId != 0 || attachment.DocumentId != blogId) {
|
||||
c.ShowErrorPage(404, "附件不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
}
|
||||
|
||||
c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName)
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/utils/sqltil"
|
||||
|
||||
"net/http"
|
||||
|
@ -37,7 +38,7 @@ func (c *BookController) Index() {
|
|||
|
||||
pageIndex, _ := c.GetInt("page", 1)
|
||||
|
||||
books, totalCount, err := models.NewBook().FindToPager(pageIndex, conf.PageSize, c.Member.MemberId)
|
||||
books, totalCount, err := models.NewBook().FindToPager(pageIndex, conf.PageSize, c.Member.MemberId, c.Lang)
|
||||
|
||||
if err != nil {
|
||||
logs.Error("BookController.Index => ", err)
|
||||
|
@ -79,7 +80,7 @@ func (c *BookController) Dashboard() {
|
|||
c.Abort("404")
|
||||
}
|
||||
|
||||
book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId)
|
||||
book, err := models.NewBookResult().SetLang(c.Lang).FindByIdentify(key, c.Member.MemberId)
|
||||
if err != nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
c.Abort("403")
|
||||
|
@ -154,16 +155,16 @@ func (c *BookController) SaveBook() {
|
|||
itemId, _ := c.GetInt("itemId")
|
||||
|
||||
if strings.Count(description, "") > 500 {
|
||||
c.JsonResult(6004, "项目描述不能大于500字")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_desc_tips"))
|
||||
}
|
||||
if commentStatus != "open" && commentStatus != "closed" && commentStatus != "group_only" && commentStatus != "registered_only" {
|
||||
commentStatus = "closed"
|
||||
}
|
||||
|
||||
if !models.NewItemsets().Exist(itemId) {
|
||||
c.JsonResult(6006, "项目空间不存在")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_space_not_exist"))
|
||||
}
|
||||
if editor != "markdown" && editor != "html" {
|
||||
if editor != "markdown" && editor != "html" && editor != "new_html" {
|
||||
editor = "markdown"
|
||||
}
|
||||
|
||||
|
@ -204,7 +205,7 @@ func (c *BookController) SaveBook() {
|
|||
book.AutoSave = 0
|
||||
}
|
||||
if err := book.Update(); err != nil {
|
||||
c.JsonResult(6006, "保存失败")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
bookResult.BookName = bookName
|
||||
bookResult.Description = description
|
||||
|
@ -221,7 +222,7 @@ func (c *BookController) PrivatelyOwned() {
|
|||
status := c.GetString("status")
|
||||
|
||||
if status != "open" && status != "close" {
|
||||
c.JsonResult(6003, "参数错误")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
state := 0
|
||||
if status == "open" {
|
||||
|
@ -238,13 +239,13 @@ func (c *BookController) PrivatelyOwned() {
|
|||
}
|
||||
//只有创始人才能变更私有状态
|
||||
if bookResult.RoleId != conf.BookFounder {
|
||||
c.JsonResult(6002, "权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
book, err := models.NewBook().Find(bookResult.BookId)
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(6005, "项目不存在")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
return
|
||||
}
|
||||
book.PrivatelyOwned = state
|
||||
|
@ -253,7 +254,7 @@ func (c *BookController) PrivatelyOwned() {
|
|||
|
||||
if err != nil {
|
||||
logs.Error("PrivatelyOwned => ", err)
|
||||
c.JsonResult(6004, "保存失败")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
logs.Info("用户 【", c.Member.Account, "]修改了项目权限 ->", state)
|
||||
c.JsonResult(0, "ok")
|
||||
|
@ -265,19 +266,19 @@ func (c *BookController) Transfer() {
|
|||
account := c.GetString("account")
|
||||
|
||||
if account == "" {
|
||||
c.JsonResult(6004, "接受者账号不能为空")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.receive_account_empty"))
|
||||
}
|
||||
member, err := models.NewMember().FindByAccount(account)
|
||||
|
||||
if err != nil {
|
||||
logs.Error("FindByAccount => ", err)
|
||||
c.JsonResult(6005, "接受用户不存在")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.receive_account_not_exist"))
|
||||
}
|
||||
if member.Status != 0 {
|
||||
c.JsonResult(6006, "接受用户已被禁用")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.receive_account_disabled"))
|
||||
}
|
||||
if member.MemberId == c.Member.MemberId {
|
||||
c.JsonResult(6007, "不能转让给自己")
|
||||
c.JsonResult(6007, i18n.Tr(c.Lang, "message.cannot_handover_myself"))
|
||||
}
|
||||
bookResult, err := c.IsPermission()
|
||||
|
||||
|
@ -339,7 +340,8 @@ func (c *BookController) UploadCover() {
|
|||
fileName := "cover_" + strconv.FormatInt(time.Now().UnixNano(), 16)
|
||||
|
||||
//附件路径按照项目组织
|
||||
filePath := filepath.Join("uploads", book.Identify, "images", fileName+ext)
|
||||
// filePath := filepath.Join("uploads", book.Identify, "images", fileName+ext)
|
||||
filePath := filepath.Join(conf.WorkingDirectory, "uploads", book.Identify, "images", fileName+ext)
|
||||
|
||||
path := filepath.Dir(filePath)
|
||||
|
||||
|
@ -404,7 +406,7 @@ func (c *BookController) Users() {
|
|||
pageIndex, _ := c.GetInt("page", 1)
|
||||
|
||||
if key == "" {
|
||||
c.ShowErrorPage(404, "项目不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
|
||||
book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId)
|
||||
|
@ -421,7 +423,7 @@ func (c *BookController) Users() {
|
|||
}
|
||||
c.Data["Model"] = *book
|
||||
|
||||
members, totalCount, err := models.NewMemberRelationshipResult().FindForUsersByBookId(book.BookId, pageIndex, conf.PageSize)
|
||||
members, totalCount, err := models.NewMemberRelationshipResult().FindForUsersByBookId(c.Lang, book.BookId, pageIndex, conf.PageSize)
|
||||
|
||||
if totalCount > 0 {
|
||||
pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl())
|
||||
|
@ -450,25 +452,25 @@ func (c *BookController) Create() {
|
|||
itemId, _ := c.GetInt("itemId")
|
||||
|
||||
if bookName == "" {
|
||||
c.JsonResult(6001, "项目名称不能为空")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.project_name_empty"))
|
||||
}
|
||||
if identify == "" {
|
||||
c.JsonResult(6002, "项目标识不能为空")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.project_id_empty"))
|
||||
}
|
||||
if ok, err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`, identify); !ok || err != nil {
|
||||
c.JsonResult(6003, "项目标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.project_id_tips"))
|
||||
}
|
||||
if strings.Count(identify, "") > 50 {
|
||||
c.JsonResult(6004, "文档标识不能超过50字")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_id_length"))
|
||||
}
|
||||
if strings.Count(description, "") > 500 {
|
||||
c.JsonResult(6004, "项目描述不能大于500字")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_desc_tips"))
|
||||
}
|
||||
if privatelyOwned != 0 && privatelyOwned != 1 {
|
||||
privatelyOwned = 1
|
||||
}
|
||||
if !models.NewItemsets().Exist(itemId) {
|
||||
c.JsonResult(6005, "项目空间不存在")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.project_space_not_exist"))
|
||||
}
|
||||
if commentStatus != "open" && commentStatus != "closed" && commentStatus != "group_only" && commentStatus != "registered_only" {
|
||||
commentStatus = "closed"
|
||||
|
@ -505,7 +507,7 @@ func (c *BookController) Create() {
|
|||
}
|
||||
|
||||
if books, _ := book.FindByField("identify", identify, "book_id"); len(books) > 0 {
|
||||
c.JsonResult(6006, "项目标识已存在")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_id_existed"))
|
||||
}
|
||||
|
||||
book.BookName = bookName
|
||||
|
@ -526,9 +528,9 @@ func (c *BookController) Create() {
|
|||
book.Editor = "markdown"
|
||||
book.Theme = "default"
|
||||
|
||||
if err := book.Insert(); err != nil {
|
||||
if err := book.Insert(c.Lang); err != nil {
|
||||
logs.Error("Insert => ", err)
|
||||
c.JsonResult(6005, "保存项目失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
bookResult, err := models.NewBookResult().FindByIdentify(book.Identify, c.Member.MemberId)
|
||||
|
||||
|
@ -552,7 +554,7 @@ func (c *BookController) Copy() {
|
|||
|
||||
identify := strings.TrimSpace(c.GetString("identify", ""))
|
||||
if identify == "" {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
book := models.NewBook()
|
||||
err := book.Copy(identify)
|
||||
|
@ -568,7 +570,7 @@ func (c *BookController) Copy() {
|
|||
}
|
||||
}
|
||||
|
||||
//导入zip压缩包
|
||||
// 导入zip压缩包或docx
|
||||
func (c *BookController) Import() {
|
||||
|
||||
file, moreFile, err := c.GetFile("import-file")
|
||||
|
@ -585,32 +587,32 @@ func (c *BookController) Import() {
|
|||
itemId, _ := c.GetInt("itemId")
|
||||
|
||||
if bookName == "" {
|
||||
c.JsonResult(6001, "项目名称不能为空")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.project_name_empty"))
|
||||
}
|
||||
if len([]rune(bookName)) > 500 {
|
||||
c.JsonResult(6002, "项目名称不能大于500字")
|
||||
}
|
||||
if identify == "" {
|
||||
c.JsonResult(6002, "项目标识不能为空")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.project_id_empty"))
|
||||
}
|
||||
if ok, err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`, identify); !ok || err != nil {
|
||||
c.JsonResult(6003, "项目标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.project_id_tips"))
|
||||
}
|
||||
if !models.NewItemsets().Exist(itemId) {
|
||||
c.JsonResult(6007, "项目空间不存在")
|
||||
c.JsonResult(6007, i18n.Tr(c.Lang, "message.project_space_not_exist"))
|
||||
}
|
||||
if strings.Count(identify, "") > 50 {
|
||||
c.JsonResult(6004, "文档标识不能超过50字")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_id_length"))
|
||||
}
|
||||
|
||||
ext := filepath.Ext(moreFile.Filename)
|
||||
|
||||
if !strings.EqualFold(ext, ".zip") {
|
||||
if !strings.EqualFold(ext, ".zip") && !strings.EqualFold(ext, ".docx") {
|
||||
c.JsonResult(6004, "不支持的文件类型")
|
||||
}
|
||||
|
||||
if books, _ := models.NewBook().FindByField("identify", identify, "book_id"); len(books) > 0 {
|
||||
c.JsonResult(6006, "项目标识已存在")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_id_existed"))
|
||||
}
|
||||
|
||||
tempPath := filepath.Join(os.TempDir(), c.CruSession.SessionID(context.TODO()))
|
||||
|
@ -639,7 +641,11 @@ func (c *BookController) Import() {
|
|||
book.Editor = "markdown"
|
||||
book.Theme = "default"
|
||||
|
||||
go book.ImportBook(tempPath)
|
||||
if strings.EqualFold(ext, ".zip") {
|
||||
go book.ImportBook(tempPath, c.Lang)
|
||||
} else if strings.EqualFold(ext, ".docx") {
|
||||
go book.ImportWordBook(tempPath, c.Lang)
|
||||
}
|
||||
|
||||
logs.Info("用户[", c.Member.Account, "]导入了项目 ->", book)
|
||||
|
||||
|
@ -655,10 +661,10 @@ func (c *BookController) Import() {
|
|||
//
|
||||
// if err != nil {
|
||||
// if err == models.ErrPermissionDenied {
|
||||
// c.JsonResult(403, "权限不足")
|
||||
// c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
// }
|
||||
// if err == orm.ErrNoRows {
|
||||
// c.JsonResult(404, "项目不存在")
|
||||
// c.JsonResult(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
// }
|
||||
// logs.Error("生成阅读令牌失败 =>", err)
|
||||
// c.JsonResult(6002, err.Error())
|
||||
|
@ -666,7 +672,7 @@ func (c *BookController) Import() {
|
|||
// book := models.NewBook()
|
||||
//
|
||||
// if _, err := book.Find(bookResult.BookId); err != nil {
|
||||
// c.JsonResult(6001, "项目不存在")
|
||||
// c.JsonResult(6001, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
// }
|
||||
// if action == "create" {
|
||||
// if bookResult.PrivatelyOwned == 0 {
|
||||
|
@ -708,7 +714,7 @@ func (c *BookController) Delete() {
|
|||
err = models.NewBook().ThoroughDeleteBook(bookResult.BookId)
|
||||
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(6002, "项目不存在")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
if err != nil {
|
||||
logs.Error("删除项目 => ", err)
|
||||
|
@ -739,22 +745,22 @@ func (c *BookController) Release() {
|
|||
|
||||
if err != nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
c.JsonResult(6001, "权限不足")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(6002, "项目不存在")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
logs.Error(err)
|
||||
c.JsonResult(6003, "未知错误")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.unknown_exception"))
|
||||
}
|
||||
if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder && book.RoleId != conf.BookEditor {
|
||||
c.JsonResult(6003, "权限不足")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
bookId = book.BookId
|
||||
}
|
||||
go models.NewBook().ReleaseContent(bookId)
|
||||
go models.NewBook().ReleaseContent(bookId, c.Lang)
|
||||
|
||||
c.JsonResult(0, "发布任务已推送到任务队列,稍后将在后台执行。")
|
||||
c.JsonResult(0, i18n.Tr(c.Lang, "message.publish_to_queue"))
|
||||
}
|
||||
|
||||
//文档排序.
|
||||
|
@ -770,7 +776,7 @@ func (c *BookController) SaveSort() {
|
|||
if c.Member.IsAdministrator() {
|
||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil || book == nil {
|
||||
c.JsonResult(6001, "项目不存在")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
return
|
||||
}
|
||||
bookId = book.BookId
|
||||
|
@ -782,7 +788,7 @@ func (c *BookController) SaveSort() {
|
|||
c.Abort("403")
|
||||
}
|
||||
if bookResult.RoleId == conf.BookObserver {
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
bookId = bookResult.BookId
|
||||
}
|
||||
|
@ -806,7 +812,7 @@ func (c *BookController) SaveSort() {
|
|||
continue
|
||||
}
|
||||
if doc.BookId != bookId {
|
||||
logs.Info("%s", "权限错误")
|
||||
logs.Info("%s", i18n.Tr(c.Lang, "message.no_permission"))
|
||||
continue
|
||||
}
|
||||
sort, ok := item["sort"].(float64)
|
||||
|
@ -846,15 +852,15 @@ func (c *BookController) Team() {
|
|||
pageIndex, _ := c.GetInt("page", 1)
|
||||
|
||||
if key == "" {
|
||||
c.ShowErrorPage(404, "项目不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
|
||||
book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId)
|
||||
if err != nil || book == nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
c.ShowErrorPage(403, "权限不足")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
c.ShowErrorPage(500, "系统错误")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
|
||||
return
|
||||
}
|
||||
//如果不是创始人也不是管理员则不能操作
|
||||
|
@ -925,7 +931,7 @@ func (c *BookController) TeamDelete() {
|
|||
teamId, _ := c.GetInt("teamId")
|
||||
|
||||
if teamId <= 0 {
|
||||
c.JsonResult(5001, "参数错误")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
book, err := c.IsPermission()
|
||||
|
||||
|
@ -990,22 +996,22 @@ func (c *BookController) IsPermission() (*models.BookResult, error) {
|
|||
identify := c.GetString("identify")
|
||||
|
||||
if identify == "" {
|
||||
return nil, errors.New("参数错误")
|
||||
return nil, errors.New(i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
|
||||
|
||||
if err != nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
return book, errors.New("权限不足")
|
||||
return book, errors.New(i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
if err == orm.ErrNoRows {
|
||||
return book, errors.New("项目不存在")
|
||||
return book, errors.New(i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
return book, err
|
||||
}
|
||||
if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder {
|
||||
return book, errors.New("权限不足")
|
||||
return book, errors.New(i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
return book, nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
)
|
||||
|
@ -20,7 +21,7 @@ func (c *BookMemberController) AddMember() {
|
|||
roleId, _ := c.GetInt("role_id", 3)
|
||||
logs.Info(account)
|
||||
if identify == "" || account <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
book, err := c.IsPermission()
|
||||
|
||||
|
@ -31,14 +32,14 @@ func (c *BookMemberController) AddMember() {
|
|||
member := models.NewMember()
|
||||
|
||||
if _, err := member.Find(account); err != nil {
|
||||
c.JsonResult(404, "用户不存在")
|
||||
c.JsonResult(404, i18n.Tr(c.Lang, "message.user_not_existed"))
|
||||
}
|
||||
if member.Status == 1 {
|
||||
c.JsonResult(6003, "用户已被禁用")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.user_disable"))
|
||||
}
|
||||
|
||||
if _, err := models.NewRelationship().FindForRoleId(book.BookId, member.MemberId); err == nil {
|
||||
c.JsonResult(6003, "用户已存在该项目中")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.user_exist_in_proj"))
|
||||
}
|
||||
|
||||
relationship := models.NewRelationship()
|
||||
|
@ -51,7 +52,7 @@ func (c *BookMemberController) AddMember() {
|
|||
memberRelationshipResult.RoleId = conf.BookRole(roleId)
|
||||
memberRelationshipResult.RelationshipId = relationship.RelationshipId
|
||||
memberRelationshipResult.BookId = book.BookId
|
||||
memberRelationshipResult.ResolveRoleName()
|
||||
memberRelationshipResult.ResolveRoleName(c.Lang)
|
||||
|
||||
c.JsonResult(0, "ok", memberRelationshipResult)
|
||||
}
|
||||
|
@ -65,33 +66,33 @@ func (c *BookMemberController) ChangeRole() {
|
|||
role, _ := c.GetInt("role_id", 0)
|
||||
|
||||
if identify == "" || memberId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
if memberId == c.Member.MemberId {
|
||||
c.JsonResult(6006, "不能变更自己的权限")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.cannot_change_own_priv"))
|
||||
}
|
||||
book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
|
||||
|
||||
if err != nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
c.JsonResult(403, "权限不足")
|
||||
c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(404, "项目不存在")
|
||||
c.JsonResult(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
c.JsonResult(6002, err.Error())
|
||||
}
|
||||
if book.RoleId != 0 && book.RoleId != 1 {
|
||||
c.JsonResult(403, "权限不足")
|
||||
c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
member := models.NewMember()
|
||||
|
||||
if _, err := member.Find(memberId); err != nil {
|
||||
c.JsonResult(6003, "用户不存在")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.user_not_existed"))
|
||||
}
|
||||
if member.Status == 1 {
|
||||
c.JsonResult(6004, "用户已被禁用")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.user_disable"))
|
||||
}
|
||||
|
||||
relationship, err := models.NewRelationship().UpdateRoleId(book.BookId, memberId, conf.BookRole(role))
|
||||
|
@ -105,7 +106,7 @@ func (c *BookMemberController) ChangeRole() {
|
|||
memberRelationshipResult.RoleId = relationship.RoleId
|
||||
memberRelationshipResult.RelationshipId = relationship.RelationshipId
|
||||
memberRelationshipResult.BookId = book.BookId
|
||||
memberRelationshipResult.ResolveRoleName()
|
||||
memberRelationshipResult.ResolveRoleName(c.Lang)
|
||||
|
||||
c.JsonResult(0, "ok", memberRelationshipResult)
|
||||
}
|
||||
|
@ -116,25 +117,25 @@ func (c *BookMemberController) RemoveMember() {
|
|||
member_id, _ := c.GetInt("member_id", 0)
|
||||
|
||||
if identify == "" || member_id <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
if member_id == c.Member.MemberId {
|
||||
c.JsonResult(6006, "不能删除自己")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.cannot_delete_self"))
|
||||
}
|
||||
book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
|
||||
|
||||
if err != nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
c.JsonResult(403, "权限不足")
|
||||
c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(404, "项目不存在")
|
||||
c.JsonResult(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
c.JsonResult(6002, err.Error())
|
||||
}
|
||||
//如果不是创始人也不是管理员则不能操作
|
||||
if book.RoleId != conf.BookFounder && book.RoleId != conf.BookAdmin {
|
||||
c.JsonResult(403, "权限不足")
|
||||
c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
err = models.NewRelationship().DeleteByBookIdAndMemberId(book.BookId, member_id)
|
||||
|
||||
|
@ -150,15 +151,15 @@ func (c *BookMemberController) IsPermission() (*models.BookResult, error) {
|
|||
|
||||
if err != nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
return book, errors.New("权限不足")
|
||||
return book, errors.New(i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
if err == orm.ErrNoRows {
|
||||
return book, errors.New("项目不存在")
|
||||
return book, errors.New(i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
return book, err
|
||||
}
|
||||
if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder {
|
||||
return book, errors.New("权限不足")
|
||||
return book, errors.New(i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
return book, nil
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/boombuler/barcode"
|
||||
"github.com/boombuler/barcode/qr"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
|
@ -43,7 +44,7 @@ func (c *DocumentController) Index() {
|
|||
token := c.GetString("token")
|
||||
|
||||
if identify == "" {
|
||||
c.ShowErrorPage(404, "项目不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
|
||||
// 如果没有开启匿名访问则跳转到登录
|
||||
|
@ -66,17 +67,9 @@ func (c *DocumentController) Index() {
|
|||
c.Data["Content"] = template.HTML(doc.Release)
|
||||
|
||||
c.Data["Description"] = utils.AutoSummary(doc.Release, 120)
|
||||
doc.IncrViewCount(doc.DocumentId)
|
||||
c.Data["ViewCount"] = doc.ViewCount + 1
|
||||
c.Data["DocumentId"] = doc.DocumentId
|
||||
|
||||
// 获取评论、分页
|
||||
comments, count, _ := models.NewComment().QueryCommentByDocumentId(doc.DocumentId, 1, conf.PageSize, c.Member)
|
||||
page := pagination.PageUtil(int(count), 1, conf.PageSize, comments)
|
||||
c.Data["Page"] = page
|
||||
}
|
||||
} else {
|
||||
c.Data["Title"] = "概要"
|
||||
c.Data["Title"] = i18n.Tr(c.Lang, "blog.summary")
|
||||
c.Data["Content"] = template.HTML(blackfriday.Run([]byte(bookResult.Description)))
|
||||
}
|
||||
|
||||
|
@ -84,14 +77,15 @@ func (c *DocumentController) Index() {
|
|||
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(404, "当前项目没有文档")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.no_doc_in_cur_proj"))
|
||||
} else {
|
||||
logs.Error("生成项目文档树时出错 -> ", err)
|
||||
c.ShowErrorPage(500, "生成项目文档树时出错")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.build_doc_tree_error"))
|
||||
}
|
||||
}
|
||||
c.Data["Model"] = bookResult
|
||||
c.Data["Result"] = template.HTML(tree)
|
||||
|
||||
}
|
||||
|
||||
// 阅读文档
|
||||
|
@ -105,7 +99,7 @@ func (c *DocumentController) Read() {
|
|||
c.Data["DocumentId"] = id
|
||||
|
||||
if identify == "" || id == "" {
|
||||
c.ShowErrorPage(404, "项目不存或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
|
||||
// 如果没有开启匿名访问则跳转到登录
|
||||
|
@ -119,64 +113,54 @@ func (c *DocumentController) Read() {
|
|||
c.TplName = fmt.Sprintf("document/%s_read.tpl", bookResult.Theme)
|
||||
|
||||
doc := models.NewDocument()
|
||||
|
||||
if docId, err := strconv.Atoi(id); err == nil {
|
||||
doc, err = doc.FromCacheById(docId)
|
||||
if err != nil || doc == nil {
|
||||
logs.Error("从缓存中读取文档时失败 ->", err)
|
||||
c.ShowErrorPage(404, "文档不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
doc, err = doc.FromCacheByIdentify(id, bookResult.BookId)
|
||||
if err != nil || doc == nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(404, "文档不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
} else {
|
||||
logs.Error("从缓存查询文档时出错 ->", err)
|
||||
c.ShowErrorPage(500, "未知异常")
|
||||
logs.Error("从数据库查询文档时出错 ->", err)
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.unknown_exception"))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if doc.BookId != bookResult.BookId {
|
||||
c.ShowErrorPage(404, "文档不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
}
|
||||
|
||||
doc.Lang = c.Lang
|
||||
doc.Processor()
|
||||
|
||||
c.Data["DocumentId"] = doc.DocumentId
|
||||
attach, err := models.NewAttachment().FindListByDocumentId(doc.DocumentId)
|
||||
if err == nil {
|
||||
doc.AttachList = attach
|
||||
}
|
||||
|
||||
doc.IncrViewCount(doc.DocumentId)
|
||||
c.Data["ViewCount"] = doc.ViewCount + 1
|
||||
|
||||
// 获取评论、分页
|
||||
comments, count, _ := models.NewComment().QueryCommentByDocumentId(doc.DocumentId, 1, conf.PageSize, c.Member)
|
||||
page := pagination.PageUtil(int(count), 1, conf.PageSize, comments)
|
||||
c.Data["Page"] = page
|
||||
doc.ViewCount = doc.ViewCount + 1
|
||||
doc.PutToCache()
|
||||
|
||||
if c.IsAjax() {
|
||||
var data struct {
|
||||
DocTitle string `json:"doc_title"`
|
||||
Body string `json:"body"`
|
||||
Title string `json:"title"`
|
||||
Version int64 `json:"version"`
|
||||
ViewCount int `json:"view_count"`
|
||||
DocId int `json:"doc_id"`
|
||||
Page pagination.Page `json:"page"`
|
||||
DocTitle string `json:"doc_title"`
|
||||
Body string `json:"body"`
|
||||
Title string `json:"title"`
|
||||
Version int64 `json:"version"`
|
||||
ViewCount int `json:"view_count"`
|
||||
}
|
||||
data.DocTitle = doc.DocumentName
|
||||
data.Body = doc.Release
|
||||
data.Title = doc.DocumentName + " - Powered by MinDoc"
|
||||
data.Version = doc.Version
|
||||
data.ViewCount = doc.ViewCount + 1
|
||||
data.DocId = doc.DocumentId
|
||||
data.Page = page
|
||||
data.ViewCount = doc.ViewCount
|
||||
|
||||
c.JsonResult(0, "ok", data)
|
||||
}
|
||||
|
@ -186,7 +170,7 @@ func (c *DocumentController) Read() {
|
|||
if err != nil && err != orm.ErrNoRows {
|
||||
logs.Error("生成项目文档树时出错 ->", err)
|
||||
|
||||
c.ShowErrorPage(500, "生成项目文档树时出错")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.build_doc_tree_error"))
|
||||
}
|
||||
|
||||
c.Data["Description"] = utils.AutoSummary(doc.Release, 120)
|
||||
|
@ -195,6 +179,7 @@ func (c *DocumentController) Read() {
|
|||
c.Data["Result"] = template.HTML(tree)
|
||||
c.Data["Title"] = doc.DocumentName
|
||||
c.Data["Content"] = template.HTML(doc.Release)
|
||||
c.Data["ViewCount"] = doc.ViewCount
|
||||
}
|
||||
|
||||
// 编辑文档
|
||||
|
@ -203,7 +188,7 @@ func (c *DocumentController) Edit() {
|
|||
|
||||
identify := c.Ctx.Input.Param(":key")
|
||||
if identify == "" {
|
||||
c.ShowErrorPage(404, "无法解析项目标识")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.project_id_error"))
|
||||
}
|
||||
|
||||
bookResult := models.NewBookResult()
|
||||
|
@ -213,7 +198,7 @@ func (c *DocumentController) Edit() {
|
|||
if c.Member.IsAdministrator() {
|
||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookResult = models.NewBookResult().ToBookResult(*book)
|
||||
|
@ -222,15 +207,15 @@ func (c *DocumentController) Edit() {
|
|||
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows || err == models.ErrPermissionDenied {
|
||||
c.ShowErrorPage(403, "项目不存在或没有权限")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
} else {
|
||||
logs.Error("查询项目时出错 -> ", err)
|
||||
c.ShowErrorPage(500, "查询项目时出错")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
|
||||
}
|
||||
return
|
||||
}
|
||||
if bookResult.RoleId == conf.BookObserver {
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,6 +223,8 @@ func (c *DocumentController) Edit() {
|
|||
if bookResult.Editor == "markdown" {
|
||||
c.TplName = "document/markdown_edit_template.tpl"
|
||||
} else if bookResult.Editor == "html" {
|
||||
c.TplName = "document/html_edit_template.tpl"
|
||||
} else if bookResult.Editor == "new_html" {
|
||||
c.TplName = "document/new_html_edit_template.tpl"
|
||||
} else {
|
||||
c.TplName = "document/" + bookResult.Editor + "_edit_template.tpl"
|
||||
|
@ -284,11 +271,11 @@ func (c *DocumentController) Create() {
|
|||
isOpen, _ := c.GetInt("is_open", 0)
|
||||
|
||||
if identify == "" {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
if docName == "" {
|
||||
c.JsonResult(6004, "文档名称不能为空")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.doc_name_empty"))
|
||||
}
|
||||
|
||||
bookId := 0
|
||||
|
@ -298,7 +285,7 @@ func (c *DocumentController) Create() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_existed_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = book.BookId
|
||||
|
@ -307,7 +294,7 @@ func (c *DocumentController) Create() {
|
|||
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("FindByIdentify => ", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_existed_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = bookResult.BookId
|
||||
|
@ -315,18 +302,18 @@ func (c *DocumentController) Create() {
|
|||
|
||||
if docIdentify != "" {
|
||||
if ok, err := regexp.MatchString(`[a-z]+[a-zA-Z0-9_.\-]*$`, docIdentify); !ok || err != nil {
|
||||
c.JsonResult(6003, "文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.project_id_tips"))
|
||||
}
|
||||
|
||||
d, _ := models.NewDocument().FindByIdentityFirst(docIdentify, bookId)
|
||||
if d.DocumentId > 0 && d.DocumentId != docId {
|
||||
c.JsonResult(6006, "文档标识已被使用")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_id_existed"))
|
||||
}
|
||||
}
|
||||
if parentId > 0 {
|
||||
doc, err := models.NewDocument().Find(parentId)
|
||||
if err != nil || doc.BookId != bookId {
|
||||
c.JsonResult(6003, "父分类不存在")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.parent_id_not_existed"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,7 +338,7 @@ func (c *DocumentController) Create() {
|
|||
|
||||
if err := document.InsertOrUpdate(); err != nil {
|
||||
logs.Error("添加或更新文档时出错 -> ", err)
|
||||
c.JsonResult(6005, "保存失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
} else {
|
||||
c.JsonResult(0, "ok", document)
|
||||
}
|
||||
|
@ -364,7 +351,7 @@ func (c *DocumentController) Upload() {
|
|||
isAttach := true
|
||||
|
||||
if identify == "" {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
name := "editormd-file-file"
|
||||
|
@ -374,7 +361,7 @@ func (c *DocumentController) Upload() {
|
|||
name = "editormd-image-file"
|
||||
file, moreFile, err = c.GetFile(name)
|
||||
if err == http.ErrMissingFile || moreFile == nil {
|
||||
c.JsonResult(6003, "没有发现需要上传的文件")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_empty"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -390,17 +377,17 @@ func (c *DocumentController) Upload() {
|
|||
}
|
||||
|
||||
if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() {
|
||||
c.JsonResult(6009, "文件大小超过了限定的最大值")
|
||||
c.JsonResult(6009, i18n.Tr(c.Lang, "message.upload_file_size_limit"))
|
||||
}
|
||||
|
||||
ext := filepath.Ext(moreFile.Filename)
|
||||
//文件必须带有后缀名
|
||||
if ext == "" {
|
||||
c.JsonResult(6003, "无法解析文件的格式")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_type_error"))
|
||||
}
|
||||
//如果文件类型设置为 * 标识不限制文件类型
|
||||
if conf.IsAllowUploadFileExt(ext) == false {
|
||||
c.JsonResult(6004, "不允许的文件类型")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.upload_file_type_error"))
|
||||
}
|
||||
|
||||
bookId := 0
|
||||
|
@ -410,7 +397,7 @@ func (c *DocumentController) Upload() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(6006, "文档不存在或权限不足")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.doc_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = book.BookId
|
||||
|
@ -420,7 +407,7 @@ func (c *DocumentController) Upload() {
|
|||
if err != nil {
|
||||
logs.Error("DocumentController.Edit => ", err)
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(6006, "权限不足")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
c.JsonResult(6001, err.Error())
|
||||
|
@ -428,7 +415,7 @@ func (c *DocumentController) Upload() {
|
|||
|
||||
// 如果没有编辑权限
|
||||
if book.RoleId != conf.BookEditor && book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder {
|
||||
c.JsonResult(6006, "权限不足")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
bookId = book.BookId
|
||||
|
@ -437,11 +424,11 @@ func (c *DocumentController) Upload() {
|
|||
if docId > 0 {
|
||||
doc, err := models.NewDocument().Find(docId)
|
||||
if err != nil {
|
||||
c.JsonResult(6007, "文档不存在")
|
||||
c.JsonResult(6007, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
}
|
||||
|
||||
if doc.BookId != bookId {
|
||||
c.JsonResult(6008, "文档不属于指定的项目")
|
||||
c.JsonResult(6008, i18n.Tr(c.Lang, "message.doc_not_belong_project"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,7 +450,7 @@ func (c *DocumentController) Upload() {
|
|||
|
||||
if err != nil {
|
||||
logs.Error("保存文件失败 -> ", err)
|
||||
c.JsonResult(6005, "保存文件失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
attachment := models.NewAttachment()
|
||||
|
@ -496,7 +483,7 @@ func (c *DocumentController) Upload() {
|
|||
if err != nil {
|
||||
os.Remove(filePath)
|
||||
logs.Error("文件保存失败 ->", err)
|
||||
c.JsonResult(6006, "文件保存失败")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
if attachment.HttpPath == "" {
|
||||
|
@ -504,7 +491,7 @@ func (c *DocumentController) Upload() {
|
|||
|
||||
if err := attachment.Update(); err != nil {
|
||||
logs.Error("保存文件失败 ->", err)
|
||||
c.JsonResult(6005, "保存文件失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,10 +533,10 @@ func (c *DocumentController) DownloadAttachment() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(404, "项目不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
} else {
|
||||
logs.Error("查找项目时出错 ->", err)
|
||||
c.ShowErrorPage(500, "系统错误")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,7 +544,7 @@ func (c *DocumentController) DownloadAttachment() {
|
|||
if c.Member == nil || c.Member.Role != conf.MemberSuperRole {
|
||||
// 如果项目是私有的,并且 token 不正确
|
||||
if (book.PrivatelyOwned == 1 && token == "") || (book.PrivatelyOwned == 1 && book.PrivateToken != token) {
|
||||
c.ShowErrorPage(403, "权限不足")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,14 +559,14 @@ func (c *DocumentController) DownloadAttachment() {
|
|||
if err != nil {
|
||||
logs.Error("查找附件时出错 -> ", err)
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(404, "附件不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
} else {
|
||||
c.ShowErrorPage(500, "查找附件时出错")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
|
||||
}
|
||||
}
|
||||
|
||||
if attachment.BookId != bookId {
|
||||
c.ShowErrorPage(404, "附件不存在或已删除")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
}
|
||||
|
||||
c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName)
|
||||
|
@ -592,39 +579,39 @@ func (c *DocumentController) RemoveAttachment() {
|
|||
attachId, _ := c.GetInt("attach_id")
|
||||
|
||||
if attachId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
attach, err := models.NewAttachment().Find(attachId)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6002, "附件不存在")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.attachment_not_exist"))
|
||||
}
|
||||
|
||||
document, err := models.NewDocument().Find(attach.DocumentId)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6003, "文档不存在")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
}
|
||||
|
||||
if c.Member.Role != conf.MemberSuperRole {
|
||||
rel, err := models.NewRelationship().FindByBookIdAndMemberId(document.BookId, c.Member.MemberId)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6004, "权限不足")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
|
||||
if rel.RoleId == conf.BookObserver {
|
||||
c.JsonResult(6004, "权限不足")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
}
|
||||
|
||||
err = attach.Delete()
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6005, "删除失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
os.Remove(filepath.Join(conf.WorkingDirectory, attach.FilePath))
|
||||
|
@ -646,7 +633,7 @@ func (c *DocumentController) Delete() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
logs.Error("FindByIdentify => ", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = book.BookId
|
||||
|
@ -655,31 +642,31 @@ func (c *DocumentController) Delete() {
|
|||
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("FindByIdentify => ", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = bookResult.BookId
|
||||
}
|
||||
|
||||
if docId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
doc, err := models.NewDocument().Find(docId)
|
||||
|
||||
if err != nil {
|
||||
logs.Error("Delete => ", err)
|
||||
c.JsonResult(6003, "删除失败")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
// 如果文档所属项目错误
|
||||
if doc.BookId != bookId {
|
||||
c.JsonResult(6004, "参数错误")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
// 递归删除项目下的文档以及子文档
|
||||
err = doc.RecursiveDocument(doc.DocumentId)
|
||||
if err != nil {
|
||||
c.JsonResult(6005, "删除失败")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
// 重置文档数量统计
|
||||
|
@ -705,7 +692,7 @@ func (c *DocumentController) Content() {
|
|||
if c.Member.IsAdministrator() {
|
||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil || book == nil {
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -716,7 +703,7 @@ func (c *DocumentController) Content() {
|
|||
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("项目不存在或权限不足 -> ", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = bookResult.BookId
|
||||
|
@ -724,7 +711,7 @@ func (c *DocumentController) Content() {
|
|||
}
|
||||
|
||||
if docId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
if c.Ctx.Input.IsPost() {
|
||||
|
@ -734,19 +721,18 @@ func (c *DocumentController) Content() {
|
|||
isCover := c.GetString("cover")
|
||||
|
||||
doc, err := models.NewDocument().Find(docId)
|
||||
|
||||
if err != nil || doc == nil {
|
||||
c.JsonResult(6003, "读取文档错误")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.read_file_error"))
|
||||
return
|
||||
}
|
||||
|
||||
if doc.BookId != bookId {
|
||||
c.JsonResult(6004, "保存的文档不属于指定项目")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.dock_not_belong_project"))
|
||||
}
|
||||
|
||||
if doc.Version != version && !strings.EqualFold(isCover, "yes") {
|
||||
logs.Info("%d|", version, doc.Version)
|
||||
c.JsonResult(6005, "文档已被修改确定要覆盖吗?")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.confirm_override_doc"))
|
||||
}
|
||||
|
||||
history := models.NewDocumentHistory()
|
||||
|
@ -759,7 +745,7 @@ func (c *DocumentController) Content() {
|
|||
history.ParentId = doc.ParentId
|
||||
history.Version = time.Now().Unix()
|
||||
history.Action = "modify"
|
||||
history.ActionName = "修改文档"
|
||||
history.ActionName = i18n.Tr(c.Lang, "doc.modify_doc")
|
||||
|
||||
if markdown == "" && content != "" {
|
||||
doc.Markdown = content
|
||||
|
@ -773,7 +759,7 @@ func (c *DocumentController) Content() {
|
|||
|
||||
if err := doc.InsertOrUpdate(); err != nil {
|
||||
logs.Error("InsertOrUpdate => ", err)
|
||||
c.JsonResult(6006, "保存失败")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
// 如果启用了文档历史,则添加历史文档
|
||||
|
@ -790,9 +776,10 @@ func (c *DocumentController) Content() {
|
|||
//如果启用了自动发布
|
||||
if autoRelease {
|
||||
go func() {
|
||||
doc.Lang = c.Lang
|
||||
err := doc.ReleaseContent()
|
||||
if err == nil {
|
||||
logs.Informational("文档自动发布成功 -> document_id=%d;document_name=%s", doc.DocumentId, doc.DocumentName)
|
||||
logs.Informational(i18n.Tr(c.Lang, "message.doc_auto_published")+"-> document_id=%d;document_name=%s", doc.DocumentId, doc.DocumentName)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -802,7 +789,7 @@ func (c *DocumentController) Content() {
|
|||
|
||||
doc, err := models.NewDocument().Find(docId)
|
||||
if err != nil {
|
||||
c.JsonResult(6003, "文档不存在")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -820,7 +807,7 @@ func (c *DocumentController) Export() {
|
|||
|
||||
identify := c.Ctx.Input.Param(":key")
|
||||
if identify == "" {
|
||||
c.ShowErrorPage(500, "参数错误")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
output := c.GetString("output")
|
||||
|
@ -832,7 +819,7 @@ func (c *DocumentController) Export() {
|
|||
return
|
||||
}
|
||||
if !conf.GetEnableExport() {
|
||||
c.ShowErrorPage(500, "系统没有开启导出功能")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "export_func_disable"))
|
||||
}
|
||||
|
||||
bookResult := models.NewBookResult()
|
||||
|
@ -840,10 +827,10 @@ func (c *DocumentController) Export() {
|
|||
book, err := models.NewBook().FindByIdentify(identify)
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(404, "项目不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
} else {
|
||||
logs.Error("查找项目时出错 ->", err)
|
||||
c.ShowErrorPage(500, "查找项目时出错")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error"))
|
||||
}
|
||||
}
|
||||
bookResult = models.NewBookResult().ToBookResult(*book)
|
||||
|
@ -851,7 +838,7 @@ func (c *DocumentController) Export() {
|
|||
bookResult = c.isReadable(identify, token)
|
||||
}
|
||||
if !bookResult.IsDownload {
|
||||
c.ShowErrorPage(200, "当前项目没有开启导出功能")
|
||||
c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.cur_project_export_func_disable"))
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") {
|
||||
|
@ -860,12 +847,12 @@ func (c *DocumentController) Export() {
|
|||
|
||||
if output == "markdown" {
|
||||
if bookResult.Editor != "markdown" {
|
||||
c.ShowErrorPage(500, "当前项目不支持Markdown编辑器")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.cur_project_not_support_md"))
|
||||
}
|
||||
p, err := bookResult.ExportMarkdown(c.CruSession.SessionID(context.TODO()))
|
||||
|
||||
if err != nil {
|
||||
c.ShowErrorPage(500, "导出文档失败")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.Ctx.Output.Download(p, bookResult.BookName+".zip")
|
||||
|
||||
|
@ -898,15 +885,15 @@ func (c *DocumentController) Export() {
|
|||
|
||||
} else if output == "pdf" || output == "epub" || output == "docx" || output == "mobi" {
|
||||
if err := models.BackgroundConvert(c.CruSession.SessionID(context.TODO()), bookResult); err != nil && err != gopool.ErrHandlerIsExist {
|
||||
c.ShowErrorPage(500, "导出失败,请查看系统日志")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.export_failed"))
|
||||
}
|
||||
|
||||
c.ShowErrorPage(200, "文档正在后台转换,请稍后再下载")
|
||||
c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.file_converting"))
|
||||
} else {
|
||||
c.ShowErrorPage(200, "不支持的文件格式")
|
||||
c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.unsupport_file_type"))
|
||||
}
|
||||
|
||||
c.ShowErrorPage(404, "项目没有导出文件")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.no_exportable_file"))
|
||||
}
|
||||
|
||||
// 生成项目访问的二维码
|
||||
|
@ -917,20 +904,20 @@ func (c *DocumentController) QrCode() {
|
|||
|
||||
book, err := models.NewBook().FindByIdentify(identify)
|
||||
if err != nil || book.BookId <= 0 {
|
||||
c.ShowErrorPage(404, "项目不存在")
|
||||
c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
|
||||
uri := conf.URLFor("DocumentController.Index", ":key", identify)
|
||||
code, err := qr.Encode(uri, qr.L, qr.Unicode)
|
||||
if err != nil {
|
||||
logs.Error("生成二维码失败 ->", err)
|
||||
c.ShowErrorPage(500, "生成二维码失败")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed"))
|
||||
}
|
||||
|
||||
code, err = barcode.Scale(code, 150, 150)
|
||||
if err != nil {
|
||||
logs.Error("生成二维码失败 ->", err)
|
||||
c.ShowErrorPage(500, "生成二维码失败")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed"))
|
||||
}
|
||||
|
||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "image/png")
|
||||
|
@ -940,7 +927,7 @@ func (c *DocumentController) QrCode() {
|
|||
err = png.Encode(c.Ctx.ResponseWriter, code)
|
||||
if err != nil {
|
||||
logs.Error("生成二维码失败 ->", err)
|
||||
c.ShowErrorPage(500, "生成二维码失败")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -953,7 +940,7 @@ func (c *DocumentController) Search() {
|
|||
keyword := strings.TrimSpace(c.GetString("keyword"))
|
||||
|
||||
if identify == "" {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
if !c.EnableAnonymous && !c.isUserLoggedIn() {
|
||||
|
@ -966,11 +953,11 @@ func (c *DocumentController) Search() {
|
|||
docs, err := models.NewDocumentSearchResult().SearchDocument(keyword, bookResult.BookId)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6002, "搜索结果错误")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.search_result_error"))
|
||||
}
|
||||
|
||||
if len(docs) < 0 {
|
||||
c.JsonResult(404, "没有数据库")
|
||||
c.JsonResult(404, i18n.Tr(c.Lang, "message.no_data"))
|
||||
}
|
||||
|
||||
for _, doc := range docs {
|
||||
|
@ -1000,7 +987,7 @@ func (c *DocumentController) History() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
logs.Error("查找项目失败 ->", err)
|
||||
c.Data["ErrorMessage"] = "项目不存在或权限不足"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1010,7 +997,7 @@ func (c *DocumentController) History() {
|
|||
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("查找项目失败 ->", err)
|
||||
c.Data["ErrorMessage"] = "项目不存在或权限不足"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1019,27 +1006,27 @@ func (c *DocumentController) History() {
|
|||
}
|
||||
|
||||
if docId <= 0 {
|
||||
c.Data["ErrorMessage"] = "参数错误"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.param_error")
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := models.NewDocument().Find(docId)
|
||||
if err != nil {
|
||||
logs.Error("Delete => ", err)
|
||||
c.Data["ErrorMessage"] = "获取历史失败"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.get_doc_his_failed")
|
||||
return
|
||||
}
|
||||
|
||||
// 如果文档所属项目错误
|
||||
if doc.BookId != bookId {
|
||||
c.Data["ErrorMessage"] = "参数错误"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.param_error")
|
||||
return
|
||||
}
|
||||
|
||||
histories, totalCount, err := models.NewDocumentHistory().FindToPager(docId, pageIndex, conf.PageSize)
|
||||
if err != nil {
|
||||
logs.Error("分页查找文档历史失败 ->", err)
|
||||
c.Data["ErrorMessage"] = "获取历史失败"
|
||||
c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.get_doc_his_failed")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1063,7 +1050,7 @@ func (c *DocumentController) DeleteHistory() {
|
|||
historyId, _ := c.GetInt("history_id", 0)
|
||||
|
||||
if historyId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
bookId := 0
|
||||
|
@ -1073,7 +1060,7 @@ func (c *DocumentController) DeleteHistory() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
logs.Error("查找项目失败 ->", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = book.BookId
|
||||
|
@ -1081,31 +1068,31 @@ func (c *DocumentController) DeleteHistory() {
|
|||
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("查找项目失败 ->", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = bookResult.BookId
|
||||
}
|
||||
|
||||
if docId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
doc, err := models.NewDocument().Find(docId)
|
||||
if err != nil {
|
||||
logs.Error("Delete => ", err)
|
||||
c.JsonResult(6001, "获取历史失败")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.get_doc_his_failed"))
|
||||
}
|
||||
|
||||
// 如果文档所属项目错误
|
||||
if doc.BookId != bookId {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
err = models.NewDocumentHistory().Delete(historyId, docId)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6002, "删除失败")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
c.JsonResult(0, "ok")
|
||||
|
@ -1122,7 +1109,7 @@ func (c *DocumentController) RestoreHistory() {
|
|||
historyId, _ := c.GetInt("history_id", 0)
|
||||
|
||||
if historyId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
bookId := 0
|
||||
|
@ -1131,7 +1118,7 @@ func (c *DocumentController) RestoreHistory() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
logs.Error("FindByIdentify => ", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = book.BookId
|
||||
|
@ -1139,31 +1126,31 @@ func (c *DocumentController) RestoreHistory() {
|
|||
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("FindByIdentify => ", err)
|
||||
c.JsonResult(6002, "项目不存在或权限不足")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit"))
|
||||
}
|
||||
|
||||
bookId = bookResult.BookId
|
||||
}
|
||||
|
||||
if docId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
doc, err := models.NewDocument().Find(docId)
|
||||
if err != nil {
|
||||
logs.Error("Delete => ", err)
|
||||
c.JsonResult(6001, "获取历史失败")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.get_doc_his_failed"))
|
||||
}
|
||||
|
||||
// 如果文档所属项目错误
|
||||
if doc.BookId != bookId {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
err = models.NewDocumentHistory().Restore(historyId, docId, c.Member.MemberId)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6002, "删除失败")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
|
||||
c.JsonResult(0, "ok", doc)
|
||||
|
@ -1185,7 +1172,7 @@ func (c *DocumentController) Compare() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
if err != nil {
|
||||
logs.Error("DocumentController.Compare => ", err)
|
||||
c.ShowErrorPage(403, "权限不足")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1196,7 +1183,7 @@ func (c *DocumentController) Compare() {
|
|||
bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
|
||||
if err != nil || bookResult.RoleId == conf.BookObserver {
|
||||
logs.Error("FindByIdentify => ", err)
|
||||
c.ShowErrorPage(403, "权限不足")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1206,7 +1193,7 @@ func (c *DocumentController) Compare() {
|
|||
}
|
||||
|
||||
if historyId <= 0 {
|
||||
c.ShowErrorPage(60002, "参数错误")
|
||||
c.ShowErrorPage(60002, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
history, err := models.NewDocumentHistory().Find(historyId)
|
||||
|
@ -1217,7 +1204,7 @@ func (c *DocumentController) Compare() {
|
|||
|
||||
doc, err := models.NewDocument().Find(history.DocumentId)
|
||||
if err != nil || doc == nil || doc.BookId != bookId {
|
||||
c.ShowErrorPage(60002, "文档不存在或已删除")
|
||||
c.ShowErrorPage(60002, i18n.Tr(c.Lang, "message.doc_not_exist"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1226,7 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu
|
|||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.ShowErrorPage(500, "项目不存在")
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
bookResult := models.NewBookResult().ToBookResult(*book)
|
||||
isOk := false
|
||||
|
@ -1264,13 +1251,13 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu
|
|||
c.SetSession(identify, token)
|
||||
} else if token, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(token, book.PrivateToken) {
|
||||
logs.Info("尝试访问文档但权限不足 ->", identify, token)
|
||||
c.ShowErrorPage(403, "权限不足")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
} else if password := c.GetString("bPassword", ""); !isOk && book.BookPassword != "" && password != "" {
|
||||
|
||||
//如果设置了密码,则判断密码是否正确
|
||||
if book.BookPassword != password {
|
||||
c.JsonResult(5001, "密码错误")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.wrong_password"))
|
||||
} else {
|
||||
c.SetSession(identify, password)
|
||||
c.JsonResult(0, "OK")
|
||||
|
@ -1289,7 +1276,7 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu
|
|||
}
|
||||
} else {
|
||||
logs.Info("尝试访问文档但权限不足 ->", identify, token)
|
||||
c.ShowErrorPage(403, "权限不足")
|
||||
c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1303,7 +1290,7 @@ func promptUserToLogIn(c *DocumentController) {
|
|||
logs.Info(" Access will be redirected to login page(SessionId: " + c.CruSession.SessionID(context.TODO()) + ").")
|
||||
|
||||
if c.IsAjax() {
|
||||
c.JsonResult(6000, "请重新登录。")
|
||||
c.JsonResult(6000, i18n.Tr(c.Lang, "message.need_relogin"))
|
||||
} else {
|
||||
c.Redirect(conf.URLFor("AccountController.Login")+"?url="+url.PathEscape(conf.BaseUrl+c.Ctx.Request.URL.RequestURI()), 302)
|
||||
}
|
||||
|
|
|
@ -28,14 +28,11 @@ func (c *HomeController) Index() {
|
|||
|
||||
pageIndex, _ := c.GetInt("page", 1)
|
||||
pageSize := 18
|
||||
|
||||
memberId := 0
|
||||
|
||||
if c.Member != nil {
|
||||
memberId = c.Member.MemberId
|
||||
}
|
||||
books, totalCount, err := models.NewBook().FindForHomeToPager(pageIndex, pageSize, memberId)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.Abort("500")
|
||||
|
@ -47,6 +44,5 @@ func (c *HomeController) Index() {
|
|||
c.Data["PageHtml"] = ""
|
||||
}
|
||||
c.Data["TotalPages"] = int(math.Ceil(float64(totalCount) / float64(pageSize)))
|
||||
|
||||
c.Data["Lists"] = books
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
"github.com/mindoc-org/mindoc/utils"
|
||||
|
@ -40,17 +41,17 @@ func (c *ManagerController) Index() {
|
|||
c.TplName = "manager/index.tpl"
|
||||
|
||||
c.Data["Model"] = models.NewDashboard().Query()
|
||||
c.Data["Action"] = "index"
|
||||
}
|
||||
|
||||
// 用户列表.
|
||||
func (c *ManagerController) Users() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/users.tpl"
|
||||
|
||||
c.Data["Action"] = "users"
|
||||
pageIndex, _ := c.GetInt("page", 0)
|
||||
|
||||
members, totalCount, err := models.NewMember().FindToPager(pageIndex, conf.PageSize)
|
||||
|
||||
if err != nil {
|
||||
c.Data["ErrorMessage"] = err.Error()
|
||||
return
|
||||
|
@ -68,7 +69,6 @@ func (c *ManagerController) Users() {
|
|||
}
|
||||
|
||||
b, err := json.Marshal(members)
|
||||
|
||||
if err != nil {
|
||||
c.Data["Result"] = template.JS("[]")
|
||||
} else {
|
||||
|
@ -89,16 +89,16 @@ func (c *ManagerController) CreateMember() {
|
|||
status, _ := c.GetInt("status", 0)
|
||||
|
||||
if ok, err := regexp.MatchString(conf.RegexpAccount, account); account == "" || !ok || err != nil {
|
||||
c.JsonResult(6001, "账号只能由英文字母数字组成,且在3-50个字符")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.username_invalid_format"))
|
||||
}
|
||||
if l := strings.Count(password1, ""); password1 == "" || l > 50 || l < 6 {
|
||||
c.JsonResult(6002, "密码必须在6-50个字符之间")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.pwd_length_tips"))
|
||||
}
|
||||
if password1 != password2 {
|
||||
c.JsonResult(6003, "确认密码不正确")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.wrong_confirm_pwd"))
|
||||
}
|
||||
if ok, err := regexp.MatchString(conf.RegexpEmail, email); !ok || err != nil || email == "" {
|
||||
c.JsonResult(6004, "邮箱格式不正确")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.email_invalid_format"))
|
||||
}
|
||||
if role != 0 && role != 1 && role != 2 {
|
||||
role = 1
|
||||
|
@ -110,7 +110,7 @@ func (c *ManagerController) CreateMember() {
|
|||
member := models.NewMember()
|
||||
|
||||
if _, err := member.FindByAccount(account); err == nil && member.MemberId > 0 {
|
||||
c.JsonResult(6005, "账号已存在")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.account_existed"))
|
||||
}
|
||||
|
||||
member.Account = account
|
||||
|
@ -139,7 +139,7 @@ func (c *ManagerController) UpdateMemberStatus() {
|
|||
status, _ := c.GetInt("status", 0)
|
||||
|
||||
if member_id <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
if status != 0 && status != 1 {
|
||||
status = 0
|
||||
|
@ -147,19 +147,19 @@ func (c *ManagerController) UpdateMemberStatus() {
|
|||
member := models.NewMember()
|
||||
|
||||
if _, err := member.Find(member_id); err != nil {
|
||||
c.JsonResult(6002, "用户不存在")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.user_not_existed"))
|
||||
}
|
||||
if member.MemberId == c.Member.MemberId {
|
||||
c.JsonResult(6004, "不能变更自己的状态")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.cannot_change_own_status"))
|
||||
}
|
||||
if member.Role == conf.MemberSuperRole {
|
||||
c.JsonResult(6005, "不能变更超级管理员的状态")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.cannot_change_super_status"))
|
||||
}
|
||||
member.Status = status
|
||||
|
||||
if err := member.Update(); err != nil {
|
||||
logs.Error("", err)
|
||||
c.JsonResult(6003, "用户状态设置失败")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok", member)
|
||||
}
|
||||
|
@ -171,27 +171,28 @@ func (c *ManagerController) ChangeMemberRole() {
|
|||
memberId, _ := c.GetInt("member_id", 0)
|
||||
role, _ := c.GetInt("role", 0)
|
||||
if memberId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
if role != int(conf.MemberAdminRole) && role != int(conf.MemberGeneralRole) {
|
||||
c.JsonResult(6001, "用户权限不正确")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
member := models.NewMember()
|
||||
|
||||
if _, err := member.Find(memberId); err != nil {
|
||||
c.JsonResult(6002, "用户不存在")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.user_not_existed"))
|
||||
}
|
||||
if member.MemberId == c.Member.MemberId {
|
||||
c.JsonResult(6004, "不能变更自己的权限")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.cannot_change_own_priv"))
|
||||
}
|
||||
if member.Role == conf.MemberSuperRole {
|
||||
c.JsonResult(6005, "不能变更超级管理员的权限")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.cannot_change_super_priv"))
|
||||
}
|
||||
member.Role = conf.SystemRole(role)
|
||||
|
||||
if err := member.Update(); err != nil {
|
||||
c.JsonResult(6003, "用户权限设置失败")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
member.Lang = c.Lang
|
||||
member.ResolveRoleName()
|
||||
c.JsonResult(0, "ok", member)
|
||||
}
|
||||
|
@ -200,7 +201,7 @@ func (c *ManagerController) ChangeMemberRole() {
|
|||
func (c *ManagerController) EditMember() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/edit_users.tpl"
|
||||
|
||||
c.Data["Action"] = "users"
|
||||
member_id, _ := c.GetInt(":id", 0)
|
||||
|
||||
if member_id <= 0 {
|
||||
|
@ -208,7 +209,6 @@ func (c *ManagerController) EditMember() {
|
|||
}
|
||||
|
||||
member, err := models.NewMember().Find(member_id)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.Abort("404")
|
||||
|
@ -224,7 +224,7 @@ func (c *ManagerController) EditMember() {
|
|||
member.Description = description
|
||||
member.RealName = c.GetString("real_name")
|
||||
if password1 != "" && password2 != password1 {
|
||||
c.JsonResult(6001, "确认密码不正确")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.wrong_confirm_pwd"))
|
||||
}
|
||||
if password1 != "" && member.AuthMethod != conf.AuthMethodLDAP {
|
||||
member.Password = password1
|
||||
|
@ -236,7 +236,7 @@ func (c *ManagerController) EditMember() {
|
|||
password, err := utils.PasswordHash(password1)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(6003, "对用户密码加密时出错")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.pwd_encrypt_failed"))
|
||||
}
|
||||
member.Password = password
|
||||
}
|
||||
|
@ -255,30 +255,28 @@ func (c *ManagerController) DeleteMember() {
|
|||
member_id, _ := c.GetInt("id", 0)
|
||||
|
||||
if member_id <= 0 {
|
||||
c.JsonResult(404, "参数错误")
|
||||
c.JsonResult(404, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
member, err := models.NewMember().Find(member_id)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(500, "用户不存在")
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.user_not_existed"))
|
||||
}
|
||||
if member.Role == conf.MemberSuperRole {
|
||||
c.JsonResult(500, "不能删除超级管理员")
|
||||
}
|
||||
superMember, err := models.NewMember().FindByFieldFirst("role", 0)
|
||||
|
||||
superMember, err := models.NewMember().FindByFieldFirst("role", 0)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(5001, "未能找到超级管理员")
|
||||
}
|
||||
|
||||
err = models.NewMember().Delete(member_id, superMember.MemberId)
|
||||
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
c.JsonResult(5002, "删除失败")
|
||||
c.JsonResult(5002, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok")
|
||||
}
|
||||
|
@ -287,7 +285,7 @@ func (c *ManagerController) DeleteMember() {
|
|||
func (c *ManagerController) Books() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/books.tpl"
|
||||
|
||||
c.Data["Action"] = "books"
|
||||
pageIndex, _ := c.GetInt("page", 1)
|
||||
|
||||
books, totalCount, err := models.NewBookResult().FindToPager(pageIndex, conf.PageSize)
|
||||
|
@ -318,7 +316,7 @@ func (c *ManagerController) EditBook() {
|
|||
c.Prepare()
|
||||
|
||||
c.TplName = "manager/edit_book.tpl"
|
||||
|
||||
c.Data["Action"] = "books"
|
||||
identify := c.GetString(":key")
|
||||
|
||||
if identify == "" {
|
||||
|
@ -328,8 +326,8 @@ func (c *ManagerController) EditBook() {
|
|||
if err != nil {
|
||||
c.Abort("500")
|
||||
}
|
||||
if c.Ctx.Input.IsPost() {
|
||||
|
||||
if c.Ctx.Input.IsPost() {
|
||||
bookName := strings.TrimSpace(c.GetString("book_name"))
|
||||
description := strings.TrimSpace(c.GetString("description", ""))
|
||||
commentStatus := c.GetString("comment_status")
|
||||
|
@ -344,7 +342,7 @@ func (c *ManagerController) EditBook() {
|
|||
itemId, _ := c.GetInt("itemId")
|
||||
|
||||
if strings.Count(description, "") > 500 {
|
||||
c.JsonResult(6004, "项目描述不能大于500字")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_desc_tips"))
|
||||
}
|
||||
if commentStatus != "open" && commentStatus != "closed" && commentStatus != "group_only" && commentStatus != "registered_only" {
|
||||
commentStatus = "closed"
|
||||
|
@ -356,7 +354,7 @@ func (c *ManagerController) EditBook() {
|
|||
}
|
||||
}
|
||||
if !models.NewItemsets().Exist(itemId) {
|
||||
c.JsonResult(6006, "项目空间不存在")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_space_not_exist"))
|
||||
}
|
||||
book.Publisher = publisher
|
||||
book.HistoryCount = historyCount
|
||||
|
@ -390,7 +388,7 @@ func (c *ManagerController) EditBook() {
|
|||
}
|
||||
|
||||
if err := book.Update(); err != nil {
|
||||
c.JsonResult(6006, "保存失败")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok")
|
||||
}
|
||||
|
@ -410,18 +408,18 @@ func (c *ManagerController) DeleteBook() {
|
|||
bookId, _ := c.GetInt("book_id", 0)
|
||||
|
||||
if bookId <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
book := models.NewBook()
|
||||
|
||||
err := book.ThoroughDeleteBook(bookId)
|
||||
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(6002, "项目不存在")
|
||||
c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
if err != nil {
|
||||
logs.Error("删除失败 -> ", err)
|
||||
c.JsonResult(6003, "删除失败")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok")
|
||||
}
|
||||
|
@ -436,7 +434,7 @@ func (c *ManagerController) CreateToken() {
|
|||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(6001, "项目不存在")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
if action == "create" {
|
||||
|
||||
|
@ -447,14 +445,14 @@ func (c *ManagerController) CreateToken() {
|
|||
book.PrivateToken = string(utils.Krand(conf.GetTokenSize(), utils.KC_RAND_KIND_ALL))
|
||||
if err := book.Update(); err != nil {
|
||||
logs.Error("生成阅读令牌失败 => ", err)
|
||||
c.JsonResult(6003, "生成阅读令牌失败")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok", conf.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken))
|
||||
} else {
|
||||
book.PrivateToken = ""
|
||||
if err := book.Update(); err != nil {
|
||||
logs.Error("CreateToken => ", err)
|
||||
c.JsonResult(6004, "删除令牌失败")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok", "")
|
||||
}
|
||||
|
@ -464,7 +462,7 @@ func (c *ManagerController) CreateToken() {
|
|||
func (c *ManagerController) Setting() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/setting.tpl"
|
||||
|
||||
c.Data["Action"] = "setting"
|
||||
options, err := models.NewOption().All()
|
||||
|
||||
if c.Ctx.Input.IsPost() {
|
||||
|
@ -483,7 +481,6 @@ func (c *ManagerController) Setting() {
|
|||
for _, item := range options {
|
||||
c.Data[item.OptionName] = item.OptionValue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Transfer 转让项目.
|
||||
|
@ -492,16 +489,16 @@ func (c *ManagerController) Transfer() {
|
|||
account := c.GetString("account")
|
||||
|
||||
if account == "" {
|
||||
c.JsonResult(6004, "接受者账号不能为空")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.receive_account_empty"))
|
||||
}
|
||||
member, err := models.NewMember().FindByAccount(account)
|
||||
|
||||
if err != nil {
|
||||
logs.Error("FindByAccount => ", err)
|
||||
c.JsonResult(6005, "接受用户不存在")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.receive_account_not_exist"))
|
||||
}
|
||||
if member.Status != 0 {
|
||||
c.JsonResult(6006, "接受用户已被禁用")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.receive_account_disabled"))
|
||||
}
|
||||
|
||||
if !c.Member.IsAdministrator() {
|
||||
|
@ -549,7 +546,7 @@ func (c *ManagerController) DeleteComment() {
|
|||
comment_id, _ := c.GetInt("comment_id", 0)
|
||||
|
||||
if comment_id <= 0 {
|
||||
c.JsonResult(6001, "参数错误")
|
||||
c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
comment := models.NewComment()
|
||||
|
@ -573,7 +570,7 @@ func (c *ManagerController) PrivatelyOwned() {
|
|||
identify := c.GetString("identify")
|
||||
|
||||
if status != "open" && status != "close" {
|
||||
c.JsonResult(6003, "参数错误")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
state := 0
|
||||
if status == "open" {
|
||||
|
@ -599,7 +596,7 @@ func (c *ManagerController) PrivatelyOwned() {
|
|||
|
||||
if err != nil {
|
||||
logs.Error("PrivatelyOwned => ", err)
|
||||
c.JsonResult(6004, "保存失败")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok")
|
||||
}
|
||||
|
@ -608,6 +605,7 @@ func (c *ManagerController) PrivatelyOwned() {
|
|||
func (c *ManagerController) AttachList() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/attach_list.tpl"
|
||||
c.Data["Action"] = "attach"
|
||||
|
||||
pageIndex, _ := c.GetInt("page", 1)
|
||||
|
||||
|
@ -638,14 +636,14 @@ func (c *ManagerController) AttachList() {
|
|||
func (c *ManagerController) AttachDetailed() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/attach_detailed.tpl"
|
||||
attach_id, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
c.Data["Action"] = "attach"
|
||||
|
||||
attach_id, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
if attach_id <= 0 {
|
||||
c.Abort("404")
|
||||
}
|
||||
|
||||
attach, err := models.NewAttachmentResult().Find(attach_id)
|
||||
|
||||
if err != nil {
|
||||
logs.Error("AttachDetailed => ", err)
|
||||
if err == orm.ErrNoRows {
|
||||
|
@ -690,11 +688,10 @@ func (c *ManagerController) AttachDelete() {
|
|||
func (c *ManagerController) LabelList() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/label_list.tpl"
|
||||
|
||||
c.Data["Action"] = "label"
|
||||
pageIndex, _ := c.GetInt("page", 1)
|
||||
|
||||
labels, totalCount, err := models.NewLabel().FindToPager(pageIndex, conf.PageSize)
|
||||
|
||||
if err != nil {
|
||||
c.ShowErrorPage(50001, err.Error())
|
||||
}
|
||||
|
@ -712,13 +709,12 @@ func (c *ManagerController) LabelList() {
|
|||
//删除标签
|
||||
func (c *ManagerController) LabelDelete() {
|
||||
labelId, err := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
|
||||
if err != nil {
|
||||
logs.Error("获取删除标签参数时出错:", err)
|
||||
c.JsonResult(50001, "参数错误")
|
||||
c.JsonResult(50001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
if labelId <= 0 {
|
||||
c.JsonResult(50001, "参数错误")
|
||||
c.JsonResult(50001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
label, err := models.NewLabel().FindFirst("label_id", labelId)
|
||||
|
@ -736,6 +732,7 @@ func (c *ManagerController) LabelDelete() {
|
|||
func (c *ManagerController) Config() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/config.tpl"
|
||||
c.Data["Action"] = "config"
|
||||
if c.Ctx.Input.IsPost() {
|
||||
content := strings.TrimSpace(c.GetString("configFileTextArea"))
|
||||
if content == "" {
|
||||
|
@ -773,11 +770,10 @@ func (c *ManagerController) Config() {
|
|||
func (c *ManagerController) Team() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/team.tpl"
|
||||
|
||||
c.Data["Action"] = "team"
|
||||
pageIndex, _ := c.GetInt("page", 0)
|
||||
|
||||
teams, totalCount, err := models.NewTeam().FindToPager(pageIndex, conf.PageSize)
|
||||
|
||||
if err != nil && err != orm.ErrNoRows {
|
||||
c.ShowErrorPage(500, err.Error())
|
||||
}
|
||||
|
@ -795,7 +791,6 @@ func (c *ManagerController) Team() {
|
|||
}
|
||||
|
||||
b, err := json.Marshal(teams)
|
||||
|
||||
if err != nil {
|
||||
c.Data["Result"] = template.JS("[]")
|
||||
} else {
|
||||
|
@ -809,7 +804,7 @@ func (c *ManagerController) TeamCreate() {
|
|||
teamName := c.GetString("teamName")
|
||||
|
||||
if teamName == "" {
|
||||
c.JsonResult(5001, "团队名称不能为空")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.team_name_empty"))
|
||||
}
|
||||
team := models.NewTeam()
|
||||
|
||||
|
@ -830,10 +825,10 @@ func (c *ManagerController) TeamEdit() {
|
|||
teamId, _ := c.GetInt("teamId")
|
||||
|
||||
if teamName == "" {
|
||||
c.JsonResult(5001, "团队名称不能为空")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.team_name_empty"))
|
||||
}
|
||||
if teamId <= 0 {
|
||||
c.JsonResult(5002, "团队标识不能为空")
|
||||
c.JsonResult(5002, i18n.Tr(c.Lang, "message.team_id_empty"))
|
||||
}
|
||||
team, err := models.NewTeam().First(teamId)
|
||||
|
||||
|
@ -846,19 +841,16 @@ func (c *ManagerController) TeamEdit() {
|
|||
c.CheckJsonError(5004, err)
|
||||
|
||||
c.JsonResult(0, "OK", team)
|
||||
|
||||
}
|
||||
|
||||
func (c *ManagerController) TeamDelete() {
|
||||
c.Prepare()
|
||||
|
||||
teamId, _ := c.GetInt("teamId")
|
||||
|
||||
if teamId <= 0 {
|
||||
c.JsonResult(5002, "团队标识不能为空")
|
||||
c.JsonResult(5002, i18n.Tr(c.Lang, "message.team_id_empty"))
|
||||
}
|
||||
err := models.NewTeam().Delete(teamId)
|
||||
|
||||
c.CheckJsonError(5001, err)
|
||||
|
||||
c.JsonResult(0, "OK")
|
||||
|
@ -867,23 +859,21 @@ func (c *ManagerController) TeamDelete() {
|
|||
func (c *ManagerController) TeamMemberList() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/team_member_list.tpl"
|
||||
c.Data["Action"] = "team"
|
||||
teamId, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
if teamId <= 0 {
|
||||
c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
pageIndex, _ := c.GetInt("page", 0)
|
||||
|
||||
if teamId <= 0 {
|
||||
c.ShowErrorPage(500, "参数错误")
|
||||
}
|
||||
|
||||
team, err := models.NewTeam().First(teamId)
|
||||
|
||||
if err == orm.ErrNoRows {
|
||||
c.ShowErrorPage(404, "团队不存在")
|
||||
}
|
||||
c.CheckErrorResult(500, err)
|
||||
c.Data["Model"] = team
|
||||
|
||||
teams, totalCount, err := models.NewTeamMember().FindToPager(teamId, pageIndex, conf.PageSize)
|
||||
|
||||
teams, totalCount, err := models.NewTeamMember().SetLang(c.Lang).FindToPager(teamId, pageIndex, conf.PageSize)
|
||||
if err != nil && err != orm.ErrNoRows {
|
||||
c.ShowErrorPage(500, err.Error())
|
||||
}
|
||||
|
@ -901,7 +891,6 @@ func (c *ManagerController) TeamMemberList() {
|
|||
}
|
||||
|
||||
b, err := json.Marshal(teams)
|
||||
|
||||
if err != nil {
|
||||
logs.Error("编码 JSON 结果失败 ->", err)
|
||||
c.Data["Result"] = template.JS("[]")
|
||||
|
@ -918,7 +907,7 @@ func (c *ManagerController) TeamSearchMember() {
|
|||
keyword := strings.TrimSpace(c.GetString("q"))
|
||||
|
||||
if teamId <= 0 {
|
||||
c.JsonResult(500, "参数错误")
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
searchResult, err := models.NewTeamMember().FindNotJoinMemberByAccount(teamId, keyword, 10)
|
||||
|
@ -936,7 +925,7 @@ func (c *ManagerController) TeamMemberAdd() {
|
|||
roleId, _ := c.GetInt("roleId")
|
||||
|
||||
if teamId <= 0 || memberId <= 0 || roleId <= 0 || roleId > int(conf.BookObserver) {
|
||||
c.JsonResult(5001, "参数不正确")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.system_error"))
|
||||
}
|
||||
|
||||
teamMember := models.NewTeamMember()
|
||||
|
@ -965,7 +954,7 @@ func (c *ManagerController) TeamMemberDelete() {
|
|||
}
|
||||
err = teamMember.Delete(teamMember.TeamMemberId)
|
||||
if err != nil {
|
||||
c.JsonResult(5002, "删除失败")
|
||||
c.JsonResult(5002, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "ok")
|
||||
}
|
||||
|
@ -976,7 +965,7 @@ func (c *ManagerController) TeamChangeMemberRole() {
|
|||
roleId, _ := c.GetInt("roleId")
|
||||
teamId, _ := c.GetInt("teamId")
|
||||
if memberId <= 0 || roleId <= 0 || teamId <= 0 || roleId > int(conf.BookObserver) {
|
||||
c.JsonResult(5001, "参数错误")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
teamMember, err := models.NewTeamMember().ChangeRoleId(teamId, memberId, conf.BookRole(roleId))
|
||||
|
@ -993,12 +982,12 @@ func (c *ManagerController) TeamChangeMemberRole() {
|
|||
func (c *ManagerController) TeamBookList() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/team_book_list.tpl"
|
||||
|
||||
c.Data["Action"] = "team"
|
||||
teamId, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||
pageIndex, _ := c.GetInt("page", 0)
|
||||
|
||||
if teamId <= 0 {
|
||||
c.JsonResult(5002, "团队标识不能为空")
|
||||
c.JsonResult(5002, i18n.Tr(c.Lang, "message.team_id_empty"))
|
||||
}
|
||||
|
||||
team, err := models.NewTeam().First(teamId)
|
||||
|
@ -1028,7 +1017,6 @@ func (c *ManagerController) TeamBookList() {
|
|||
}
|
||||
|
||||
b, err := json.Marshal(teams)
|
||||
|
||||
if err != nil {
|
||||
logs.Error("编码 JSON 结果失败 ->", err)
|
||||
c.Data["Result"] = template.JS("[]")
|
||||
|
@ -1045,7 +1033,7 @@ func (c *ManagerController) TeamBookAdd() {
|
|||
bookId, _ := c.GetInt("bookId")
|
||||
|
||||
if teamId <= 0 || bookId <= 0 {
|
||||
c.JsonResult(500, "参数错误")
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
teamRel := models.NewTeamRelationship()
|
||||
teamRel.BookId = bookId
|
||||
|
@ -1069,7 +1057,7 @@ func (c *ManagerController) TeamSearchBook() {
|
|||
keyword := strings.TrimSpace(c.GetString("q"))
|
||||
|
||||
if teamId <= 0 {
|
||||
c.JsonResult(500, "参数错误")
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
searchResult, err := models.NewTeamRelationship().FindNotJoinBookByName(teamId, keyword, 10)
|
||||
|
@ -1087,13 +1075,13 @@ func (c *ManagerController) TeamBookDelete() {
|
|||
teamRelationshipId, _ := c.GetInt("teamRelId")
|
||||
|
||||
if teamRelationshipId <= 0 {
|
||||
c.JsonResult(500, "参数错误")
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
err := models.NewTeamRelationship().Delete(teamRelationshipId)
|
||||
|
||||
if err != nil {
|
||||
c.JsonResult(5001, "删除失败")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.failed"))
|
||||
}
|
||||
c.JsonResult(0, "OK")
|
||||
}
|
||||
|
@ -1102,6 +1090,7 @@ func (c *ManagerController) TeamBookDelete() {
|
|||
func (c *ManagerController) Itemsets() {
|
||||
c.Prepare()
|
||||
c.TplName = "manager/itemsets.tpl"
|
||||
c.Data["Action"] = "itemsets"
|
||||
pageIndex, _ := c.GetInt("page", 0)
|
||||
|
||||
items, totalCount, err := models.NewItemsets().FindToPager(pageIndex, conf.PageSize)
|
||||
|
@ -1123,7 +1112,6 @@ func (c *ManagerController) Itemsets() {
|
|||
}
|
||||
|
||||
c.Data["Lists"] = items
|
||||
|
||||
}
|
||||
|
||||
//编辑或添加项目空间.
|
||||
|
@ -1133,14 +1121,14 @@ func (c *ManagerController) ItemsetsEdit() {
|
|||
itemName := strings.TrimSpace(c.GetString("itemName"))
|
||||
itemKey := strings.TrimSpace(c.GetString("itemKey"))
|
||||
if itemName == "" || itemKey == "" {
|
||||
c.JsonResult(5001, "参数错误")
|
||||
c.JsonResult(5001, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
var item *models.Itemsets
|
||||
var err error
|
||||
if itemId > 0 {
|
||||
if item, err = models.NewItemsets().First(itemId); err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
c.JsonResult(5002, "项目空间不存在")
|
||||
c.JsonResult(5002, i18n.Tr(c.Lang, "message.project_space_not_exist"))
|
||||
} else {
|
||||
c.JsonResult(5003, "查询项目空间出错")
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
"github.com/mindoc-org/mindoc/utils"
|
||||
|
@ -87,16 +88,16 @@ func (c *SearchController) User() {
|
|||
key := c.Ctx.Input.Param(":key")
|
||||
keyword := strings.TrimSpace(c.GetString("q"))
|
||||
if key == "" || keyword == "" {
|
||||
c.JsonResult(404, "参数错误")
|
||||
c.JsonResult(404, i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
keyword = sqltil.EscapeLike(keyword)
|
||||
|
||||
book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId)
|
||||
if err != nil {
|
||||
if err == models.ErrPermissionDenied {
|
||||
c.JsonResult(403, "没有权限")
|
||||
c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission"))
|
||||
}
|
||||
c.JsonResult(500, "项目不存在")
|
||||
c.JsonResult(500, i18n.Tr(c.Lang, "message.item_not_exist"))
|
||||
}
|
||||
|
||||
//members, err := models.NewMemberRelationshipResult().FindNotJoinUsersByAccount(book.BookId, 10, "%"+keyword+"%")
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/graphics"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
|
@ -28,7 +29,7 @@ func (c *SettingController) Index() {
|
|||
description := strings.TrimSpace(c.GetString("description"))
|
||||
|
||||
if email == "" {
|
||||
c.JsonResult(601, "邮箱不能为空")
|
||||
c.JsonResult(601, i18n.Tr(c.Lang, "message.email_empty"))
|
||||
}
|
||||
member := c.Member
|
||||
member.Email = email
|
||||
|
@ -48,34 +49,34 @@ func (c *SettingController) Password() {
|
|||
|
||||
if c.Ctx.Input.IsPost() {
|
||||
if c.Member.AuthMethod == conf.AuthMethodLDAP {
|
||||
c.JsonResult(6009, "当前用户不支持修改密码")
|
||||
c.JsonResult(6009, i18n.Tr(c.Lang, "message.cur_user_cannot_change_pwd"))
|
||||
}
|
||||
password1 := c.GetString("password1")
|
||||
password2 := c.GetString("password2")
|
||||
password3 := c.GetString("password3")
|
||||
|
||||
if password1 == "" {
|
||||
c.JsonResult(6003, "原密码不能为空")
|
||||
c.JsonResult(6003, i18n.Tr(c.Lang, "message.origin_pwd_empty"))
|
||||
}
|
||||
|
||||
if password2 == "" {
|
||||
c.JsonResult(6004, "新密码不能为空")
|
||||
c.JsonResult(6004, i18n.Tr(c.Lang, "message.new_pwd_empty"))
|
||||
}
|
||||
if count := strings.Count(password2, ""); count < 6 || count > 18 {
|
||||
c.JsonResult(6009, "密码必须在6-18字之间")
|
||||
c.JsonResult(6009, i18n.Tr(c.Lang, "message.pwd_length"))
|
||||
}
|
||||
if password2 != password3 {
|
||||
c.JsonResult(6003, "确认密码不正确")
|
||||
}
|
||||
if ok, _ := utils.PasswordVerify(c.Member.Password, password1); !ok {
|
||||
c.JsonResult(6005, "原始密码不正确")
|
||||
c.JsonResult(6005, i18n.Tr(c.Lang, "message.wrong_origin_pwd"))
|
||||
}
|
||||
if password1 == password2 {
|
||||
c.JsonResult(6006, "新密码不能和原始密码相同")
|
||||
c.JsonResult(6006, i18n.Tr(c.Lang, "message.same_pwd"))
|
||||
}
|
||||
pwd, err := utils.PasswordHash(password2)
|
||||
if err != nil {
|
||||
c.JsonResult(6007, "密码加密失败")
|
||||
c.JsonResult(6007, i18n.Tr(c.Lang, "message.pwd_encrypt_failed"))
|
||||
}
|
||||
c.Member.Password = pwd
|
||||
if err := c.Member.Update(); err != nil {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/models"
|
||||
)
|
||||
|
@ -20,7 +21,7 @@ func (c *TemplateController) isPermission() error {
|
|||
bookIdentify := c.GetString("identify", "")
|
||||
|
||||
if bookIdentify == "" {
|
||||
return errors.New("参数错误")
|
||||
return errors.New(i18n.Tr(c.Lang, "message.param_error"))
|
||||
}
|
||||
|
||||
if !c.Member.IsAdministrator() {
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
MinDoc_New:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/mindoc/mindoc:v2.0-beta.2
|
||||
privileged: false
|
||||
restart: always
|
||||
ports:
|
||||
- 8181:8181
|
||||
volumes:
|
||||
- /var/www/mindoc/database:/mindoc/database
|
||||
- /var/www/mindoc/uploads:/mindoc/uploads
|
||||
environment:
|
||||
- MINDOC_RUN_MODE=prod
|
||||
- MINDOC_DB_ADAPTER=sqlite3
|
||||
- MINDOC_DB_DATABASE=./database/mindoc.db
|
||||
- MINDOC_CACHE=true
|
||||
- MINDOC_CACHE_PROVIDER=file
|
||||
- MINDOC_ENABLE_EXPORT=false
|
||||
- MINDOC_BASE_URL=
|
||||
- MINDOC_CDN_IMG_URL=
|
||||
- MINDOC_CDN_CSS_URL=
|
||||
- MINDOC_CDN_JS_URL=
|
||||
dns:
|
||||
- 223.5.5.5
|
||||
- 223.6.6.6
|
||||
version: "3"
|
||||
services:
|
||||
mindoc:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/mindoc-org/mindoc:v2.1-beta.5
|
||||
container_name: mindoc
|
||||
privileged: false
|
||||
restart: always
|
||||
ports:
|
||||
- 8181:8181
|
||||
volumes:
|
||||
- /var/www/mindoc://mindoc-sync-host
|
||||
environment:
|
||||
- MINDOC_RUN_MODE=prod
|
||||
- MINDOC_DB_ADAPTER=sqlite3
|
||||
- MINDOC_DB_DATABASE=./database/mindoc.db
|
||||
- MINDOC_CACHE=true
|
||||
- MINDOC_CACHE_PROVIDER=file
|
||||
- MINDOC_ENABLE_EXPORT=false
|
||||
- MINDOC_BASE_URL=
|
||||
- MINDOC_CDN_IMG_URL=
|
||||
- MINDOC_CDN_CSS_URL=
|
||||
- MINDOC_CDN_JS_URL=
|
||||
dns:
|
||||
- 223.5.5.5
|
||||
- 223.6.6.6
|
||||
|
|
4
go.mod
4
go.mod
|
@ -4,17 +4,21 @@ go 1.13
|
|||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.4.1
|
||||
github.com/Unknwon/goconfig v0.0.0-20200908083735-df7de6a44db8 // indirect
|
||||
github.com/andybalholm/cascadia v1.2.0 // indirect
|
||||
github.com/beego/beego/v2 v2.0.2-0.20210322114547-10ea897525a5
|
||||
github.com/beego/i18n v0.0.0-20161101132742-e9308947f407
|
||||
github.com/boombuler/barcode v1.0.0
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
|
||||
github.com/howeyc/fsnotify v0.9.0
|
||||
github.com/kardianos/service v1.1.0
|
||||
github.com/lib/pq v1.7.0 // indirect
|
||||
github.com/lifei6671/gocaptcha v0.1.1
|
||||
github.com/mattn/go-runewidth v0.0.13
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/russross/blackfriday/v2 v2.1.0
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-00010101000000-000000000000 // indirect
|
||||
gopkg.in/ldap.v2 v2.5.1
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
|
|
17
go.sum
17
go.sum
|
@ -3,6 +3,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/PuerkitoBio/goquery v1.4.1 h1:smcIRGdYm/w7JSbcdeLHEMzxmsBQvl8lhf0dSw2nzMI=
|
||||
github.com/PuerkitoBio/goquery v1.4.1/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA=
|
||||
github.com/Unknwon/goconfig v0.0.0-20200908083735-df7de6a44db8 h1:1TrMV1HmBApBbM+Hy7RCKZD6UlYWYIPPfoeXomG7+zE=
|
||||
github.com/Unknwon/goconfig v0.0.0-20200908083735-df7de6a44db8/go.mod h1:wngxua9XCNjvHjDiTiV26DaKDT+0c63QR6H5hjVUUxw=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
|
@ -14,6 +16,8 @@ github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxB
|
|||
github.com/beego/beego/v2 v2.0.2-0.20210322114547-10ea897525a5 h1:i0swsv6hmoF6pkeG2S/dvOWwOKFPGDKhrmTlWH6I1nM=
|
||||
github.com/beego/beego/v2 v2.0.2-0.20210322114547-10ea897525a5/go.mod h1:JlRUJ/NVNygorqjyt7/lQ8R++KSE0qXvxeIfbnIUd7Q=
|
||||
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
||||
github.com/beego/i18n v0.0.0-20161101132742-e9308947f407 h1:WtJfx5HqASTQp7HfiZldnin8KQV2futplF3duGp5PGc=
|
||||
github.com/beego/i18n v0.0.0-20161101132742-e9308947f407/go.mod h1:KLeFCpAMq2+50NkXC8iiJxLLiiTfTqrGtKEVm+2fk7s=
|
||||
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
|
@ -92,6 +96,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
|
@ -101,6 +107,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
|||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kardianos/service v1.1.0 h1:QV2SiEeWK42P0aEmGcsAgjApw/lRxkwopvT+Gu6t1/0=
|
||||
github.com/kardianos/service v1.1.0/go.mod h1:RrJI2xn5vve/r32U5suTbeaSGoMU6GbNPoj36CVYcHc=
|
||||
|
@ -118,6 +126,8 @@ github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
|
|||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lifei6671/gocaptcha v0.1.1 h1:5cvU3w0bK8eJm1P6AiQoPuicoZVAgKKpREBxXF9IaHo=
|
||||
github.com/lifei6671/gocaptcha v0.1.1/go.mod h1:6QlTU2WzFhzqylAJWSo3OANfKCraGccJwbK01P5fFmI=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
|
@ -166,6 +176,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
|
|||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
|
@ -176,6 +188,10 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz
|
|||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
@ -254,6 +270,7 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm
|
|||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
|
@ -18,6 +18,8 @@ func ImageCopy(src image.Image, x, y, w, h int) (image.Image, error) {
|
|||
subImg = rgbImg.SubImage(image.Rect(x, y, x+w, y+h)).(*image.RGBA) //图片裁剪x0 y0 x1 y1
|
||||
} else if rgbImg, ok := src.(*image.NRGBA); ok {
|
||||
subImg = rgbImg.SubImage(image.Rect(x, y, x+w, y+h)).(*image.NRGBA) //图片裁剪x0 y0 x1 y1
|
||||
} else if rgbImg, ok := src.(*image.Paletted); ok {
|
||||
subImg = rgbImg.SubImage(image.Rect(x, y, x+w, y+h)).(*image.Paletted) //图片裁剪x0 y0 x1 y1
|
||||
} else {
|
||||
|
||||
return subImg, errors.New("图片解码失败")
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/utils"
|
||||
"github.com/mindoc-org/mindoc/utils/cryptil"
|
||||
|
@ -115,7 +116,7 @@ func NewBook() *Book {
|
|||
}
|
||||
|
||||
//添加一个项目
|
||||
func (book *Book) Insert() error {
|
||||
func (book *Book) Insert(lang string) error {
|
||||
o := orm.NewOrm()
|
||||
// o.Begin()
|
||||
book.BookName = utils.StripTags(book.BookName)
|
||||
|
@ -141,7 +142,7 @@ func (book *Book) Insert() error {
|
|||
}
|
||||
document := NewDocument()
|
||||
document.BookId = book.BookId
|
||||
document.DocumentName = "空白文档"
|
||||
document.DocumentName = i18n.Tr(lang, "init.blank_doc") //"空白文档"
|
||||
document.MemberId = book.MemberId
|
||||
err = document.InsertOrUpdate()
|
||||
if err != nil {
|
||||
|
@ -362,7 +363,7 @@ func (book *Book) FindByIdentify(identify string, cols ...string) (*Book, error)
|
|||
}
|
||||
|
||||
//分页查询指定用户的项目
|
||||
func (book *Book) FindToPager(pageIndex, pageSize, memberId int) (books []*BookResult, totalCount int, err error) {
|
||||
func (book *Book) FindToPager(pageIndex, pageSize, memberId int, lang string) (books []*BookResult, totalCount int, err error) {
|
||||
|
||||
o := orm.NewOrm()
|
||||
|
||||
|
@ -430,13 +431,13 @@ ORDER BY book.order_index, book.book_id DESC limit ?,?`
|
|||
books[index].LastModifyText = text.Account + " 于 " + text.ModifyTime.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
if book.RoleId == 0 {
|
||||
book.RoleName = "创始人"
|
||||
book.RoleName = i18n.Tr(lang, "common.creator")
|
||||
} else if book.RoleId == 1 {
|
||||
book.RoleName = "管理员"
|
||||
book.RoleName = i18n.Tr(lang, "common.administrator")
|
||||
} else if book.RoleId == 2 {
|
||||
book.RoleName = "编辑者"
|
||||
book.RoleName = i18n.Tr(lang, "common.editor")
|
||||
} else if book.RoleId == 3 {
|
||||
book.RoleName = "观察者"
|
||||
book.RoleName = i18n.Tr(lang, "common.observer")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -631,7 +632,7 @@ WHERE (relationship_id > 0 OR book.privately_owned = 0 or team.team_member_id >
|
|||
}
|
||||
|
||||
// ReleaseContent 批量发布文档
|
||||
func (book *Book) ReleaseContent(bookId int) {
|
||||
func (book *Book) ReleaseContent(bookId int, lang string) {
|
||||
releaseQueue <- bookId
|
||||
once.Do(func() {
|
||||
go func() {
|
||||
|
@ -652,6 +653,7 @@ func (book *Book) ReleaseContent(bookId int) {
|
|||
}
|
||||
for _, item := range docs {
|
||||
item.BookId = bookId
|
||||
item.Lang = lang
|
||||
_ = item.ReleaseContent()
|
||||
}
|
||||
|
||||
|
@ -678,8 +680,8 @@ func (book *Book) ResetDocumentNumber(bookId int) {
|
|||
}
|
||||
}
|
||||
|
||||
//导入项目
|
||||
func (book *Book) ImportBook(zipPath string) error {
|
||||
// 导入zip项目
|
||||
func (book *Book) ImportBook(zipPath string, lang string) error {
|
||||
if !filetil.FileExists(zipPath) {
|
||||
return errors.New("文件不存在 => " + zipPath)
|
||||
}
|
||||
|
@ -972,7 +974,79 @@ func (book *Book) ImportBook(zipPath string) error {
|
|||
book.Description = "【项目导入存在错误:" + err.Error() + "】"
|
||||
}
|
||||
logs.Info("项目导入完毕 => ", book.BookName)
|
||||
book.ReleaseContent(book.BookId)
|
||||
book.ReleaseContent(book.BookId, lang)
|
||||
return err
|
||||
}
|
||||
|
||||
// 导入docx项目
|
||||
func (book *Book) ImportWordBook(docxPath string, lang string) (err error) {
|
||||
if !filetil.FileExists(docxPath) {
|
||||
return errors.New("文件不存在")
|
||||
}
|
||||
docxPath = strings.Replace(docxPath, "\\", "/", -1)
|
||||
|
||||
o := orm.NewOrm()
|
||||
|
||||
o.Insert(book)
|
||||
relationship := NewRelationship()
|
||||
relationship.BookId = book.BookId
|
||||
relationship.RoleId = 0
|
||||
relationship.MemberId = book.MemberId
|
||||
err = relationship.Insert()
|
||||
if err != nil {
|
||||
logs.Error("插入项目与用户关联 -> ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
doc := NewDocument()
|
||||
doc.BookId = book.BookId
|
||||
doc.MemberId = book.MemberId
|
||||
docIdentify := strings.Replace(strings.TrimPrefix(docxPath, os.TempDir()+"/"), "/", "-", -1)
|
||||
|
||||
if ok, err := regexp.MatchString(`[a-z]+[a-zA-Z0-9_.\-]*$`, docIdentify); !ok || err != nil {
|
||||
docIdentify = "import-" + docIdentify
|
||||
}
|
||||
|
||||
doc.Identify = docIdentify
|
||||
|
||||
if doc.Markdown, err = utils.Docx2md(docxPath, false); err != nil {
|
||||
logs.Error("导入doc项目转换异常 => ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// fmt.Println("===doc.Markdown===")
|
||||
// fmt.Println(doc.Markdown)
|
||||
// fmt.Println("==================")
|
||||
|
||||
doc.Content = string(blackfriday.Run([]byte(doc.Markdown)))
|
||||
|
||||
// fmt.Println("===doc.Content===")
|
||||
// fmt.Println(doc.Content)
|
||||
// fmt.Println("==================")
|
||||
|
||||
doc.Version = time.Now().Unix()
|
||||
|
||||
var docName string
|
||||
for _, line := range strings.Split(doc.Markdown, "\n") {
|
||||
if strings.HasPrefix(line, "#") {
|
||||
docName = strings.TrimLeft(line, "#")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
doc.DocumentName = strings.TrimSpace(docName)
|
||||
|
||||
doc.DocumentId = book.MemberId
|
||||
|
||||
if err := doc.InsertOrUpdate("document_name", "book_id", "markdown", "content"); err != nil {
|
||||
logs.Error(doc.DocumentId, err)
|
||||
}
|
||||
if err != nil {
|
||||
logs.Error("导入项目异常 => ", err)
|
||||
book.Description = "【项目导入存在错误:" + err.Error() + "】"
|
||||
}
|
||||
logs.Info("项目导入完毕 => ", book.BookName)
|
||||
book.ReleaseContent(book.BookId, lang)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/converter"
|
||||
"github.com/mindoc-org/mindoc/utils/cryptil"
|
||||
|
@ -70,6 +71,7 @@ type BookResult struct {
|
|||
IsDisplayComment bool `json:"is_display_comment"`
|
||||
IsDownload bool `json:"is_download"`
|
||||
AutoSave bool `json:"auto_save"`
|
||||
Lang string
|
||||
}
|
||||
|
||||
func NewBookResult() *BookResult {
|
||||
|
@ -85,6 +87,11 @@ func (m *BookResult) String() string {
|
|||
return string(ret)
|
||||
}
|
||||
|
||||
func (m *BookResult) SetLang(lang string) *BookResult {
|
||||
m.Lang = lang
|
||||
return m
|
||||
}
|
||||
|
||||
// 根据项目标识查询项目以及指定用户权限的信息.
|
||||
func (m *BookResult) FindByIdentify(identify string, memberId int) (*BookResult, error) {
|
||||
if identify == "" || memberId <= 0 {
|
||||
|
@ -131,13 +138,13 @@ func (m *BookResult) FindByIdentify(identify string, memberId int) (*BookResult,
|
|||
}
|
||||
|
||||
if m.RoleId == conf.BookFounder {
|
||||
m.RoleName = "创始人"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.creator")
|
||||
} else if m.RoleId == conf.BookAdmin {
|
||||
m.RoleName = "管理员"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.administrator")
|
||||
} else if m.RoleId == conf.BookEditor {
|
||||
m.RoleName = "编辑者"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.editor")
|
||||
} else if m.RoleId == conf.BookObserver {
|
||||
m.RoleName = "观察者"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.observer")
|
||||
}
|
||||
|
||||
doc := NewDocument()
|
||||
|
|
|
@ -3,6 +3,8 @@ package models
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/beego/i18n"
|
||||
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
|
@ -44,6 +46,8 @@ type Document struct {
|
|||
IsOpen int `orm:"column(is_open);type(int);default(0)" json:"is_open"`
|
||||
ViewCount int `orm:"column(view_count);type(int)" json:"view_count"`
|
||||
AttachList []*Attachment `orm:"-" json:"attach"`
|
||||
//i18n
|
||||
Lang string `orm:"-"`
|
||||
}
|
||||
|
||||
// 多字段唯一键
|
||||
|
@ -276,7 +280,7 @@ func (item *Document) Processor() *Document {
|
|||
//处理附件
|
||||
attachList, err := NewAttachment().FindListByDocumentId(item.DocumentId)
|
||||
if err == nil && len(attachList) > 0 {
|
||||
content := bytes.NewBufferString("<div class=\"attach-list\"><strong>附件</strong><ul>")
|
||||
content := bytes.NewBufferString("<div class=\"attach-list\"><strong>" + i18n.Tr(item.Lang, "doc.attachment") + "</strong><ul>")
|
||||
for _, attach := range attachList {
|
||||
if strings.HasPrefix(attach.HttpPath, "/") {
|
||||
attach.HttpPath = strings.TrimSuffix(conf.BaseUrl, "/") + attach.HttpPath
|
||||
|
@ -306,7 +310,7 @@ func (item *Document) Processor() *Document {
|
|||
docCreator, err := NewMember().Find(item.MemberId, "real_name", "account")
|
||||
release := "<div class=\"wiki-bottom\">"
|
||||
|
||||
release += "作者:"
|
||||
release += i18n.Tr(item.Lang, "doc.ft_author")
|
||||
if err == nil && docCreator != nil {
|
||||
if docCreator.RealName != "" {
|
||||
release += docCreator.RealName
|
||||
|
@ -314,19 +318,19 @@ func (item *Document) Processor() *Document {
|
|||
release += docCreator.Account
|
||||
}
|
||||
}
|
||||
release += " 创建时间:" + item.CreateTime.Local().Format("2006-01-02 15:04") + "<br>"
|
||||
release += " " + i18n.Tr(item.Lang, "doc.ft_create_time") + item.CreateTime.Local().Format("2006-01-02 15:04") + "<br>"
|
||||
|
||||
if item.ModifyAt > 0 {
|
||||
docModify, err := NewMember().Find(item.ModifyAt, "real_name", "account")
|
||||
if err == nil {
|
||||
if docModify.RealName != "" {
|
||||
release += "最后编辑:" + docModify.RealName
|
||||
release += i18n.Tr(item.Lang, "doc.ft_last_editor") + docModify.RealName
|
||||
} else {
|
||||
release += "最后编辑:" + docModify.Account
|
||||
release += i18n.Tr(item.Lang, "doc.ft_last_editor") + docModify.Account
|
||||
}
|
||||
}
|
||||
}
|
||||
release += " 更新时间:" + item.ModifyTime.Local().Format("2006-01-02 15:04") + "<br>"
|
||||
release += " " + i18n.Tr(item.Lang, "doc.ft_update_time") + item.ModifyTime.Local().Format("2006-01-02 15:04") + "<br>"
|
||||
release += "</div>"
|
||||
|
||||
if selector := docQuery.Find("div.markdown-article").First(); selector.Size() > 0 {
|
||||
|
@ -335,7 +339,7 @@ func (item *Document) Processor() *Document {
|
|||
selector.First().AppendHtml(release)
|
||||
}
|
||||
}
|
||||
cdnimg,_ := web.AppConfig.String("cdnimg")
|
||||
cdnimg, _ := web.AppConfig.String("cdnimg")
|
||||
|
||||
docQuery.Find("img").Each(func(i int, selection *goquery.Selection) {
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/utils"
|
||||
)
|
||||
|
@ -44,6 +45,8 @@ type Member struct {
|
|||
CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"`
|
||||
CreateAt int `orm:"type(int);column(create_at)" json:"create_at"`
|
||||
LastLoginTime time.Time `orm:"type(datetime);column(last_login_time);null" json:"last_login_time"`
|
||||
//i18n
|
||||
Lang string `orm:"-"`
|
||||
}
|
||||
|
||||
// TableName 获取对应数据库表名.
|
||||
|
@ -327,11 +330,11 @@ func (m *Member) Find(id int, cols ...string) (*Member, error) {
|
|||
|
||||
func (m *Member) ResolveRoleName() {
|
||||
if m.Role == conf.MemberSuperRole {
|
||||
m.RoleName = "超级管理员"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.administrator")
|
||||
} else if m.Role == conf.MemberAdminRole {
|
||||
m.RoleName = "管理员"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.editor")
|
||||
} else if m.Role == conf.MemberGeneralRole {
|
||||
m.RoleName = "普通用户"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.obverser")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
)
|
||||
|
||||
|
@ -54,19 +55,19 @@ func (m *MemberRelationshipResult) FromMember(member *Member) *MemberRelationshi
|
|||
return m
|
||||
}
|
||||
|
||||
func (m *MemberRelationshipResult) ResolveRoleName() *MemberRelationshipResult {
|
||||
func (m *MemberRelationshipResult) ResolveRoleName(lang string) *MemberRelationshipResult {
|
||||
if m.RoleId == conf.BookAdmin {
|
||||
m.RoleName = "管理者"
|
||||
m.RoleName = i18n.Tr(lang, "common.administrator")
|
||||
} else if m.RoleId == conf.BookEditor {
|
||||
m.RoleName = "编辑者"
|
||||
m.RoleName = i18n.Tr(lang, "common.editor")
|
||||
} else if m.RoleId == conf.BookObserver {
|
||||
m.RoleName = "观察者"
|
||||
m.RoleName = i18n.Tr(lang, "common.obverser")
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// 根据项目ID查询用户
|
||||
func (m *MemberRelationshipResult) FindForUsersByBookId(bookId, pageIndex, pageSize int) ([]*MemberRelationshipResult, int, error) {
|
||||
func (m *MemberRelationshipResult) FindForUsersByBookId(lang string, bookId, pageIndex, pageSize int) ([]*MemberRelationshipResult, int, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
var members []*MemberRelationshipResult
|
||||
|
@ -92,7 +93,7 @@ func (m *MemberRelationshipResult) FindForUsersByBookId(bookId, pageIndex, pageS
|
|||
}
|
||||
|
||||
for _, item := range members {
|
||||
item.ResolveRoleName()
|
||||
item.ResolveRoleName(lang)
|
||||
}
|
||||
return members, total_count, nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
)
|
||||
|
||||
|
@ -18,6 +19,7 @@ type TeamMember struct {
|
|||
Account string `orm:"-" json:"account"`
|
||||
RealName string `orm:"-" json:"real_name"`
|
||||
Avatar string `orm:"-" json:"avatar"`
|
||||
Lang string `orm:"-"`
|
||||
}
|
||||
|
||||
// TableName 获取对应数据库表名.
|
||||
|
@ -46,6 +48,11 @@ func NewTeamMember() *TeamMember {
|
|||
return &TeamMember{}
|
||||
}
|
||||
|
||||
func (m *TeamMember) SetLang(lang string) *TeamMember {
|
||||
m.Lang = lang
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *TeamMember) First(id int, cols ...string) (*TeamMember, error) {
|
||||
if id <= 0 {
|
||||
return nil, errors.New("参数错误")
|
||||
|
@ -173,6 +180,7 @@ func (m *TeamMember) FindToPager(teamId, pageIndex, pageSize int) (list []*TeamM
|
|||
|
||||
//将来优化
|
||||
for _, item := range list {
|
||||
item.Lang = m.Lang
|
||||
item.Include()
|
||||
}
|
||||
return
|
||||
|
@ -187,13 +195,13 @@ func (m *TeamMember) Include() *TeamMember {
|
|||
m.Avatar = member.Avatar
|
||||
}
|
||||
if m.RoleId == 0 {
|
||||
m.RoleName = "创始人"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.creator") //"创始人"
|
||||
} else if m.RoleId == 1 {
|
||||
m.RoleName = "管理员"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.administrator") //"管理员"
|
||||
} else if m.RoleId == 2 {
|
||||
m.RoleName = "编辑者"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.editor") //"编辑者"
|
||||
} else if m.RoleId == 3 {
|
||||
m.RoleName = "观察者"
|
||||
m.RoleName = i18n.Tr(m.Lang, "common.observer") //"观察者"
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
|
|
@ -1,11 +1,82 @@
|
|||
package routers
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/beego/v2/server/web/context"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/controllers"
|
||||
)
|
||||
|
||||
func rt(req *http.Request) (*http.Response, error) {
|
||||
log.Printf("request received. url=%s", req.URL)
|
||||
// req.Header.Set("Host", "httpbin.org") // <--- I set it here as well
|
||||
defer log.Printf("request complete. url=%s", req.URL)
|
||||
|
||||
return http.DefaultTransport.RoundTrip(req)
|
||||
}
|
||||
|
||||
// roundTripper makes func signature a http.RoundTripper
|
||||
type roundTripper func(*http.Request) (*http.Response, error)
|
||||
|
||||
func (f roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return f(req) }
|
||||
|
||||
type CorsTransport struct {
|
||||
http.RoundTripper
|
||||
}
|
||||
|
||||
func (t *CorsTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
||||
// refer:
|
||||
// - https://stackoverflow.com/questions/31535569/golang-how-to-read-response-body-of-reverseproxy/31536962#31536962
|
||||
// - https://gist.github.com/simon-cj/b4da0b2bca793ec3b8a5abe04c8fca41
|
||||
resp, err = t.RoundTripper.RoundTrip(req)
|
||||
logs.Debug(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Header.Del("Access-Control-Request-Method")
|
||||
resp.Header.Set("Access-Control-Allow-Origin", "*")
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
web.Any("/cors-anywhere", func(ctx *context.Context) {
|
||||
u, _ := url.PathUnescape(ctx.Input.Query("url"))
|
||||
logs.Error("ReverseProxy: ", u)
|
||||
if len(u) > 0 && strings.HasPrefix(u, "http") {
|
||||
if strings.TrimRight(conf.BaseUrl, "/") == ctx.Input.Site() {
|
||||
ctx.Redirect(302, u)
|
||||
} else {
|
||||
target, _ := url.Parse(u)
|
||||
logs.Debug("target: ", target)
|
||||
|
||||
proxy := &httputil.ReverseProxy{
|
||||
Transport: roundTripper(rt),
|
||||
Director: func(req *http.Request) {
|
||||
req.Header = ctx.Request.Header
|
||||
req.URL.Scheme = target.Scheme
|
||||
req.URL.Host = target.Host
|
||||
req.URL.Path = target.Path
|
||||
req.Header.Set("Host", target.Host)
|
||||
},
|
||||
}
|
||||
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
proxy.ServeHTTP(ctx.ResponseWriter, ctx.Request)
|
||||
}
|
||||
} else {
|
||||
ctx.ResponseWriter.WriteHeader(http.StatusBadRequest)
|
||||
ctx.Output.Body([]byte("400 Bad Request"))
|
||||
}
|
||||
})
|
||||
|
||||
web.Router("/", &controllers.HomeController{}, "*:Index")
|
||||
|
||||
web.Router("/login", &controllers.AccountController{}, "*:Login")
|
||||
|
|
44
start.sh
44
start.sh
|
@ -1,12 +1,36 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
cd /mindoc/
|
||||
|
||||
if [ ! -f "/mindoc/conf/app.conf" ] ; then
|
||||
cp /mindoc/conf/app.conf.example /mindoc/conf/app.conf
|
||||
fi
|
||||
|
||||
export ZONEINFO=/mindoc/lib/time/zoneinfo.zip
|
||||
# 数据库等初始化
|
||||
/mindoc/mindoc_linux_amd64 install
|
||||
exec /mindoc/mindoc_linux_amd64
|
||||
|
||||
# 导出同步检查
|
||||
mkdir -p /mindoc-sync-host
|
||||
if ! [ -f "/mindoc-sync-host/sync.sh" ]; then
|
||||
# 同步方向: docker->HOST 或 HOST -> docker
|
||||
# echo "export MINDOC_SYNC=" >> /mindoc-sync-host/sync.sh # 不同步
|
||||
echo "export MINDOC_SYNC=docker2host" >> /mindoc-sync-host/sync.sh # 默认 docker->HOST
|
||||
|
||||
# 同步内容
|
||||
# conf: 配置
|
||||
# database: sqlite方式数据库
|
||||
# runtime: 运行时数据(日志等)
|
||||
# static: 静态文件
|
||||
# uploads: 上传文件
|
||||
# views: 页面视图
|
||||
# echo "export SYNC_LIST='conf;database;runtime;static;uploads;views'" >> /mindoc-sync-host/sync.sh # 同步所有内容
|
||||
# echo "export SYNC_LIST=" >> /mindoc-sync-host/sync.sh # 不同步任何内容
|
||||
echo "export SYNC_LIST='conf;database;uploads'" >> /mindoc-sync-host/sync.sh # 同步conf、database、uploads
|
||||
|
||||
# 同步操作(sync/copy/sync --dry-run 等,具体参考rclone文档,host2docker务必谨慎操作)
|
||||
# echo "export SYNC_ACTION=sync --dry-run" >> /mindoc-sync-host/sync.sh # 无操作且仅显示同步文件信息(--dry-run)
|
||||
echo "export SYNC_ACTION=sync" >> /mindoc-sync-host/sync.sh # 默认同步
|
||||
|
||||
# 同步脚本
|
||||
echo "source /mindoc/sync_host.sh" >> /mindoc-sync-host/sync.sh
|
||||
fi
|
||||
# 同步操作
|
||||
source /mindoc-sync-host/sync.sh
|
||||
|
||||
# 运行
|
||||
/mindoc/mindoc_linux_amd64
|
|
@ -265,7 +265,7 @@ table>tbody>tr:hover{
|
|||
right: 0;
|
||||
overflow-y: auto;
|
||||
background-color: #fafafa;
|
||||
margin-bottom: 35px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.m-manual .manual-tab .tab-item.active {
|
||||
|
@ -1173,4 +1173,4 @@ table>tbody>tr:hover{
|
|||
opacity: .3;
|
||||
z-index: 3000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ body{
|
|||
bottom: 0;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid #DDDDDD;
|
||||
z-index: 999;
|
||||
}
|
||||
.manual-editor-container .manual-editormd{
|
||||
position: absolute;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Editor.md
|
||||
*
|
||||
* @file editormd.js
|
||||
* @version v1.5.0
|
||||
* @file editormd.js
|
||||
* @version v1.5.0
|
||||
* @description Open source online markdown editor.
|
||||
* @license MIT License
|
||||
* @author Pandao
|
||||
|
@ -170,6 +170,7 @@
|
|||
flowChart : false, // flowChart.js only support IE9+
|
||||
sequenceDiagram : false, // sequenceDiagram.js only support IE9+
|
||||
mermaid : true,
|
||||
mindMap : true, // 脑图
|
||||
previewCodeHighlight : true,
|
||||
|
||||
toolbar : true, // show/hide toolbar
|
||||
|
@ -511,48 +512,45 @@
|
|||
|
||||
|
||||
if (settings.mermaid) {
|
||||
editormd.loadCSS(loadPath + "mermaid/mermaid", function () {
|
||||
editormd.loadScript(loadPath + "mermaid/mermaid.min", function () {
|
||||
window.mermaid.initialize({
|
||||
theme: 'default',
|
||||
startOnLoad:true,
|
||||
cloneCssStyles: true,
|
||||
flowchart: {
|
||||
htmlLabels: false,
|
||||
useMaxWidth:false
|
||||
},
|
||||
});
|
||||
mermaid.ganttConfig = {
|
||||
axisFormatter: [
|
||||
// Within a day
|
||||
['%I:%M', function (d) {
|
||||
return d.getHours();
|
||||
}],
|
||||
// Monday a week
|
||||
['%m/%d', function (d) { // redefine date here as '%m/%d'instead of 'w. %U', search mermaid.js
|
||||
return d.getDay() == 1;
|
||||
}],
|
||||
// Day within a week (not monday)
|
||||
['%a %d', function (d) {
|
||||
return d.getDay() && d.getDate() != 1;
|
||||
}],
|
||||
// within a month
|
||||
['%b %d', function (d) {
|
||||
return d.getDate() != 1;
|
||||
}],
|
||||
// Month
|
||||
['%m-%y', function (d) {
|
||||
return d.getMonth();
|
||||
}],[ "%m-%Y", function () {
|
||||
return d.getFullYear();
|
||||
}]]
|
||||
};
|
||||
|
||||
if (!isLoadedDisplay){
|
||||
isLoadedDisplay = true;
|
||||
_this.loadedDisplay();
|
||||
}
|
||||
editormd.loadScript(loadPath + "mermaid/mermaid.min", function () {
|
||||
window.mermaid.initialize({
|
||||
theme: 'default',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
flowchart: { curve: 'basis' },
|
||||
gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50 },
|
||||
});
|
||||
mermaid.ganttConfig = {
|
||||
axisFormatter: [
|
||||
// Within a day
|
||||
['%I:%M', function (d) {
|
||||
return d.getHours();
|
||||
}],
|
||||
// Monday a week
|
||||
['%m/%d', function (d) { // redefine date here as '%m/%d'instead of 'w. %U', search mermaid.js
|
||||
return d.getDay() == 1;
|
||||
}],
|
||||
// Day within a week (not monday)
|
||||
['%a %d', function (d) {
|
||||
return d.getDay() && d.getDate() != 1;
|
||||
}],
|
||||
// within a month
|
||||
['%b %d', function (d) {
|
||||
return d.getDate() != 1;
|
||||
}],
|
||||
// Month
|
||||
['%m-%y', function (d) {
|
||||
return d.getMonth();
|
||||
}],[ "%m-%Y", function () {
|
||||
return d.getFullYear();
|
||||
}]]
|
||||
};
|
||||
|
||||
if (!isLoadedDisplay){
|
||||
isLoadedDisplay = true;
|
||||
_this.loadedDisplay();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (settings.flowChart)
|
||||
|
@ -569,6 +567,20 @@
|
|||
});
|
||||
}
|
||||
|
||||
if (settings.mindMap)
|
||||
{
|
||||
editormd.loadScript(loadPath + "mindmap/transform.min", function() {
|
||||
editormd.loadScript(loadPath + "mindmap/d3@5", function() {
|
||||
editormd.loadScript(loadPath + "mindmap/view.min", function() {
|
||||
if (!isLoadedDisplay){
|
||||
isLoadedDisplay = true;
|
||||
_this.loadedDisplay();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if(settings.sequenceDiagram) {
|
||||
editormd.loadCSS(loadPath + "sequence/sequence-diagram-min", function () {
|
||||
editormd.loadScript(loadPath + "sequence/webfont", function() {
|
||||
|
@ -1560,6 +1572,22 @@
|
|||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 解析思维导图 - 2020-04-12
|
||||
*
|
||||
* @returns {editormd} 返回editormd的实例对象
|
||||
*/
|
||||
mindmapRender:function(){
|
||||
this.previewContainer.find(".mindmap").each(function(){
|
||||
var mmap = $(this);
|
||||
var md_data = window.markmap.transform(mmap.text().trim());
|
||||
window.markmap.markmap("svg#"+this.id,md_data)
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* 解析和渲染流程图及时序图
|
||||
* FlowChart and SequenceDiagram Renderer
|
||||
|
@ -2069,6 +2097,7 @@
|
|||
sequenceDiagram : settings.sequenceDiagram,
|
||||
previewCodeHighlight : settings.previewCodeHighlight,
|
||||
mermaid : settings.mermaid,
|
||||
mindMap : settings.mindMap, // 思维导图
|
||||
};
|
||||
|
||||
var markedOptions = this.markedOptions = {
|
||||
|
@ -2150,6 +2179,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
// 渲染脑图
|
||||
if(settings.mindMap){
|
||||
setTimeout(function(){
|
||||
_this.mindmapRender();
|
||||
},10)
|
||||
|
||||
}
|
||||
|
||||
if (settings.flowChart || settings.sequenceDiagram || settings.mermaid)
|
||||
{
|
||||
flowchartTimer = setTimeout(function(){
|
||||
|
@ -3539,7 +3576,7 @@
|
|||
ext : ".png"
|
||||
};
|
||||
|
||||
// Twitter Emoji (Twemoji) graphics files url path
|
||||
// Twitter Emoji (Twemoji) graphics files url path
|
||||
editormd.twemoji = {
|
||||
path : "http://twemoji.maxcdn.com/36x36/",
|
||||
ext : ".png"
|
||||
|
@ -3896,6 +3933,23 @@
|
|||
{
|
||||
return "<p class=\"" + editormd.classNames.tex + "\">" + code + "</p>";
|
||||
}
|
||||
else if (/^mindmap/i.test(lang)){
|
||||
var len = 9 || 32;
|
||||
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
||||
var maxPos = $chars.length;
|
||||
var map_id = '';
|
||||
var custom_height;
|
||||
var h = lang.split('>')[1];
|
||||
if (h != undefined) {
|
||||
custom_height = h;
|
||||
} else {
|
||||
custom_height = 150;
|
||||
}
|
||||
for (var i = 0; i < len; i++) {
|
||||
map_id += $chars.charAt(Math.floor(Math.random() * maxPos));
|
||||
}
|
||||
return "<svg class='mindmap' style='width:100%;min-height=150px;height:"+custom_height+"px;' id='mindmap-"+ map_id +"'>"+code+"</svg>";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
@ -4183,6 +4237,7 @@
|
|||
sequenceDiagram : false,
|
||||
previewCodeHighlight : true,
|
||||
mermaid : true,
|
||||
mindMap : true, //思维导图
|
||||
};
|
||||
|
||||
editormd.$marked = marked;
|
||||
|
@ -4213,6 +4268,7 @@
|
|||
flowChart : settings.flowChart,
|
||||
sequenceDiagram : settings.sequenceDiagram,
|
||||
mermaid : settings.mermaid,
|
||||
mindMap : settings.mindMap, // 思维导图
|
||||
previewCodeHighlight : settings.previewCodeHighlight,
|
||||
};
|
||||
|
||||
|
@ -4307,6 +4363,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
// 前台渲染脑图
|
||||
if(settings.mindMap){
|
||||
var mindmapHandle = function(){
|
||||
div.find(".mindmap").each(function(){
|
||||
var mmap = $(this);
|
||||
var md_data = window.markmap.transform(mmap.text().trim());
|
||||
window.markmap.markmap("svg#"+this.id,md_data)
|
||||
});
|
||||
}
|
||||
mindmapHandle();
|
||||
}
|
||||
|
||||
div.getMarkdown = function() {
|
||||
return saveTo.val();
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,273 +0,0 @@
|
|||
/* Flowchart variables */
|
||||
/* Sequence Diagram variables */
|
||||
/* Gantt chart variables */
|
||||
.lang-mermaid .mermaid .label {
|
||||
color: #333;
|
||||
}
|
||||
.lang-mermaid .node rect,
|
||||
.lang-mermaid .node circle,
|
||||
.lang-mermaid .node ellipse,
|
||||
.lang-mermaid .node polygon {
|
||||
fill: #ECECFF;
|
||||
stroke: #CCCCFF;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
.lang-mermaid .edgePath .path {
|
||||
stroke: #333333;
|
||||
}
|
||||
.lang-mermaid .edgeLabel {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
.lang-mermaid .cluster rect {
|
||||
fill: #ffffde !important;
|
||||
rx: 4 !important;
|
||||
stroke: #aaaa33 !important;
|
||||
stroke-width: 1px !important;
|
||||
}
|
||||
.lang-mermaid .cluster text {
|
||||
fill: #333;
|
||||
}
|
||||
.lang-mermaid .actor {
|
||||
stroke: #CCCCFF;
|
||||
fill: #ECECFF;
|
||||
}
|
||||
.lang-mermaid text.actor {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
}
|
||||
.lang-mermaid .actor-line {
|
||||
stroke: grey;
|
||||
}
|
||||
.lang-mermaid .messageLine0 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: "2 2";
|
||||
marker-end: "url(#arrowhead)";
|
||||
stroke: #333;
|
||||
}
|
||||
.lang-mermaid .messageLine1 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: "2 2";
|
||||
stroke: #333;
|
||||
}
|
||||
.lang-mermaid #arrowhead {
|
||||
fill: #333;
|
||||
}
|
||||
.lang-mermaid #crosshead path {
|
||||
fill: #333 !important;
|
||||
stroke: #333 !important;
|
||||
}
|
||||
.lang-mermaid .messageText {
|
||||
fill: #333;
|
||||
stroke: none;
|
||||
}
|
||||
.lang-mermaid .labelBox {
|
||||
stroke: #CCCCFF;
|
||||
fill: #ECECFF;
|
||||
}
|
||||
.lang-mermaid .labelText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
}
|
||||
.lang-mermaid .loopText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
}
|
||||
.lang-mermaid .loopLine {
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: "2 2";
|
||||
marker-end: "url(#arrowhead)";
|
||||
stroke: #CCCCFF;
|
||||
}
|
||||
.lang-mermaid .note {
|
||||
stroke: #aaaa33;
|
||||
fill: #fff5ad;
|
||||
}
|
||||
.lang-mermaid .noteText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
/** Section styling */
|
||||
.lang-mermaid .section {
|
||||
stroke: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.lang-mermaid .section0 {
|
||||
fill: rgba(102, 102, 255, 0.49);
|
||||
}
|
||||
.lang-mermaid .section2 {
|
||||
fill: #fff400;
|
||||
}
|
||||
.lang-mermaid .section1,
|
||||
.section3 {
|
||||
fill: white;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.lang-mermaid .sectionTitle0 {
|
||||
fill: #333;
|
||||
}
|
||||
.lang-mermaid .sectionTitle1 {
|
||||
fill: #333;
|
||||
}
|
||||
.lang-mermaid .sectionTitle2 {
|
||||
fill: #333;
|
||||
}
|
||||
.lang-mermaid .sectionTitle3 {
|
||||
fill: #333;
|
||||
}
|
||||
.lang-mermaid .sectionTitle {
|
||||
text-anchor: start;
|
||||
font-size: 11px;
|
||||
text-height: 14px;
|
||||
}
|
||||
/* Grid and axis */
|
||||
.lang-mermaid .grid .tick {
|
||||
stroke: lightgrey;
|
||||
opacity: 0.3;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.lang-mermaid .grid path {
|
||||
stroke-width: 0;
|
||||
}
|
||||
/* Today line */
|
||||
.lang-mermaid .today {
|
||||
fill: none;
|
||||
stroke: red;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
/* Task styling */
|
||||
/* Default task */
|
||||
.lang-mermaid .task {
|
||||
stroke-width: 2;
|
||||
}
|
||||
.lang-mermaid .taskText {
|
||||
text-anchor: middle;
|
||||
font-size: 11px;
|
||||
}
|
||||
.lang-mermaid .taskTextOutsideRight {
|
||||
fill: black;
|
||||
text-anchor: start;
|
||||
font-size: 11px;
|
||||
}
|
||||
.lang-mermaid .taskTextOutsideLeft {
|
||||
fill: black;
|
||||
text-anchor: end;
|
||||
font-size: 11px;
|
||||
}
|
||||
/* Specific task settings for the sections*/
|
||||
.lang-mermaid .taskText0,
|
||||
.lang-mermaid .taskText1,
|
||||
.lang-mermaid .taskText2,
|
||||
.lang-mermaid .taskText3 {
|
||||
fill: white;
|
||||
}
|
||||
.lang-mermaid .task0,
|
||||
.lang-mermaid .task1,
|
||||
.lang-mermaid .task2,
|
||||
.lang-mermaid .task3 {
|
||||
fill: #8a90dd;
|
||||
stroke: #534fbc;
|
||||
}
|
||||
.lang-mermaid .taskTextOutside0,
|
||||
.lang-mermaid .taskTextOutside2 {
|
||||
fill: black;
|
||||
}
|
||||
.lang-mermaid .taskTextOutside1,
|
||||
.lang-mermaid .taskTextOutside3 {
|
||||
fill: black;
|
||||
}
|
||||
/* Active task */
|
||||
.lang-mermaid .active0,
|
||||
.lang-mermaid .active1,
|
||||
.lang-mermaid .active2,
|
||||
.lang-mermaid .active3 {
|
||||
fill: #bfc7ff;
|
||||
stroke: #534fbc;
|
||||
}
|
||||
.lang-mermaid .activeText0,
|
||||
.lang-mermaid .activeText1,
|
||||
.lang-mermaid .activeText2,
|
||||
.lang-mermaid .activeText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
/* Completed task */
|
||||
.lang-mermaid .done0,
|
||||
.lang-mermaid .done1,
|
||||
.lang-mermaid .done2,
|
||||
.lang-mermaid .done3 {
|
||||
stroke: grey;
|
||||
fill: lightgrey;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.lang-mermaid .doneText0,
|
||||
.lang-mermaid .doneText1,
|
||||
.lang-mermaid .doneText2,
|
||||
.lang-mermaid .doneText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
/* Tasks on the critical line */
|
||||
.lang-mermaid .crit0,
|
||||
.lang-mermaid .crit1,
|
||||
.lang-mermaid .crit2,
|
||||
.lang-mermaid .crit3 {
|
||||
stroke: #ff8888;
|
||||
fill: red;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.lang-mermaid .activeCrit0,
|
||||
.lang-mermaid .activeCrit1,
|
||||
.lang-mermaid .activeCrit2,
|
||||
.lang-mermaid .activeCrit3 {
|
||||
stroke: #ff8888;
|
||||
fill: #bfc7ff;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.lang-mermaid .doneCrit0,
|
||||
.lang-mermaid .doneCrit1,
|
||||
.lang-mermaid .doneCrit2,
|
||||
.lang-mermaid .doneCrit3 {
|
||||
stroke: #ff8888;
|
||||
fill: lightgrey;
|
||||
stroke-width: 2;
|
||||
cursor: pointer;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.lang-mermaid .doneCritText0,
|
||||
.lang-mermaid .doneCritText1,
|
||||
.lang-mermaid .doneCritText2,
|
||||
.lang-mermaid .doneCritText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
.lang-mermaid .activeCritText0,
|
||||
.lang-mermaid .activeCritText1,
|
||||
.lang-mermaid .activeCritText2,
|
||||
.lang-mermaid .activeCritText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
.lang-mermaid .titleText {
|
||||
text-anchor: middle;
|
||||
font-size: 18px;
|
||||
fill: black;
|
||||
}
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
.lang-mermaid .node text {
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
.lang-mermaid div.mermaidTooltip {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
max-width: 200px;
|
||||
padding: 2px;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 12px;
|
||||
background: #ffffde;
|
||||
border: 1px solid #aaaa33;
|
||||
border-radius: 2px;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
}
|
|
@ -1,275 +0,0 @@
|
|||
/* Flowchart variables */
|
||||
/* Sequence Diagram variables */
|
||||
/* Gantt chart variables */
|
||||
.mermaid .label {
|
||||
color: #323D47;
|
||||
}
|
||||
.node rect,
|
||||
.node circle,
|
||||
.node ellipse,
|
||||
.node polygon {
|
||||
fill: #BDD5EA;
|
||||
stroke: #81B1DB;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
.edgePath .path {
|
||||
stroke: lightgrey;
|
||||
}
|
||||
.edgeLabel {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
.cluster rect {
|
||||
fill: #6D6D65 !important;
|
||||
rx: 4 !important;
|
||||
stroke: rgba(255, 255, 255, 0.25) !important;
|
||||
stroke-width: 1px !important;
|
||||
}
|
||||
.cluster text {
|
||||
fill: #F9FFFE;
|
||||
}
|
||||
.actor {
|
||||
stroke: #81B1DB;
|
||||
fill: #BDD5EA;
|
||||
}
|
||||
text.actor {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
}
|
||||
.actor-line {
|
||||
stroke: lightgrey;
|
||||
}
|
||||
.messageLine0 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: "2 2";
|
||||
marker-end: "url(#arrowhead)";
|
||||
stroke: lightgrey;
|
||||
}
|
||||
.messageLine1 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: "2 2";
|
||||
stroke: lightgrey;
|
||||
}
|
||||
#arrowhead {
|
||||
fill: lightgrey !important;
|
||||
}
|
||||
#crosshead path {
|
||||
fill: lightgrey !important;
|
||||
stroke: lightgrey !important;
|
||||
}
|
||||
.messageText {
|
||||
fill: lightgrey;
|
||||
stroke: none;
|
||||
}
|
||||
.labelBox {
|
||||
stroke: #81B1DB;
|
||||
fill: #BDD5EA;
|
||||
}
|
||||
.labelText {
|
||||
fill: #323D47;
|
||||
stroke: none;
|
||||
}
|
||||
.loopText {
|
||||
fill: lightgrey;
|
||||
stroke: none;
|
||||
}
|
||||
.loopLine {
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: "2 2";
|
||||
marker-end: "url(#arrowhead)";
|
||||
stroke: #81B1DB;
|
||||
}
|
||||
.note {
|
||||
stroke: rgba(255, 255, 255, 0.25);
|
||||
fill: #fff5ad;
|
||||
}
|
||||
.noteText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
/** Section styling */
|
||||
.section {
|
||||
stroke: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.section0 {
|
||||
fill: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
.section2 {
|
||||
fill: #EAE8B9;
|
||||
}
|
||||
.section1,
|
||||
.section3 {
|
||||
fill: white;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.sectionTitle0 {
|
||||
fill: #F9FFFE;
|
||||
}
|
||||
.sectionTitle1 {
|
||||
fill: #F9FFFE;
|
||||
}
|
||||
.sectionTitle2 {
|
||||
fill: #F9FFFE;
|
||||
}
|
||||
.sectionTitle3 {
|
||||
fill: #F9FFFE;
|
||||
}
|
||||
.sectionTitle {
|
||||
text-anchor: start;
|
||||
font-size: 11px;
|
||||
text-height: 14px;
|
||||
}
|
||||
/* Grid and axis */
|
||||
.grid .tick {
|
||||
stroke: rgba(255, 255, 255, 0.3);
|
||||
opacity: 0.3;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.grid .tick text {
|
||||
fill: lightgrey;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.grid path {
|
||||
stroke-width: 0;
|
||||
}
|
||||
/* Today line */
|
||||
.today {
|
||||
fill: none;
|
||||
stroke: #DB5757;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
/* Task styling */
|
||||
/* Default task */
|
||||
.task {
|
||||
stroke-width: 1;
|
||||
}
|
||||
.taskText {
|
||||
text-anchor: middle;
|
||||
font-size: 11px;
|
||||
}
|
||||
.taskTextOutsideRight {
|
||||
fill: #323D47;
|
||||
text-anchor: start;
|
||||
font-size: 11px;
|
||||
}
|
||||
.taskTextOutsideLeft {
|
||||
fill: #323D47;
|
||||
text-anchor: end;
|
||||
font-size: 11px;
|
||||
}
|
||||
/* Specific task settings for the sections*/
|
||||
.taskText0,
|
||||
.taskText1,
|
||||
.taskText2,
|
||||
.taskText3 {
|
||||
fill: #323D47;
|
||||
}
|
||||
.task0,
|
||||
.task1,
|
||||
.task2,
|
||||
.task3 {
|
||||
fill: #BDD5EA;
|
||||
stroke: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.taskTextOutside0,
|
||||
.taskTextOutside2 {
|
||||
fill: lightgrey;
|
||||
}
|
||||
.taskTextOutside1,
|
||||
.taskTextOutside3 {
|
||||
fill: lightgrey;
|
||||
}
|
||||
/* Active task */
|
||||
.active0,
|
||||
.active1,
|
||||
.active2,
|
||||
.active3 {
|
||||
fill: #81B1DB;
|
||||
stroke: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.activeText0,
|
||||
.activeText1,
|
||||
.activeText2,
|
||||
.activeText3 {
|
||||
fill: #323D47 !important;
|
||||
}
|
||||
/* Completed task */
|
||||
.done0,
|
||||
.done1,
|
||||
.done2,
|
||||
.done3 {
|
||||
fill: lightgrey;
|
||||
}
|
||||
.doneText0,
|
||||
.doneText1,
|
||||
.doneText2,
|
||||
.doneText3 {
|
||||
fill: #323D47 !important;
|
||||
}
|
||||
/* Tasks on the critical line */
|
||||
.crit0,
|
||||
.crit1,
|
||||
.crit2,
|
||||
.crit3 {
|
||||
stroke: #E83737;
|
||||
fill: #E83737;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.activeCrit0,
|
||||
.activeCrit1,
|
||||
.activeCrit2,
|
||||
.activeCrit3 {
|
||||
stroke: #E83737;
|
||||
fill: #81B1DB;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.doneCrit0,
|
||||
.doneCrit1,
|
||||
.doneCrit2,
|
||||
.doneCrit3 {
|
||||
stroke: #E83737;
|
||||
fill: lightgrey;
|
||||
stroke-width: 1;
|
||||
cursor: pointer;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.doneCritText0,
|
||||
.doneCritText1,
|
||||
.doneCritText2,
|
||||
.doneCritText3 {
|
||||
fill: lightgrey !important;
|
||||
}
|
||||
.activeCritText0,
|
||||
.activeCritText1,
|
||||
.activeCritText2,
|
||||
.activeCritText3 {
|
||||
fill: #323D47 !important;
|
||||
}
|
||||
.titleText {
|
||||
text-anchor: middle;
|
||||
font-size: 18px;
|
||||
fill: lightgrey;
|
||||
}
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
.node text {
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
div.mermaidTooltip {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
max-width: 200px;
|
||||
padding: 2px;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 12px;
|
||||
background: #6D6D65;
|
||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||
border-radius: 2px;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
}
|
|
@ -1,353 +0,0 @@
|
|||
/* Flowchart variables */
|
||||
/* Sequence Diagram variables */
|
||||
/* Gantt chart variables */
|
||||
.mermaid .label {
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
color: #333;
|
||||
}
|
||||
.node rect,
|
||||
.node circle,
|
||||
.node ellipse,
|
||||
.node polygon {
|
||||
fill: #cde498;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
.edgePath .path {
|
||||
stroke: green;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
.edgeLabel {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
.cluster rect {
|
||||
fill: #cdffb2 !important;
|
||||
rx: 4 !important;
|
||||
stroke: #6eaa49 !important;
|
||||
stroke-width: 1px !important;
|
||||
}
|
||||
.cluster text {
|
||||
fill: #333;
|
||||
}
|
||||
.actor {
|
||||
stroke: #13540c;
|
||||
fill: #cde498;
|
||||
}
|
||||
text.actor {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
}
|
||||
.actor-line {
|
||||
stroke: grey;
|
||||
}
|
||||
.messageLine0 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: "2 2";
|
||||
marker-end: "url(#arrowhead)";
|
||||
stroke: #333;
|
||||
}
|
||||
.messageLine1 {
|
||||
stroke-width: 1.5;
|
||||
stroke-dasharray: "2 2";
|
||||
stroke: #333;
|
||||
}
|
||||
#arrowhead {
|
||||
fill: #333;
|
||||
}
|
||||
#crosshead path {
|
||||
fill: #333 !important;
|
||||
stroke: #333 !important;
|
||||
}
|
||||
.messageText {
|
||||
fill: #333;
|
||||
stroke: none;
|
||||
}
|
||||
.labelBox {
|
||||
stroke: #326932;
|
||||
fill: #cde498;
|
||||
}
|
||||
.labelText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
}
|
||||
.loopText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
}
|
||||
.loopLine {
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: "2 2";
|
||||
marker-end: "url(#arrowhead)";
|
||||
stroke: #326932;
|
||||
}
|
||||
.note {
|
||||
stroke: #6eaa49;
|
||||
fill: #fff5ad;
|
||||
}
|
||||
.noteText {
|
||||
fill: black;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
/** Section styling */
|
||||
.section {
|
||||
stroke: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.section0 {
|
||||
fill: #6eaa49;
|
||||
}
|
||||
.section2 {
|
||||
fill: #6eaa49;
|
||||
}
|
||||
.section1,
|
||||
.section3 {
|
||||
fill: white;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.sectionTitle0 {
|
||||
fill: #333;
|
||||
}
|
||||
.sectionTitle1 {
|
||||
fill: #333;
|
||||
}
|
||||
.sectionTitle2 {
|
||||
fill: #333;
|
||||
}
|
||||
.sectionTitle3 {
|
||||
fill: #333;
|
||||
}
|
||||
.sectionTitle {
|
||||
text-anchor: start;
|
||||
font-size: 11px;
|
||||
text-height: 14px;
|
||||
}
|
||||
/* Grid and axis */
|
||||
.grid .tick {
|
||||
stroke: lightgrey;
|
||||
opacity: 0.3;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.grid path {
|
||||
stroke-width: 0;
|
||||
}
|
||||
/* Today line */
|
||||
.today {
|
||||
fill: none;
|
||||
stroke: red;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
/* Task styling */
|
||||
/* Default task */
|
||||
.task {
|
||||
stroke-width: 2;
|
||||
}
|
||||
.taskText {
|
||||
text-anchor: middle;
|
||||
font-size: 11px;
|
||||
}
|
||||
.taskTextOutsideRight {
|
||||
fill: black;
|
||||
text-anchor: start;
|
||||
font-size: 11px;
|
||||
}
|
||||
.taskTextOutsideLeft {
|
||||
fill: black;
|
||||
text-anchor: end;
|
||||
font-size: 11px;
|
||||
}
|
||||
/* Specific task settings for the sections*/
|
||||
.taskText0,
|
||||
.taskText1,
|
||||
.taskText2,
|
||||
.taskText3 {
|
||||
fill: white;
|
||||
}
|
||||
.task0,
|
||||
.task1,
|
||||
.task2,
|
||||
.task3 {
|
||||
fill: #487e3a;
|
||||
stroke: #13540c;
|
||||
}
|
||||
.taskTextOutside0,
|
||||
.taskTextOutside2 {
|
||||
fill: black;
|
||||
}
|
||||
.taskTextOutside1,
|
||||
.taskTextOutside3 {
|
||||
fill: black;
|
||||
}
|
||||
/* Active task */
|
||||
.active0,
|
||||
.active1,
|
||||
.active2,
|
||||
.active3 {
|
||||
fill: #cde498;
|
||||
stroke: #13540c;
|
||||
}
|
||||
.activeText0,
|
||||
.activeText1,
|
||||
.activeText2,
|
||||
.activeText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
/* Completed task */
|
||||
.done0,
|
||||
.done1,
|
||||
.done2,
|
||||
.done3 {
|
||||
stroke: grey;
|
||||
fill: lightgrey;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.doneText0,
|
||||
.doneText1,
|
||||
.doneText2,
|
||||
.doneText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
/* Tasks on the critical line */
|
||||
.crit0,
|
||||
.crit1,
|
||||
.crit2,
|
||||
.crit3 {
|
||||
stroke: #ff8888;
|
||||
fill: red;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.activeCrit0,
|
||||
.activeCrit1,
|
||||
.activeCrit2,
|
||||
.activeCrit3 {
|
||||
stroke: #ff8888;
|
||||
fill: #cde498;
|
||||
stroke-width: 2;
|
||||
}
|
||||
.doneCrit0,
|
||||
.doneCrit1,
|
||||
.doneCrit2,
|
||||
.doneCrit3 {
|
||||
stroke: #ff8888;
|
||||
fill: lightgrey;
|
||||
stroke-width: 2;
|
||||
cursor: pointer;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.doneCritText0,
|
||||
.doneCritText1,
|
||||
.doneCritText2,
|
||||
.doneCritText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
.activeCritText0,
|
||||
.activeCritText1,
|
||||
.activeCritText2,
|
||||
.activeCritText3 {
|
||||
fill: black !important;
|
||||
}
|
||||
.titleText {
|
||||
text-anchor: middle;
|
||||
font-size: 18px;
|
||||
fill: black;
|
||||
}
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
g.classGroup text {
|
||||
fill: #13540c;
|
||||
stroke: none;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
g.classGroup rect {
|
||||
fill: #cde498;
|
||||
stroke: #13540c;
|
||||
}
|
||||
g.classGroup line {
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
svg .classLabel .box {
|
||||
stroke: none;
|
||||
stroke-width: 0;
|
||||
fill: #cde498;
|
||||
opacity: 0.5;
|
||||
}
|
||||
svg .classLabel .label {
|
||||
fill: #13540c;
|
||||
}
|
||||
.relation {
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
.composition {
|
||||
fill: #13540c;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#compositionStart {
|
||||
fill: #13540c;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#compositionEnd {
|
||||
fill: #13540c;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.aggregation {
|
||||
fill: #cde498;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#aggregationStart {
|
||||
fill: #cde498;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#aggregationEnd {
|
||||
fill: #cde498;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#dependencyStart {
|
||||
fill: #13540c;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#dependencyEnd {
|
||||
fill: #13540c;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#extensionStart {
|
||||
fill: #13540c;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
#extensionEnd {
|
||||
fill: #13540c;
|
||||
stroke: #13540c;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.node text {
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
div.mermaidTooltip {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
max-width: 200px;
|
||||
padding: 2px;
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
font-size: 12px;
|
||||
background: #cdffb2;
|
||||
border: 1px solid #6eaa49;
|
||||
border-radius: 2px;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 29 KiB |
|
@ -3,6 +3,10 @@ $(function () {
|
|||
js : window.katex.js,
|
||||
css : window.katex.css
|
||||
};
|
||||
var htmlDecodeList = ["style","script","title","onmouseover","onmouseout","style"];
|
||||
if (!window.IS_ENABLE_IFRAME) {
|
||||
htmlDecodeList.unshift("iframe");
|
||||
}
|
||||
window.editor = editormd("docEditor", {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
@ -18,8 +22,8 @@ $(function () {
|
|||
taskList: true,
|
||||
flowChart: true,
|
||||
mermaid: true,
|
||||
htmlDecode: "style,script,iframe,title,onmouseover,onmouseout,style",
|
||||
lineNumbers: false,
|
||||
htmlDecode: htmlDecodeList.join(','),
|
||||
lineNumbers: true,
|
||||
sequenceDiagram: true,
|
||||
highlightStyle: window.highlightStyle ? window.highlightStyle : "github",
|
||||
tocStartLevel: 1,
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* 将es6的class语法转为浏览器可以直接使用的语法,
|
||||
* 取自 https://babeljs.io/repl
|
||||
* 需要添加 @babel/plugin-transform-classes
|
||||
* 是要到的方法添加了`c2b`前缀
|
||||
*/
|
||||
|
||||
function c2b_classCallCheck(instance, Constructor) {
|
||||
if (!(instance instanceof Constructor)) {
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
}
|
||||
}
|
||||
|
||||
function _defineProperties(target, props) {
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var descriptor = props[i];
|
||||
descriptor.enumerable = descriptor.enumerable || false;
|
||||
descriptor.configurable = true;
|
||||
if ("value" in descriptor) descriptor.writable = true;
|
||||
Object.defineProperty(target, descriptor.key, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
function c2b_createClass(Constructor, protoProps, staticProps) {
|
||||
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
||||
if (staticProps) _defineProperties(Constructor, staticProps);
|
||||
return Constructor;
|
||||
}
|
||||
|
||||
function c2b_inherits(subClass, superClass) {
|
||||
if (typeof superClass !== "function" && superClass !== null) {
|
||||
throw new TypeError("Super expression must either be null or a function");
|
||||
}
|
||||
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
||||
constructor: { value: subClass, writable: true, configurable: true }
|
||||
});
|
||||
if (superClass) _setPrototypeOf(subClass, superClass);
|
||||
}
|
||||
|
||||
function _setPrototypeOf(o, p) {
|
||||
_setPrototypeOf =
|
||||
Object.setPrototypeOf ||
|
||||
function _setPrototypeOf(o, p) {
|
||||
o.__proto__ = p;
|
||||
return o;
|
||||
};
|
||||
return _setPrototypeOf(o, p);
|
||||
}
|
||||
|
||||
function c2b_createSuper(Derived) {
|
||||
var hasNativeReflectConstruct = _isNativeReflectConstruct();
|
||||
return function _createSuperInternal() {
|
||||
var Super = _getPrototypeOf(Derived),
|
||||
result;
|
||||
if (hasNativeReflectConstruct) {
|
||||
var NewTarget = _getPrototypeOf(this).constructor;
|
||||
result = Reflect.construct(Super, arguments, NewTarget);
|
||||
} else {
|
||||
result = Super.apply(this, arguments);
|
||||
}
|
||||
return _possibleConstructorReturn(this, result);
|
||||
};
|
||||
}
|
||||
|
||||
function _possibleConstructorReturn(self, call) {
|
||||
if (call && (typeof call === "object" || typeof call === "function")) {
|
||||
return call;
|
||||
} else if (call !== void 0) {
|
||||
throw new TypeError(
|
||||
"Derived constructors may only return object or undefined"
|
||||
);
|
||||
}
|
||||
return _assertThisInitialized(self);
|
||||
}
|
||||
|
||||
function _assertThisInitialized(self) {
|
||||
if (self === void 0) {
|
||||
throw new ReferenceError(
|
||||
"this hasn't been initialised - super() hasn't been called"
|
||||
);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
function _isNativeReflectConstruct() {
|
||||
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
||||
if (Reflect.construct.sham) return false;
|
||||
if (typeof Proxy === "function") return true;
|
||||
try {
|
||||
Boolean.prototype.valueOf.call(
|
||||
Reflect.construct(Boolean, [], function () {})
|
||||
);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function _getPrototypeOf(o) {
|
||||
_getPrototypeOf = Object.setPrototypeOf
|
||||
? Object.getPrototypeOf
|
||||
: function _getPrototypeOf(o) {
|
||||
return o.__proto__ || Object.getPrototypeOf(o);
|
||||
};
|
||||
return _getPrototypeOf(o);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
!function(P,H,k){"use strict";if(1==P.importNode.length&&!H.get("ungap-li")){var D="extends";try{var e={extends:"li"},t=HTMLLIElement,n=function(){return Reflect.construct(t,[],n)};if(n.prototype=k.create(t.prototype),H.define("ungap-li",n,e),!/is="ungap-li"/.test((new n).outerHTML))throw e}catch(e){!function(){var l="attributeChangedCallback",n="connectedCallback",r="disconnectedCallback",e=Element.prototype,i=k.assign,t=k.create,o=k.defineProperties,a=k.getOwnPropertyDescriptor,s=k.setPrototypeOf,u=H.define,c=H.get,f=H.upgrade,p=H.whenDefined,v=t(null),d=new WeakMap,g={childList:!0,subtree:!0};Reflect.ownKeys(self).filter(function(e){return"string"==typeof e&&/^HTML(?!Element)/.test(e)}).forEach(function(e){function t(){}var n=self[e];s(t,n),(t.prototype=n.prototype).constructor=t,(n={})[e]={value:t},o(self,n)}),new MutationObserver(m).observe(P,g),O(Document.prototype,"importNode"),O(Node.prototype,"cloneNode"),o(H,{define:{value:function(e,t,n){if(e=e.toLowerCase(),n&&D in n){v[e]=i({},n,{Class:t});for(var e=n[D]+'[is="'+e+'"]',r=P.querySelectorAll(e),o=0,a=r.length;o<a;o++)A(r[o])}else u.apply(H,arguments)}},get:{value:function(e){return e in v?v[e].Class:c.call(H,e)}},upgrade:{value:function(e){var t=L(e);!t||e instanceof t.Class?f.call(H,e):N(e,t)}},whenDefined:{value:function(e){return e in v?Promise.resolve():p.call(H,e)}}});var h=P.createElement;o(P,{createElement:{value:function(e,t){e=h.call(P,e);return t&&"is"in t&&(e.setAttribute("is",t.is),H.upgrade(e)),e}}});var b=a(e,"attachShadow").value,y=a(e,"innerHTML");function m(e){for(var t=0,n=e.length;t<n;t++){for(var r=e[t],o=r.addedNodes,a=r.removedNodes,i=0,l=o.length;i<l;i++)A(o[i]);for(i=0,l=a.length;i<l;i++)C(a[i])}}function w(e){for(var t=0,n=e.length;t<n;t++){var r=e[t],o=r.attributeName,a=r.oldValue,i=r.target,r=i.getAttribute(o);l in i&&(a!=r||null!=r)&&i[l](o,a,i.getAttribute(o),null)}}function C(e){var t;1===e.nodeType&&((t=L(e))&&e instanceof t.Class&&r in e&&d.get(e)!==r&&(d.set(e,r),Promise.resolve(e).then(T)),E(e,C))}function L(e){e=e.getAttribute("is");return e&&(e=e.toLowerCase())in v?v[e]:null}function M(e){e[n]()}function T(e){e[r]()}function N(e,t){var t=t.Class,n=t.observedAttributes||[];if(s(e,t.prototype),n.length){new MutationObserver(w).observe(e,{attributes:!0,attributeFilter:n,attributeOldValue:!0});for(var r=[],o=0,a=n.length;o<a;o++)r.push({attributeName:n[o],oldValue:null,target:e});w(r)}}function A(e){var t;1===e.nodeType&&((t=L(e))&&(e instanceof t.Class||N(e,t),n in e&&e.isConnected&&d.get(e)!==n&&(d.set(e,n),Promise.resolve(e).then(M))),E(e,A))}function E(e,t){for(var n=e.content,r=(n&&11==n.nodeType?n:e).querySelectorAll("[is]"),o=0,a=r.length;o<a;o++)t(r[o])}function O(e,t){var n=e[t],r={};r[t]={value:function(){var e=n.apply(this,arguments);switch(e.nodeType){case 1:case 11:E(e,A)}return e}},o(e,r)}o(e,{attachShadow:{value:function(){var e=b.apply(this,arguments);return new MutationObserver(m).observe(e,g),e}},innerHTML:{get:y.get,set:function(e){y.set.call(this,e),/\bis=("|')?[a-z0-9_-]+\1/i.test(e)&&E(this,A)}}})}()}}}(document,customElements,Object);
|
|
@ -5,7 +5,7 @@
|
|||
/**
|
||||
* 打开最后选中的节点
|
||||
*/
|
||||
function openLastSelectedNode() {
|
||||
function openLastSelectedNode() {
|
||||
//如果文档树或编辑器没有准备好则不加载文档
|
||||
if (window.treeCatalog == null || window.editor == null) {
|
||||
return false;
|
||||
|
@ -81,7 +81,14 @@ function jstree_save(node, parent) {
|
|||
var index = layer.load(1, {
|
||||
shade: [0.1, '#fff'] //0.1透明度的白色背景
|
||||
});
|
||||
|
||||
locales = {
|
||||
'zh-CN': {
|
||||
saveSortSucc: '保存排序成功',
|
||||
},
|
||||
'en': {
|
||||
saveSortSucc: 'Save sort success',
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
url: window.sortURL,
|
||||
type: "post",
|
||||
|
@ -89,7 +96,7 @@ function jstree_save(node, parent) {
|
|||
success: function (res) {
|
||||
layer.close(index);
|
||||
if (res.errcode === 0) {
|
||||
layer.msg("保存排序成功");
|
||||
layer.msg(locales[lang].saveSortSucc);
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
|
@ -138,8 +145,27 @@ function getSiblingSort(node) {
|
|||
* @param $node
|
||||
*/
|
||||
function openDeleteDocumentDialog($node) {
|
||||
var index = layer.confirm('你确定要删除该文档吗?', {
|
||||
btn: ['确定', '取消'] //按钮
|
||||
locales = {
|
||||
'zh-CN': {
|
||||
saveSortSucc: '保存排序成功',
|
||||
confirmDeleteDoc: '你确定要删除该文档吗?',
|
||||
confirm: '确定',
|
||||
cancel: '取消',
|
||||
deleteFailed: '删除失败',
|
||||
confirmLeave: '您输入的内容尚未保存,确定离开此页面吗?'
|
||||
},
|
||||
'en': {
|
||||
saveSortSucc: 'Save sort success',
|
||||
confirmDeleteDoc: 'Are you sure you want to delete this document?',
|
||||
confirm: 'Confirm',
|
||||
cancel: 'Cancel',
|
||||
deleteFailed: 'Delete Failed',
|
||||
confirmLeave: 'The content you entered has not been saved. Are you sure you want to leave this page?'
|
||||
}
|
||||
}
|
||||
langs = locales[lang];
|
||||
var index = layer.confirm(langs.confirmDeleteDoc, {
|
||||
btn: [langs.confirm, langs.cancel] //按钮
|
||||
}, function () {
|
||||
|
||||
$.post(window.deleteURL, {"identify": window.book.identify, "doc_id": $node.id}).done(function (res) {
|
||||
|
@ -154,11 +180,11 @@ function openDeleteDocumentDialog($node) {
|
|||
// console.log(window.documentCategory)
|
||||
setLastSelectNode();
|
||||
} else {
|
||||
layer.msg("删除失败", {icon: 2})
|
||||
layer.msg(lang.deleteFailed, {icon: 2})
|
||||
}
|
||||
}).fail(function () {
|
||||
layer.close(index);
|
||||
layer.msg("删除失败", {icon: 2})
|
||||
layer.msg(lang.deleteFailed, {icon: 2})
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -228,6 +254,14 @@ function pushVueLists($lists) {
|
|||
* 发布项目
|
||||
*/
|
||||
function releaseBook() {
|
||||
locales = {
|
||||
'zh-CN': {
|
||||
publishToQueue: '发布任务已推送到任务队列,稍后将在后台执行。',
|
||||
},
|
||||
'en': {
|
||||
publishToQueue: 'The publish task has been pushed to the queue</br> and will be executed soon.',
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
url: window.releaseURL,
|
||||
data: {"identify": window.book.identify},
|
||||
|
@ -235,7 +269,7 @@ function releaseBook() {
|
|||
dataType: "json",
|
||||
success: function (res) {
|
||||
if (res.errcode === 0) {
|
||||
layer.msg("发布任务已推送到任务队列,稍后将在后台执行。");
|
||||
layer.msg(locales[lang].publishToQueue);
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
|
@ -298,9 +332,17 @@ function showSuccess($msg, $id) {
|
|||
}
|
||||
|
||||
window.documentHistory = function () {
|
||||
locales = {
|
||||
'zh-CN': {
|
||||
hisVer: '历史版本',
|
||||
},
|
||||
'en': {
|
||||
hisVer: 'Historic version',
|
||||
}
|
||||
}
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '历史版本',
|
||||
title: locales[lang].hisVer,
|
||||
shadeClose: true,
|
||||
shade: 0.8,
|
||||
area: ['700px', '80%'],
|
||||
|
@ -320,6 +362,16 @@ window.documentHistory = function () {
|
|||
};
|
||||
|
||||
function uploadImage($id, $callback) {
|
||||
locales = {
|
||||
'zh-CN': {
|
||||
unsupportType: '不支持的图片格式',
|
||||
uploadFailed: '图片上传失败'
|
||||
},
|
||||
'en': {
|
||||
unsupportType: 'Unsupport image type',
|
||||
uploadFailed: 'Upload image failed'
|
||||
}
|
||||
}
|
||||
/** 粘贴上传图片 **/
|
||||
document.getElementById($id).addEventListener('paste', function (e) {
|
||||
if (e.clipboardData && e.clipboardData.items) {
|
||||
|
@ -345,7 +397,7 @@ function uploadImage($id, $callback) {
|
|||
fileName += ".gif";
|
||||
break;
|
||||
default :
|
||||
layer.msg("不支持的图片格式");
|
||||
layer.msg(locales[lang].unsupportType);
|
||||
return;
|
||||
}
|
||||
var form = new FormData();
|
||||
|
@ -367,7 +419,7 @@ function uploadImage($id, $callback) {
|
|||
error: function () {
|
||||
layer.close(layerIndex);
|
||||
$callback('error');
|
||||
layer.msg("图片上传失败");
|
||||
layer.msg(locales[lang].uploadFailed);
|
||||
},
|
||||
success: function (data) {
|
||||
layer.close(layerIndex);
|
||||
|
|
|
@ -1,21 +1,60 @@
|
|||
$(function () {
|
||||
wangEditor.config.mapAk = window.baiduMapKey;
|
||||
window.addDocumentModalFormHtml = $(this).find("form").html();
|
||||
wangEditor.config.printLog = false;
|
||||
window.editor = new wangEditor('htmlEditor');
|
||||
window.editor = new wangEditor('#htmlEditor');
|
||||
editor.config.mapAk = window.baiduMapKey;
|
||||
editor.config.printLog = false;
|
||||
editor.config.showMenuTooltips = true
|
||||
editor.config.menuTooltipPosition = 'down'
|
||||
editor.config.uploadImgUrl = window.imageUploadURL;
|
||||
editor.config.uploadImgFileName = "editormd-image-file";
|
||||
editor.config.uploadParams = {
|
||||
"editor" : "wangEditor"
|
||||
};
|
||||
wangEditor.config.menus.splice(0,0,"|");
|
||||
wangEditor.config.menus.splice(0,0,"history");
|
||||
wangEditor.config.menus.splice(0,0,"save");
|
||||
wangEditor.config.menus.splice(0,0,"release");
|
||||
wangEditor.config.menus.splice(29,0,"attach")
|
||||
editor.config.uploadImgServer = window.imageUploadURL;
|
||||
editor.config.customUploadImg = function (resultFiles, insertImgFn) {
|
||||
// resultFiles 是 input 中选中的文件列表
|
||||
// insertImgFn 是获取图片 url 后,插入到编辑器的方法
|
||||
var file = resultFiles[0];
|
||||
// file type is only image.
|
||||
if (/^image\//.test(file.type)) {
|
||||
var form = new FormData();
|
||||
form.append('editormd-image-file', file, file.name);
|
||||
|
||||
var layerIndex = 0;
|
||||
|
||||
$.ajax({
|
||||
url: window.imageUploadURL,
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: form,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
error: function() {
|
||||
layer.close(layerIndex);
|
||||
layer.msg("图片上传失败");
|
||||
},
|
||||
success: function(data) {
|
||||
layer.close(layerIndex);
|
||||
if(data.errcode !== 0){
|
||||
layer.msg(data.message);
|
||||
}else{
|
||||
insertImgFn(data.url);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn('You could only upload images.');
|
||||
}
|
||||
};
|
||||
/*
|
||||
editor.config.menus.splice(0,0,"|");
|
||||
editor.config.menus.splice(0,0,"history");
|
||||
editor.config.menus.splice(0,0,"save");
|
||||
editor.config.menus.splice(0,0,"release");
|
||||
editor.config.menus.splice(29,0,"attach")
|
||||
|
||||
//移除地图、背景色
|
||||
editor.config.menus = $.map(wangEditor.config.menus, function(item, key) {
|
||||
editor.config.menus = $.map(editor.config.menus, function(item, key) {
|
||||
|
||||
if (item === 'fullscreen') {
|
||||
return null;
|
||||
|
@ -23,16 +62,8 @@ $(function () {
|
|||
|
||||
return item;
|
||||
});
|
||||
|
||||
window.editor.ready(function () {
|
||||
if(window.documentCategory.length > 0){
|
||||
var item = window.documentCategory[0];
|
||||
var $select_node = { node : {id : item.id}};
|
||||
loadDocument($select_node);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
*/
|
||||
/*
|
||||
window.editor.config.uploadImgFns.onload = function (resultText, xhr) {
|
||||
// resultText 服务器端返回的text
|
||||
// xhr 是 xmlHttpRequest 对象,IE8、9中不支持
|
||||
|
@ -47,13 +78,15 @@ $(function () {
|
|||
layer.msg(res.message);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
window.editor.onchange = function () {
|
||||
window.editor.config.onchange = function (newHtml) {
|
||||
var saveMenu = window.editor.menus.menuList.find((item) => item.key == 'save');
|
||||
// 判断内容是否改变
|
||||
if (window.source !== this.$txt.html()) {
|
||||
window.editor.menus.save.$domNormal.addClass('selected');
|
||||
if (window.source !== window.editor.txt.html()) {
|
||||
saveMenu.$elem.addClass('selected');
|
||||
} else {
|
||||
window.editor.menus.save.$domNormal.removeClass('selected');
|
||||
saveMenu.$elem.removeClass('selected');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -62,7 +95,11 @@ $(function () {
|
|||
|
||||
$("#htmlEditor").css("height","100%");
|
||||
|
||||
|
||||
if(window.documentCategory.length > 0){
|
||||
var item = window.documentCategory[0];
|
||||
var $select_node = { node : {id : item.id}};
|
||||
loadDocument($select_node);
|
||||
}
|
||||
|
||||
/***
|
||||
* 加载指定的文档到编辑器中
|
||||
|
@ -78,8 +115,8 @@ $(function () {
|
|||
|
||||
if(res.errcode === 0){
|
||||
window.isLoad = true;
|
||||
window.editor.clear();
|
||||
window.editor.$txt.html(res.data.content);
|
||||
window.editor.txt.clear();
|
||||
window.editor.txt.html(res.data.content);
|
||||
// 将原始内容备份
|
||||
window.source = res.data.content;
|
||||
var node = { "id" : res.data.doc_id,'parent' : res.data.parent_id === 0 ? '#' : res.data.parent_id ,"text" : res.data.doc_name,"identify" : res.data.identify,"version" : res.data.version};
|
||||
|
@ -105,7 +142,7 @@ $(function () {
|
|||
var index = null;
|
||||
var node = window.selectNode;
|
||||
|
||||
var html = window.editor.$txt.html() ;
|
||||
var html = window.editor.txt.html() ;
|
||||
|
||||
var content = "";
|
||||
if($.trim(html) !== ""){
|
||||
|
@ -149,7 +186,7 @@ $(function () {
|
|||
// 更新内容备份
|
||||
window.source = res.data.content;
|
||||
// 触发编辑器 onchange 回调函数
|
||||
window.editor.onchange();
|
||||
window.editor.config.onchange();
|
||||
if(typeof callback === "function"){
|
||||
callback();
|
||||
}
|
||||
|
@ -267,7 +304,7 @@ $(function () {
|
|||
}).on('loaded.jstree', function () {
|
||||
window.treeCatalog = $(this).jstree();
|
||||
}).on('select_node.jstree', function (node, selected, event) {
|
||||
if(window.editor.menus.save.$domNormal.hasClass('selected')) {
|
||||
if(window.editor.menus.menuList.find((item) => item.key == 'save').$elem.hasClass('selected')) {
|
||||
if(confirm("编辑内容未保存,需要保存吗?")){
|
||||
saveDocument(false,function () {
|
||||
loadDocument(selected);
|
||||
|
@ -283,7 +320,7 @@ $(function () {
|
|||
|
||||
window.releaseBook = function () {
|
||||
if(Object.prototype.toString.call(window.documentCategory) === '[object Array]' && window.documentCategory.length > 0){
|
||||
if(window.editor.menus.save.$domNormal.hasClass('selected')) {
|
||||
if(window.editor.menus.menuList.find((item) => item.key == 'save').$elem.hasClass('selected')) {
|
||||
if(confirm("编辑内容未保存,需要保存吗?")) {
|
||||
saveDocument();
|
||||
}
|
||||
|
@ -305,4 +342,16 @@ $(function () {
|
|||
layer.msg("没有需要发布的文档")
|
||||
}
|
||||
};
|
||||
|
||||
$(window).resize(function(e) {
|
||||
var $container = $(editor.$textContainerElem.elems[0]);
|
||||
var $manual = $container.closest('.manual-wangEditor');
|
||||
var maxHeight = $manual.closest('.manual-editor-container').innerHeight();
|
||||
var statusHeight = $manual.siblings('.manual-editor-status').outerHeight(true);
|
||||
var manualHeihgt = maxHeight - statusHeight;
|
||||
$manual.height(manualHeihgt);
|
||||
var toolbarHeight = $container.siblings('.w-e-toolbar').outerHeight(true);
|
||||
$container.height($container.parent().innerHeight() - toolbarHeight);
|
||||
});
|
||||
$(window).trigger('resize');
|
||||
});
|
|
@ -4,12 +4,66 @@ $(function () {
|
|||
css : window.katex.css
|
||||
};
|
||||
|
||||
window.editormdLocales = {
|
||||
'zh-CN': {
|
||||
placeholder: '本编辑器支持 Markdown 编辑,左边编写,右边预览。',
|
||||
contentUnsaved: '编辑内容未保存,需要保存吗?',
|
||||
noDocNeedPublish: '没有需要发布的文档',
|
||||
loadDocFailed: '文档加载失败',
|
||||
fetchDocFailed: '获取当前文档信息失败',
|
||||
cannotAddToEmptyNode: '空节点不能添加内容',
|
||||
overrideModified: '文档已被其他人修改确定覆盖已存在的文档吗?',
|
||||
confirm: '确定',
|
||||
cancel: '取消',
|
||||
contentsNameEmpty: '目录名称不能为空',
|
||||
addDoc: '添加文档',
|
||||
edit: '编辑',
|
||||
delete: '删除',
|
||||
loadFailed: '加载失败请重试',
|
||||
tplNameEmpty: '模板名称不能为空',
|
||||
tplContentEmpty: '模板内容不能为空',
|
||||
saveSucc: '保存成功',
|
||||
serverExcept: '服务器异常',
|
||||
paramName: '参数名称',
|
||||
paramType: '参数类型',
|
||||
example: '示例值',
|
||||
remark: '备注',
|
||||
},
|
||||
'en': {
|
||||
placeholder: 'This editor supports Markdown editing, writing on the left and previewing on the right.',
|
||||
contentUnsaved: 'The edited content is not saved, need to save it?',
|
||||
noDocNeedPublish: 'No Document need to be publish',
|
||||
loadDocFailed: 'Load Document failed',
|
||||
fetchDocFailed: 'Fetch Document info failed',
|
||||
cannotAddToEmptyNode: 'Cannot add content to empty node',
|
||||
overrideModified: 'The document has been modified by someone else, are you sure to overwrite the document?',
|
||||
confirm: 'Confirm',
|
||||
cancel: 'Cancel',
|
||||
contentsNameEmpty: 'Document Name cannot be empty',
|
||||
addDoc: 'Add Document',
|
||||
edit: 'Edit',
|
||||
delete: 'Delete',
|
||||
loadFailed: 'Failed to load, please try again',
|
||||
tplNameEmpty: 'Template name cannot be empty',
|
||||
tplContentEmpty: 'Template content cannot be empty',
|
||||
saveSucc: 'Save success',
|
||||
serverExcept: 'Server Exception',
|
||||
paramName: 'Parameter',
|
||||
paramType: 'Type',
|
||||
example: 'Example',
|
||||
remark: 'Remark',
|
||||
}
|
||||
};
|
||||
var htmlDecodeList = ["style","script","title","onmouseover","onmouseout","style"];
|
||||
if (!window.IS_ENABLE_IFRAME) {
|
||||
htmlDecodeList.unshift("iframe");
|
||||
}
|
||||
window.editor = editormd("docEditor", {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
path: window.editormdLib,
|
||||
toolbar: true,
|
||||
placeholder: "本编辑器支持 Markdown 编辑,左边编写,右边预览。",
|
||||
placeholder: window.editormdLocales[window.lang].placeholder,
|
||||
imageUpload: true,
|
||||
imageFormats: ["jpg", "jpeg", "gif", "png","svg", "JPG", "JPEG", "GIF", "PNG","SVG"],
|
||||
imageUploadURL: window.imageUploadURL,
|
||||
|
@ -18,8 +72,8 @@ $(function () {
|
|||
fileUploadURL: window.fileUploadURL,
|
||||
taskList: true,
|
||||
flowChart: true,
|
||||
htmlDecode: "style,script,iframe,title,onmouseover,onmouseout,style",
|
||||
lineNumbers: false,
|
||||
htmlDecode: htmlDecodeList.join(','),
|
||||
lineNumbers: true,
|
||||
sequenceDiagram: true,
|
||||
tocStartLevel: 1,
|
||||
tocm: true,
|
||||
|
@ -57,6 +111,7 @@ $(function () {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.isLoad = true;
|
||||
},
|
||||
onchange: function () {
|
||||
|
@ -110,7 +165,7 @@ $(function () {
|
|||
} else if (name === "release") {
|
||||
if (Object.prototype.toString.call(window.documentCategory) === '[object Array]' && window.documentCategory.length > 0) {
|
||||
if ($("#markdown-save").hasClass('change')) {
|
||||
var confirm_result = confirm("编辑内容未保存,需要保存吗?");
|
||||
var confirm_result = confirm(editormdLocales[lang].contentUnsaved);
|
||||
if (confirm_result) {
|
||||
saveDocument(false, releaseBook);
|
||||
return;
|
||||
|
@ -119,7 +174,7 @@ $(function () {
|
|||
|
||||
releaseBook();
|
||||
} else {
|
||||
layer.msg("没有需要发布的文档")
|
||||
layer.msg(editormdLocales[lang].noDocNeedPublish)
|
||||
}
|
||||
} else if (name === "tasks") {
|
||||
// 插入 GFM 任务列表
|
||||
|
@ -141,7 +196,7 @@ $(function () {
|
|||
} else {
|
||||
var action = window.editor.toolbarHandlers[name];
|
||||
|
||||
if (action !== "undefined") {
|
||||
if (!!action && action !== "undefined") {
|
||||
$.proxy(action, window.editor)();
|
||||
window.editor.focus();
|
||||
}
|
||||
|
@ -175,11 +230,11 @@ $(function () {
|
|||
pushVueLists(res.data.attach);
|
||||
setLastSelectNode($node);
|
||||
} else {
|
||||
layer.msg("文档加载失败");
|
||||
layer.msg(editormdLocales[lang].loadDocFailed);
|
||||
}
|
||||
}).fail(function () {
|
||||
layer.close(index);
|
||||
layer.msg("文档加载失败");
|
||||
layer.msg(editormdLocales[lang].loadDocFailed);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -195,11 +250,11 @@ $(function () {
|
|||
var version = "";
|
||||
|
||||
if (!node) {
|
||||
layer.msg("获取当前文档信息失败");
|
||||
layer.msg(editormdLocales[lang].fetchDocFailed);
|
||||
return;
|
||||
}
|
||||
if (node.a_attr && node.a_attr.disabled) {
|
||||
layer.msg("空节点不能添加内容");
|
||||
layer.msg(editormdLocales[lang].cannotAddToEmptyNode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -246,8 +301,8 @@ $(function () {
|
|||
}
|
||||
|
||||
} else if(res.errcode === 6005) {
|
||||
var confirmIndex = layer.confirm('文档已被其他人修改确定覆盖已存在的文档吗?', {
|
||||
btn: ['确定', '取消'] // 按钮
|
||||
var confirmIndex = layer.confirm(editormdLocales[lang].overrideModified, {
|
||||
btn: [editormdLocales[lang].confirm, editormdLocales[lang].cancel] // 按钮
|
||||
}, function() {
|
||||
layer.close(confirmIndex);
|
||||
saveDocument(true, callback);
|
||||
|
@ -257,7 +312,7 @@ $(function () {
|
|||
}
|
||||
},
|
||||
error : function (XMLHttpRequest, textStatus, errorThrown) {
|
||||
layer.msg("服务器错误:" + errorThrown);
|
||||
layer.msg(window.editormdLocales[window.lang].serverExcept + errorThrown);
|
||||
},
|
||||
complete :function () {
|
||||
layer.close(index);
|
||||
|
@ -287,7 +342,7 @@ $(function () {
|
|||
beforeSubmit: function () {
|
||||
var doc_name = $.trim($("#documentName").val());
|
||||
if (doc_name === "") {
|
||||
return showError("目录名称不能为空", "#add-error-message")
|
||||
return showError(editormdLocales[lang].contentsNameEmpty, "#add-error-message")
|
||||
}
|
||||
$("#btnSaveDocument").button("loading");
|
||||
return true;
|
||||
|
@ -347,7 +402,7 @@ $(function () {
|
|||
"separator_before": false,
|
||||
"separator_after": true,
|
||||
"_disabled": false,
|
||||
"label": "添加文档",
|
||||
"label": window.editormdLocales[window.lang].addDoc,//"添加文档",
|
||||
"icon": "fa fa-plus",
|
||||
"action": function (data) {
|
||||
var inst = $.jstree.reference(data.reference),
|
||||
|
@ -360,7 +415,7 @@ $(function () {
|
|||
"separator_before": false,
|
||||
"separator_after": true,
|
||||
"_disabled": false,
|
||||
"label": "编辑",
|
||||
"label": window.editormdLocales[window.lang].edit,
|
||||
"icon": "fa fa-edit",
|
||||
"action": function (data) {
|
||||
var inst = $.jstree.reference(data.reference);
|
||||
|
@ -372,7 +427,7 @@ $(function () {
|
|||
"separator_before": false,
|
||||
"separator_after": true,
|
||||
"_disabled": false,
|
||||
"label": "删除",
|
||||
"label": window.editormdLocales[window.lang].delete,
|
||||
"icon": "fa fa-trash-o",
|
||||
"action": function (data) {
|
||||
var inst = $.jstree.reference(data.reference);
|
||||
|
@ -390,7 +445,7 @@ $(function () {
|
|||
}).on('select_node.jstree', function (node, selected) {
|
||||
|
||||
if ($("#markdown-save").hasClass('change')) {
|
||||
if (confirm("编辑内容未保存,需要保存吗?")) {
|
||||
if (confirm(window.editormdLocales[window.lang].contentUnsaved)) {
|
||||
saveDocument(false, function () {
|
||||
loadDocument(selected);
|
||||
});
|
||||
|
@ -446,7 +501,7 @@ $(function () {
|
|||
$("#displayCustomsTemplateList").html($res);
|
||||
},
|
||||
error : function () {
|
||||
layer.msg("加载失败请重试");
|
||||
layer.msg(window.editormdLocales[window.lang].loadFailed);
|
||||
},
|
||||
complete : function () {
|
||||
layer.close(index);
|
||||
|
@ -464,11 +519,11 @@ $(function () {
|
|||
beforeSubmit: function () {
|
||||
var doc_name = $.trim($("#templateName").val());
|
||||
if (doc_name === "") {
|
||||
return showError("模板名称不能为空", "#saveTemplateForm .show-error-message");
|
||||
return showError(window.editormdLocales[window.lang].tplNameEmpty, "#saveTemplateForm .show-error-message");
|
||||
}
|
||||
var content = $("#saveTemplateForm").find("input[name='content']").val();
|
||||
if (content === ""){
|
||||
return showError("模板内容不能为空", "#saveTemplateForm .show-error-message");
|
||||
return showError(window.editormdLocales[window.lang].tplContentEmpty, "#saveTemplateForm .show-error-message");
|
||||
}
|
||||
|
||||
$("#btnSaveTemplate").button("loading");
|
||||
|
@ -478,7 +533,7 @@ $(function () {
|
|||
success: function ($res) {
|
||||
if($res.errcode === 0){
|
||||
$("#saveTemplateModal").modal("hide");
|
||||
layer.msg("保存成功");
|
||||
layer.msg(window.editormdLocales[window.lang].saveSucc);
|
||||
}else{
|
||||
return showError($res.message, "#saveTemplateForm .show-error-message");
|
||||
}
|
||||
|
@ -521,7 +576,7 @@ $(function () {
|
|||
resetEditorChanged(true);
|
||||
$("#displayCustomsTemplateModal").modal("hide");
|
||||
},error : function () {
|
||||
layer.msg("服务器异常");
|
||||
layer.msg(window.editormdLocales[window.lang].serverExcept);
|
||||
}
|
||||
});
|
||||
}).on("click",".btn-delete",function () {
|
||||
|
@ -541,7 +596,7 @@ $(function () {
|
|||
$then.parents("tr").empty().remove();
|
||||
}
|
||||
},error : function () {
|
||||
layer.msg("服务器异常");
|
||||
layer.msg(window.editormdLocales[window.lang].serverExcept);
|
||||
},
|
||||
complete: function () {
|
||||
$then.button("reset");
|
||||
|
@ -555,7 +610,11 @@ $(function () {
|
|||
try {
|
||||
var jsonObj = $.parseJSON(content);
|
||||
var data = foreachJson(jsonObj,"");
|
||||
var table = "| 参数名称 | 参数类型 | 示例值 | 备注 |\n| ------------ | ------------ | ------------ | ------------ |\n";
|
||||
var table = "| " + window.editormdLocales[window.lang].paramName
|
||||
+ " | " + window.editormdLocales[window.lang].paramType
|
||||
+ " | " + window.editormdLocales[window.lang].example
|
||||
+ " | " + window.editormdLocales[window.lang].remark
|
||||
+ " |\n| ------------ | ------------ | ------------ | ------------ |\n";
|
||||
$.each(data,function (i,item) {
|
||||
table += "|" + item.key + "|" + item.type + "|" + item.value +"| |\n";
|
||||
});
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
let AttachMenu = (function (_BtnMenu) {
|
||||
c2b_inherits(AttachMenu, _BtnMenu);
|
||||
|
||||
var _super = c2b_createSuper(AttachMenu);
|
||||
|
||||
function AttachMenu(editor) {
|
||||
c2b_classCallCheck(this, AttachMenu);
|
||||
|
||||
const $elem = E.$(`<div class="w-e-menu" data-title="附件">
|
||||
<i class="fa fa-paperclip" aria-hidden="true"></i>
|
||||
</div>`);
|
||||
return _super.call(this, $elem, editor);
|
||||
}
|
||||
|
||||
c2b_createClass(AttachMenu, [
|
||||
{
|
||||
key: "clickHandler",
|
||||
value: function clickHandler() {
|
||||
$("#uploadAttachModal").modal("show");
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "tryChangeActive",
|
||||
value: function tryChangeActive() {
|
||||
// this.active();
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
return AttachMenu;
|
||||
})(E.BtnMenu);
|
||||
|
||||
|
||||
var menuKey = 'attach';
|
||||
E.registerMenu(menuKey, AttachMenu);
|
||||
})();
|
|
@ -0,0 +1,42 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
let HistoryMenu = (function (_BtnMenu) {
|
||||
c2b_inherits(HistoryMenu, _BtnMenu);
|
||||
|
||||
var _super = c2b_createSuper(HistoryMenu);
|
||||
|
||||
function HistoryMenu(editor) {
|
||||
c2b_classCallCheck(this, HistoryMenu);
|
||||
|
||||
const $elem = E.$(`<div class="w-e-menu" data-title="history">
|
||||
<i class="fa fa-history" aria-hidden="true"></i>
|
||||
</div>`);
|
||||
return _super.call(this, $elem, editor);
|
||||
}
|
||||
|
||||
c2b_createClass(HistoryMenu, [
|
||||
{
|
||||
key: "clickHandler",
|
||||
value: function clickHandler() {
|
||||
window.documentHistory();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "tryChangeActive",
|
||||
value: function tryChangeActive() {
|
||||
// this.active();
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
return HistoryMenu;
|
||||
})(E.BtnMenu);
|
||||
|
||||
|
||||
var menuKey = '历史';
|
||||
E.registerMenu(menuKey, HistoryMenu);
|
||||
})();
|
|
@ -0,0 +1,42 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
let ReleaseMenu = (function (_BtnMenu) {
|
||||
c2b_inherits(ReleaseMenu, _BtnMenu);
|
||||
|
||||
var _super = c2b_createSuper(ReleaseMenu);
|
||||
|
||||
function ReleaseMenu(editor) {
|
||||
c2b_classCallCheck(this, ReleaseMenu);
|
||||
|
||||
const $elem = E.$(`<div class="w-e-menu" data-title="发布">
|
||||
<i class="fa fa-cloud-upload" aria-hidden="true"></i>
|
||||
</div>`);
|
||||
return _super.call(this, $elem, editor);
|
||||
}
|
||||
|
||||
c2b_createClass(ReleaseMenu, [
|
||||
{
|
||||
key: "clickHandler",
|
||||
value: function clickHandler() {
|
||||
window.releaseBook();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "tryChangeActive",
|
||||
value: function tryChangeActive() {
|
||||
// this.active();
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
return ReleaseMenu;
|
||||
})(E.BtnMenu);
|
||||
|
||||
|
||||
var menuKey = 'release';
|
||||
E.registerMenu(menuKey, ReleaseMenu);
|
||||
})();
|
|
@ -0,0 +1,42 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
let SaveMenu = (function (_BtnMenu) {
|
||||
c2b_inherits(SaveMenu, _BtnMenu);
|
||||
|
||||
var _super = c2b_createSuper(SaveMenu);
|
||||
|
||||
function SaveMenu(editor) {
|
||||
c2b_classCallCheck(this, SaveMenu);
|
||||
|
||||
const $elem = E.$(`<div class="w-e-menu" data-title="保存">
|
||||
<i class="fa fa-floppy-o" aria-hidden="true"></i>
|
||||
</div>`);
|
||||
return _super.call(this, $elem, editor);
|
||||
}
|
||||
|
||||
c2b_createClass(SaveMenu, [
|
||||
{
|
||||
key: "clickHandler",
|
||||
value: function clickHandler() {
|
||||
window.saveDocument();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "tryChangeActive",
|
||||
value: function tryChangeActive() {
|
||||
// this.active();
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
return SaveMenu;
|
||||
})(E.BtnMenu);
|
||||
|
||||
|
||||
var menuKey = 'save';
|
||||
E.registerMenu(menuKey, SaveMenu);
|
||||
})();
|
|
@ -0,0 +1,87 @@
|
|||
customElements.define('x-frame-bypass', class extends HTMLIFrameElement {
|
||||
static get observedAttributes() {
|
||||
return ['src']
|
||||
}
|
||||
constructor () {
|
||||
super()
|
||||
}
|
||||
attributeChangedCallback () {
|
||||
this.load(this.src)
|
||||
}
|
||||
connectedCallback () {
|
||||
this.sandbox = '' + this.sandbox || 'allow-forms allow-modals allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation' // all except allow-top-navigation
|
||||
}
|
||||
load (url, options) {
|
||||
if (!url || !url.startsWith('http'))
|
||||
throw new Error(`X-Frame-Bypass src ${url} does not start with http(s)://`)
|
||||
console.log('X-Frame-Bypass loading:', url)
|
||||
this.srcdoc = `<html>
|
||||
<head>
|
||||
<style>
|
||||
.loader {
|
||||
position: absolute;
|
||||
top: calc(50% - 25px);
|
||||
left: calc(50% - 25px);
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: #333;
|
||||
border-radius: 50%;
|
||||
animation: loader 1s infinite ease-in-out;
|
||||
}
|
||||
@keyframes loader {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="loader"></div>
|
||||
</body>
|
||||
</html>`
|
||||
this.fetchProxy(url, options, 0).then(res => res.text()).then(data => {
|
||||
if (data)
|
||||
this.srcdoc = data.replace(/<head([^>]*)>/i, `<head$1>
|
||||
<base href="${url}">
|
||||
<script>
|
||||
// X-Frame-Bypass navigation event handlers
|
||||
document.addEventListener('click', e => {
|
||||
if (frameElement && document.activeElement && document.activeElement.href) {
|
||||
e.preventDefault()
|
||||
frameElement.load(document.activeElement.href)
|
||||
}
|
||||
})
|
||||
document.addEventListener('submit', e => {
|
||||
if (frameElement && document.activeElement && document.activeElement.form && document.activeElement.form.action) {
|
||||
e.preventDefault()
|
||||
if (document.activeElement.form.method === 'post')
|
||||
frameElement.load(document.activeElement.form.action, {method: 'post', body: new FormData(document.activeElement.form)})
|
||||
else
|
||||
frameElement.load(document.activeElement.form.action + '?' + new URLSearchParams(new FormData(document.activeElement.form)))
|
||||
}
|
||||
})
|
||||
</script>`)
|
||||
}).catch(e => console.error('Cannot load X-Frame-Bypass:', e))
|
||||
}
|
||||
fetchProxy (url, options, i) {
|
||||
const proxies = (options || {}).proxies || [
|
||||
window.BASE_URL + 'cors-anywhere?url=',
|
||||
'https://cors-anywhere.herokuapp.com/',
|
||||
'https://yacdn.org/proxy/',
|
||||
'https://api.codetabs.com/v1/proxy/?quest='
|
||||
]
|
||||
return fetch(proxies[i] + url, options).then(res => {
|
||||
if (!res.ok)
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
return res
|
||||
}).catch(error => {
|
||||
if (i === proxies.length - 1)
|
||||
throw error
|
||||
return this.fetchProxy(url, options, i + 1)
|
||||
})
|
||||
}
|
||||
}, {extends: 'iframe'})
|
|
@ -1,831 +0,0 @@
|
|||
/* 编辑器边框颜色 */
|
||||
/* 菜单颜色、上边框颜色 */
|
||||
/* 菜单选中状态的颜色 */
|
||||
/* input focus 时的颜色 */
|
||||
/* 按钮颜色 */
|
||||
/* tab selected 状态下的颜色 */
|
||||
.wangEditor-container {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
}
|
||||
.wangEditor-container a:focus,
|
||||
.wangEditor-container button:focus {
|
||||
outline: none;
|
||||
}
|
||||
.wangEditor-container,
|
||||
.wangEditor-container * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
line-height: 1;
|
||||
}
|
||||
.wangEditor-container img {
|
||||
border: none;
|
||||
}
|
||||
.wangEditor-container .clearfix:after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
.wangEditor-container .clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
.wangEditor-container textarea {
|
||||
border: none;
|
||||
}
|
||||
.wangEditor-container textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
.wangEditor-container .height-tip {
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
background-color: #ccc;
|
||||
left: 0;
|
||||
transition: top .2s;
|
||||
}
|
||||
.wangEditor-container .txt-toolbar {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
padding: 3px 5px;
|
||||
border-top: 2px solid #666;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
}
|
||||
.wangEditor-container .txt-toolbar .tip-triangle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 5px solid;
|
||||
border-color: transparent transparent #666 transparent;
|
||||
top: -12px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
}
|
||||
.wangEditor-container .txt-toolbar a {
|
||||
color: #666;
|
||||
display: inline-block;
|
||||
margin: 0 3px;
|
||||
padding: 5px;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.wangEditor-container .txt-toolbar a:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-container .img-drag-point {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
cursor: se-resize;
|
||||
background-color: #666;
|
||||
margin-left: -6px;
|
||||
margin-top: -6px;
|
||||
box-shadow: 1px 1px 5px #999;
|
||||
}
|
||||
.wangEditor-container .wangEditor-upload-progress {
|
||||
position: absolute;
|
||||
height: 1px;
|
||||
background: #1e88e5;
|
||||
width: 0;
|
||||
display: none;
|
||||
-webkit-transition: width .5s;
|
||||
-o-transition: width .5s;
|
||||
transition: width .5s;
|
||||
}
|
||||
.wangEditor-fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.wangEditor-container .code-textarea {
|
||||
resize: none;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
font-family: 'Verdana';
|
||||
color: #333;
|
||||
padding: 0 15px 0 15px;
|
||||
}
|
||||
.wangEditor-menu-container {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
background-color: #fff;
|
||||
}
|
||||
.wangEditor-menu-container a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.wangEditor-menu-container .menu-group {
|
||||
float: left;
|
||||
padding: 0 8px;
|
||||
border-right: 1px solid #f1f1f1;
|
||||
}
|
||||
.wangEditor-menu-container .menu-item {
|
||||
float: left;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
height: 31px;
|
||||
width: 35px;
|
||||
}
|
||||
.wangEditor-menu-container .menu-item:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-menu-container .menu-item a {
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
width: 100%;
|
||||
padding: 8px 0;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.wangEditor-menu-container .menu-item .selected {
|
||||
color: #1e88e5;
|
||||
}
|
||||
.wangEditor-menu-container .menu-item .active {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-menu-container .menu-item .disable {
|
||||
opacity: 0.5;
|
||||
filter: alpha(opacity=50);
|
||||
}
|
||||
.wangEditor-menu-container .menu-tip {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
background-color: #666;
|
||||
color: #fff;
|
||||
padding: 7px 0;
|
||||
font-size: 12px;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -30px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 1px 1px 5px #999;
|
||||
display: none;
|
||||
/*// 小三角
|
||||
.tip-triangle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border:5px solid;
|
||||
border-color: transparent transparent @fore-color transparent;
|
||||
top: -10px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
}*/
|
||||
}
|
||||
.wangEditor-menu-container .menu-tip-40 {
|
||||
width: 40px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
.wangEditor-menu-container .menu-tip-50 {
|
||||
width: 50px;
|
||||
margin-left: -25px;
|
||||
}
|
||||
.wangEditor-menu-shadow {
|
||||
/*border-bottom-width: 0;*/
|
||||
border-bottom: 1px\9 solid\9 #f1f1f1\9;
|
||||
box-shadow: 0 1px 3px #999;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 15px;
|
||||
padding-top: 0;
|
||||
margin-top: 5px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt p,
|
||||
.wangEditor-container .wangEditor-txt h1,
|
||||
.wangEditor-container .wangEditor-txt h2,
|
||||
.wangEditor-container .wangEditor-txt h3,
|
||||
.wangEditor-container .wangEditor-txt h4,
|
||||
.wangEditor-container .wangEditor-txt h5 {
|
||||
margin: 10px 0;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt p *,
|
||||
.wangEditor-container .wangEditor-txt h1 *,
|
||||
.wangEditor-container .wangEditor-txt h2 *,
|
||||
.wangEditor-container .wangEditor-txt h3 *,
|
||||
.wangEditor-container .wangEditor-txt h4 *,
|
||||
.wangEditor-container .wangEditor-txt h5 * {
|
||||
line-height: 1.8;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt ul,
|
||||
.wangEditor-container .wangEditor-txt ol {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt img {
|
||||
cursor: pointer;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt img.clicked {
|
||||
box-shadow: 1px 1px 10px #999;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt table.clicked {
|
||||
box-shadow: 1px 1px 10px #999;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt pre code {
|
||||
line-height: 1.5;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt:focus {
|
||||
outline: none;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt blockquote {
|
||||
display: block;
|
||||
border-left: 8px solid #d0e5f2;
|
||||
padding: 5px 10px;
|
||||
margin: 10px 0;
|
||||
line-height: 1.4;
|
||||
font-size: 100%;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt table {
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt table td,
|
||||
.wangEditor-container .wangEditor-txt table th {
|
||||
border: 1px solid #999;
|
||||
padding: 3px 5px;
|
||||
min-width: 50px;
|
||||
height: 20px;
|
||||
}
|
||||
.wangEditor-container .wangEditor-txt pre {
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f8f8f8;
|
||||
padding: 10px;
|
||||
margin: 5px 0px;
|
||||
font-size: 0.8em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.wangEditor-drop-list {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
transition: height .7s;
|
||||
border-top: 1px solid #f1f1f1;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
}
|
||||
.wangEditor-drop-list a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
color: #666;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
.wangEditor-drop-list a:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-drop-panel,
|
||||
.txt-toolbar {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
/*border: 1px\9 solid\9 #cccccc\9;*/
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
border-top: 2px solid #666;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
}
|
||||
.wangEditor-drop-panel .tip-triangle,
|
||||
.txt-toolbar .tip-triangle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 5px solid;
|
||||
border-color: transparent transparent #666 transparent;
|
||||
top: -12px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
}
|
||||
.wangEditor-drop-panel a,
|
||||
.txt-toolbar a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.wangEditor-drop-panel input[type=text],
|
||||
.txt-toolbar input[type=text] {
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-size: 14px;
|
||||
height: 20px;
|
||||
color: #333;
|
||||
padding: 3px 0;
|
||||
}
|
||||
.wangEditor-drop-panel input[type=text]:focus,
|
||||
.txt-toolbar input[type=text]:focus {
|
||||
outline: none;
|
||||
border-bottom: 2px solid #1e88e5;
|
||||
}
|
||||
.wangEditor-drop-panel input[type=text].block,
|
||||
.txt-toolbar input[type=text].block {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.wangEditor-drop-panel textarea,
|
||||
.txt-toolbar textarea {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.wangEditor-drop-panel textarea:focus,
|
||||
.txt-toolbar textarea:focus {
|
||||
outline: none;
|
||||
border-color: #1e88e5;
|
||||
}
|
||||
.wangEditor-drop-panel button,
|
||||
.txt-toolbar button {
|
||||
font-size: 14px;
|
||||
color: #1e88e5;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.wangEditor-drop-panel button:hover,
|
||||
.txt-toolbar button:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-drop-panel button:focus,
|
||||
.txt-toolbar button:focus {
|
||||
outline: none;
|
||||
}
|
||||
.wangEditor-drop-panel button.right,
|
||||
.txt-toolbar button.right {
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.wangEditor-drop-panel button.gray,
|
||||
.txt-toolbar button.gray {
|
||||
color: #999;
|
||||
}
|
||||
.wangEditor-drop-panel button.link,
|
||||
.txt-toolbar button.link {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.wangEditor-drop-panel button.link:hover,
|
||||
.txt-toolbar button.link:hover {
|
||||
background-color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.wangEditor-drop-panel .color-item,
|
||||
.txt-toolbar .color-item {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.wangEditor-drop-panel .color-item:hover,
|
||||
.txt-toolbar .color-item:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-drop-panel .list-menu-item,
|
||||
.txt-toolbar .list-menu-item {
|
||||
display: block;
|
||||
float: left;
|
||||
color: #333;
|
||||
padding: 5px 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.wangEditor-drop-panel .list-menu-item:hover,
|
||||
.txt-toolbar .list-menu-item:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-drop-panel table.choose-table,
|
||||
.txt-toolbar table.choose-table {
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.wangEditor-drop-panel table.choose-table td,
|
||||
.txt-toolbar table.choose-table td {
|
||||
border: 1px solid #ccc;
|
||||
width: 16px;
|
||||
height: 12px;
|
||||
}
|
||||
.wangEditor-drop-panel table.choose-table td.active,
|
||||
.txt-toolbar table.choose-table td.active {
|
||||
background-color: #ccc;
|
||||
opacity: .5;
|
||||
filter: alpha(opacity=50);
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .tab-container,
|
||||
.txt-toolbar .panel-tab .tab-container {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .tab-container a,
|
||||
.txt-toolbar .panel-tab .tab-container a {
|
||||
display: inline-block;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
margin: 0 5px;
|
||||
padding: 5px 5px;
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .tab-container a.selected,
|
||||
.txt-toolbar .panel-tab .tab-container a.selected {
|
||||
color: #1e88e5;
|
||||
border-bottom: 2px solid #1e88e5;
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .content-container .content,
|
||||
.txt-toolbar .panel-tab .content-container .content {
|
||||
display: none;
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .content-container .content a,
|
||||
.txt-toolbar .panel-tab .content-container .content a {
|
||||
display: inline-block;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .content-container .content a:hover,
|
||||
.txt-toolbar .panel-tab .content-container .content a:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .content-container .selected,
|
||||
.txt-toolbar .panel-tab .content-container .selected {
|
||||
display: block;
|
||||
}
|
||||
.wangEditor-drop-panel .panel-tab .emotion-content-container,
|
||||
.txt-toolbar .panel-tab .emotion-content-container {
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.wangEditor-drop-panel .upload-icon-container,
|
||||
.txt-toolbar .upload-icon-container {
|
||||
color: #ccc;
|
||||
text-align: center;
|
||||
margin: 20px 20px 15px 20px !important;
|
||||
padding: 5px !important;
|
||||
font-size: 65px;
|
||||
cursor: pointer;
|
||||
border: 2px dotted #f1f1f1;
|
||||
display: block !important;
|
||||
}
|
||||
.wangEditor-drop-panel .upload-icon-container:hover,
|
||||
.txt-toolbar .upload-icon-container:hover {
|
||||
color: #666;
|
||||
border-color: #ccc;
|
||||
}
|
||||
.wangEditor-modal {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #f1f1f1;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
border-top: 1px\9 solid\9 #ccc\9;
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
}
|
||||
.wangEditor-modal .wangEditor-modal-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin-top: -25px;
|
||||
margin-right: -25px;
|
||||
font-size: 1.5em;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'icomoon';
|
||||
src: url('../fonts/icomoon.eot?-qdfu1s');
|
||||
src: url('../fonts/icomoon.eot?#iefix-qdfu1s') format('embedded-opentype'), url('../fonts/icomoon.ttf?-qdfu1s') format('truetype'), url('../fonts/icomoon.woff?-qdfu1s') format('woff'), url('../fonts/icomoon.svg?-qdfu1s#icomoon') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
[class^="wangeditor-menu-img-"],
|
||||
[class*=" wangeditor-menu-img-"] {
|
||||
font-family: 'icomoon';
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
/* Better Font Rendering =========== */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.wangeditor-menu-img-link:before {
|
||||
content: "\e800";
|
||||
}
|
||||
.wangeditor-menu-img-unlink:before {
|
||||
content: "\e801";
|
||||
}
|
||||
.wangeditor-menu-img-code:before {
|
||||
content: "\e802";
|
||||
}
|
||||
.wangeditor-menu-img-cancel:before {
|
||||
content: "\e803";
|
||||
}
|
||||
.wangeditor-menu-img-terminal:before {
|
||||
content: "\e804";
|
||||
}
|
||||
.wangeditor-menu-img-angle-down:before {
|
||||
content: "\e805";
|
||||
}
|
||||
.wangeditor-menu-img-font:before {
|
||||
content: "\e806";
|
||||
}
|
||||
.wangeditor-menu-img-bold:before {
|
||||
content: "\e807";
|
||||
}
|
||||
.wangeditor-menu-img-italic:before {
|
||||
content: "\e808";
|
||||
}
|
||||
.wangeditor-menu-img-header:before {
|
||||
content: "\e809";
|
||||
}
|
||||
.wangeditor-menu-img-align-left:before {
|
||||
content: "\e80a";
|
||||
}
|
||||
.wangeditor-menu-img-align-center:before {
|
||||
content: "\e80b";
|
||||
}
|
||||
.wangeditor-menu-img-align-right:before {
|
||||
content: "\e80c";
|
||||
}
|
||||
.wangeditor-menu-img-list-bullet:before {
|
||||
content: "\e80d";
|
||||
}
|
||||
.wangeditor-menu-img-indent-left:before {
|
||||
content: "\e80e";
|
||||
}
|
||||
.wangeditor-menu-img-indent-right:before {
|
||||
content: "\e80f";
|
||||
}
|
||||
.wangeditor-menu-img-list-numbered:before {
|
||||
content: "\e810";
|
||||
}
|
||||
.wangeditor-menu-img-underline:before {
|
||||
content: "\e811";
|
||||
}
|
||||
.wangeditor-menu-img-table:before {
|
||||
content: "\e812";
|
||||
}
|
||||
.wangeditor-menu-img-eraser:before {
|
||||
content: "\e813";
|
||||
}
|
||||
.wangeditor-menu-img-text-height:before {
|
||||
content: "\e814";
|
||||
}
|
||||
.wangeditor-menu-img-brush:before {
|
||||
content: "\e815";
|
||||
}
|
||||
.wangeditor-menu-img-pencil:before {
|
||||
content: "\e816";
|
||||
}
|
||||
.wangeditor-menu-img-minus:before {
|
||||
content: "\e817";
|
||||
}
|
||||
.wangeditor-menu-img-picture:before {
|
||||
content: "\e818";
|
||||
}
|
||||
.wangeditor-menu-img-file-image:before {
|
||||
content: "\e819";
|
||||
}
|
||||
.wangeditor-menu-img-cw:before {
|
||||
content: "\e81a";
|
||||
}
|
||||
.wangeditor-menu-img-ccw:before {
|
||||
content: "\e81b";
|
||||
}
|
||||
.wangeditor-menu-img-music:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.wangeditor-menu-img-play:before {
|
||||
content: "\e912";
|
||||
}
|
||||
.wangeditor-menu-img-location:before {
|
||||
content: "\e947";
|
||||
}
|
||||
.wangeditor-menu-img-happy:before {
|
||||
content: "\e9df";
|
||||
}
|
||||
.wangeditor-menu-img-sigma:before {
|
||||
content: "\ea67";
|
||||
}
|
||||
.wangeditor-menu-img-enlarge2:before {
|
||||
content: "\e98b";
|
||||
}
|
||||
.wangeditor-menu-img-shrink2:before {
|
||||
content: "\e98c";
|
||||
}
|
||||
.wangeditor-menu-img-newspaper:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.wangeditor-menu-img-camera:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.wangeditor-menu-img-video-camera:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.wangeditor-menu-img-file-zip:before {
|
||||
content: "\e92b";
|
||||
}
|
||||
.wangeditor-menu-img-stack:before {
|
||||
content: "\e92e";
|
||||
}
|
||||
.wangeditor-menu-img-credit-card:before {
|
||||
content: "\e93f";
|
||||
}
|
||||
.wangeditor-menu-img-address-book:before {
|
||||
content: "\e944";
|
||||
}
|
||||
.wangeditor-menu-img-envelop:before {
|
||||
content: "\e945";
|
||||
}
|
||||
.wangeditor-menu-img-drawer:before {
|
||||
content: "\e95c";
|
||||
}
|
||||
.wangeditor-menu-img-download:before {
|
||||
content: "\e960";
|
||||
}
|
||||
.wangeditor-menu-img-upload:before {
|
||||
content: "\e961";
|
||||
}
|
||||
.wangeditor-menu-img-lock:before {
|
||||
content: "\e98f";
|
||||
}
|
||||
.wangeditor-menu-img-unlocked:before {
|
||||
content: "\e990";
|
||||
}
|
||||
.wangeditor-menu-img-wrench:before {
|
||||
content: "\e991";
|
||||
}
|
||||
.wangeditor-menu-img-eye:before {
|
||||
content: "\e9ce";
|
||||
}
|
||||
.wangeditor-menu-img-eye-blocked:before {
|
||||
content: "\e9d1";
|
||||
}
|
||||
.wangeditor-menu-img-command:before {
|
||||
content: "\ea4e";
|
||||
}
|
||||
.wangeditor-menu-img-font2:before {
|
||||
content: "\ea5c";
|
||||
}
|
||||
.wangeditor-menu-img-libreoffice:before {
|
||||
content: "\eade";
|
||||
}
|
||||
.wangeditor-menu-img-quotes-left:before {
|
||||
content: "\e977";
|
||||
}
|
||||
.wangeditor-menu-img-strikethrough:before {
|
||||
content: "\ea65";
|
||||
}
|
||||
.wangeditor-menu-img-desktop:before {
|
||||
content: "\f108";
|
||||
}
|
||||
.wangeditor-menu-img-tablet:before {
|
||||
content: "\f10a";
|
||||
}
|
||||
.wangeditor-menu-img-search-plus:before {
|
||||
content: "\f00e";
|
||||
}
|
||||
.wangeditor-menu-img-search-minus:before {
|
||||
content: "\f010";
|
||||
}
|
||||
.wangeditor-menu-img-trash-o:before {
|
||||
content: "\f014";
|
||||
}
|
||||
.wangeditor-menu-img-align-justify:before {
|
||||
content: "\f039";
|
||||
}
|
||||
.wangeditor-menu-img-arrows-v:before {
|
||||
content: "\f07d";
|
||||
}
|
||||
.wangeditor-menu-img-sigma2:before {
|
||||
content: "\ea68";
|
||||
}
|
||||
.wangeditor-menu-img-omega:before {
|
||||
content: "\e900";
|
||||
}
|
||||
.wangeditor-menu-img-cancel-circle:before {
|
||||
content: "\e901";
|
||||
}
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #333;
|
||||
background: #f8f8f8;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
.hljs-comment,
|
||||
.diff .hljs-header {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
.hljs-keyword,
|
||||
.css .rule .hljs-keyword,
|
||||
.hljs-winutils,
|
||||
.nginx .hljs-title,
|
||||
.hljs-subst,
|
||||
.hljs-request,
|
||||
.hljs-status {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
.hljs-number,
|
||||
.hljs-hexcolor,
|
||||
.ruby .hljs-constant {
|
||||
color: #008080;
|
||||
}
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-doctag,
|
||||
.tex .hljs-formula {
|
||||
color: #d14;
|
||||
}
|
||||
.hljs-title,
|
||||
.hljs-id,
|
||||
.scss .hljs-preprocessor {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
.hljs-list .hljs-keyword,
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-type,
|
||||
.vhdl .hljs-literal,
|
||||
.tex .hljs-command {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
.hljs-tag,
|
||||
.hljs-tag .hljs-title,
|
||||
.hljs-rule .hljs-property,
|
||||
.django .hljs-tag .hljs-keyword {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
.hljs-attribute,
|
||||
.hljs-variable,
|
||||
.lisp .hljs-body,
|
||||
.hljs-name {
|
||||
color: #008080;
|
||||
}
|
||||
.hljs-regexp {
|
||||
color: #009926;
|
||||
}
|
||||
.hljs-symbol,
|
||||
.ruby .hljs-symbol .hljs-string,
|
||||
.lisp .hljs-keyword,
|
||||
.clojure .hljs-keyword,
|
||||
.scheme .hljs-keyword,
|
||||
.tex .hljs-special,
|
||||
.hljs-prompt {
|
||||
color: #990073;
|
||||
}
|
||||
.hljs-built_in {
|
||||
color: #0086b3;
|
||||
}
|
||||
.hljs-preprocessor,
|
||||
.hljs-pragma,
|
||||
.hljs-pi,
|
||||
.hljs-doctype,
|
||||
.hljs-shebang,
|
||||
.hljs-cdata {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
.diff .hljs-change {
|
||||
background: #0086b3;
|
||||
}
|
||||
.hljs-chunk {
|
||||
color: #aaa;
|
||||
}
|
|
@ -1,810 +0,0 @@
|
|||
|
||||
// ---------- begin 全局颜色配置 ------------
|
||||
|
||||
/* 编辑器边框颜色 */
|
||||
@border-color: #ccc;
|
||||
|
||||
/* 菜单颜色、上边框颜色 */
|
||||
@fore-color: #666;
|
||||
|
||||
/* 菜单选中状态的颜色 */
|
||||
@selected-color: #1e88e5;
|
||||
|
||||
/* input focus 时的颜色 */
|
||||
@focus-input-color: #1e88e5;
|
||||
|
||||
/* 按钮颜色 */
|
||||
@button-color: #1e88e5;
|
||||
|
||||
/* tab selected 状态下的颜色 */
|
||||
@selected-tab-color: #1e88e5;
|
||||
|
||||
// ---------- end 全局颜色配置 ------------
|
||||
|
||||
|
||||
.wangEditor-container {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
border: 1px solid @border-color;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
|
||||
a:focus,
|
||||
button:focus{
|
||||
outline:none;
|
||||
}
|
||||
|
||||
&,* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
textarea {
|
||||
border: none;
|
||||
&:focus{
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示p head 高度的 tip
|
||||
.height-tip {
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
background-color: #ccc;
|
||||
left: 0;
|
||||
transition: top .2s;
|
||||
}
|
||||
|
||||
// 设置 img table 的 toolbar
|
||||
.txt-toolbar {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
padding: 3px 5px;
|
||||
border-top: 2px solid @fore-color;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
|
||||
// for IE8
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
|
||||
// 小三角
|
||||
.tip-triangle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 5px solid;
|
||||
border-color: transparent transparent @fore-color transparent;
|
||||
top: -12px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @fore-color;
|
||||
display: inline-block;
|
||||
margin: 0 3px;
|
||||
padding: 5px;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 图品拖拽大小
|
||||
.img-drag-point {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
cursor: se-resize;
|
||||
background-color: @fore-color;
|
||||
margin-left: -6px;
|
||||
margin-top: -6px;
|
||||
box-shadow: 1px 1px 5px #999;
|
||||
}
|
||||
|
||||
// 进度条
|
||||
.wangEditor-upload-progress {
|
||||
position: absolute;
|
||||
height: 1px;
|
||||
background: #1e88e5;
|
||||
width: 0;
|
||||
display: none;
|
||||
-webkit-transition: width .5s;
|
||||
-o-transition: width .5s;
|
||||
transition: width .5s;
|
||||
}
|
||||
}
|
||||
.wangEditor-fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.wangEditor-container {
|
||||
.code-textarea {
|
||||
resize: none;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
font-family: 'Verdana';
|
||||
color: #333;
|
||||
padding: 0 15px 0 15px;
|
||||
}
|
||||
}
|
||||
.wangEditor-menu-container {
|
||||
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
background-color: #fff;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
// 菜单组
|
||||
.menu-group {
|
||||
float: left;
|
||||
padding: 0 8px;
|
||||
border-right: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
// 单个菜单容器
|
||||
.menu-item {
|
||||
float: left;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
height: 31px;
|
||||
width: 35px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
// 菜单
|
||||
a {
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: @fore-color;
|
||||
width: 100%;
|
||||
padding: 8px 0;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
// 菜单选中状态
|
||||
.selected {
|
||||
color: @selected-color;
|
||||
}
|
||||
|
||||
// 激活状态
|
||||
.active {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
// 禁用状态
|
||||
.disable {
|
||||
opacity: 0.5;
|
||||
filter: Alpha(opacity=50);
|
||||
}
|
||||
}
|
||||
|
||||
// tip提示
|
||||
.menu-tip {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
background-color: @fore-color;
|
||||
color: #fff;
|
||||
padding: 7px 0;
|
||||
font-size: 12px;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -30px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 1px 1px 5px #999;
|
||||
|
||||
display: none;
|
||||
|
||||
/*// 小三角
|
||||
.tip-triangle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border:5px solid;
|
||||
border-color: transparent transparent @fore-color transparent;
|
||||
top: -10px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
}*/
|
||||
}
|
||||
.menu-tip-40 {
|
||||
width: 40px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
.menu-tip-50 {
|
||||
width: 50px;
|
||||
margin-left: -25px;
|
||||
}
|
||||
}
|
||||
.wangEditor-menu-shadow {
|
||||
/*border-bottom-width: 0;*/
|
||||
border-bottom: 1px\9 solid\9 #f1f1f1\9;
|
||||
box-shadow: 0 1px 3px #999;
|
||||
}
|
||||
.wangEditor-container {
|
||||
.wangEditor-txt{
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 15px;
|
||||
padding-top: 0;
|
||||
margin-top: 5px;
|
||||
overflow-y: auto;
|
||||
|
||||
p,h1,h2,h3,h4,h5 {
|
||||
margin: 10px 0;
|
||||
line-height: 1.8;
|
||||
|
||||
* {
|
||||
line-height: 1.8;
|
||||
}
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
cursor: pointer;
|
||||
}
|
||||
img.clicked {
|
||||
box-shadow: 1px 1px 10px #999;
|
||||
}
|
||||
|
||||
table.clicked {
|
||||
box-shadow: 1px 1px 10px #999;
|
||||
}
|
||||
|
||||
pre code {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
&:focus{
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.wangEditor-container {
|
||||
.wangEditor-txt {
|
||||
blockquote {
|
||||
display: block;
|
||||
border-left: 8px solid #d0e5f2;
|
||||
padding: 5px 10px;
|
||||
margin: 10px 0;
|
||||
line-height: 1.4;
|
||||
font-size: 100%;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
table {
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table td,
|
||||
table th {
|
||||
border: 1px solid #999;
|
||||
padding: 3px 5px;
|
||||
min-width: 50px;
|
||||
height: 20px;
|
||||
}
|
||||
pre {
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f8f8f8;
|
||||
padding: 10px;
|
||||
margin: 5px 0px;
|
||||
font-size: 0.8em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.wangEditor-drop-list {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
|
||||
transition: height .7s;
|
||||
|
||||
border-top: 1px solid #f1f1f1;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
|
||||
// for IE8
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
color: @fore-color;
|
||||
padding: 3px 5px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.wangEditor-drop-panel,
|
||||
.txt-toolbar {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
/*border: 1px\9 solid\9 #cccccc\9;*/
|
||||
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
|
||||
border-top: 2px solid @fore-color;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
|
||||
// for IE8
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
|
||||
// 小三角
|
||||
.tip-triangle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 5px solid;
|
||||
border-color: transparent transparent @fore-color transparent;
|
||||
top: -12px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
// 输入框
|
||||
input[type=text] {
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-size: 14px;
|
||||
height: 20px;
|
||||
color: #333;
|
||||
padding: 3px 0;
|
||||
|
||||
&:focus{
|
||||
outline: none;
|
||||
border-bottom: 2px solid @focus-input-color;
|
||||
}
|
||||
}
|
||||
input[type=text].block {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
textarea {
|
||||
border: 1px solid #ccc;
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: @focus-input-color;
|
||||
}
|
||||
}
|
||||
|
||||
// 按钮
|
||||
button {
|
||||
font-size: 14px;
|
||||
color: @button-color;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
&:focus{
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
button.right {
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
}
|
||||
button.gray {
|
||||
color: #999;
|
||||
}
|
||||
button.link {
|
||||
padding: 5px 10px;
|
||||
&:hover {
|
||||
background-color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
// 颜色块
|
||||
.color-item {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
}
|
||||
|
||||
// 列表
|
||||
.list-menu-item {
|
||||
display: block;
|
||||
float: left;
|
||||
color: #333;
|
||||
padding: 5px 5px;
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
}
|
||||
|
||||
// 表格
|
||||
table.choose-table {
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
|
||||
td {
|
||||
border: 1px solid #ccc;
|
||||
width: 16px;
|
||||
height: 12px;
|
||||
}
|
||||
td.active {
|
||||
background-color: #ccc;
|
||||
opacity: .5;
|
||||
filter: Alpha(opacity=50);
|
||||
}
|
||||
}
|
||||
|
||||
// tab
|
||||
.panel-tab {
|
||||
.tab-container {
|
||||
margin-bottom: 5px;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
margin: 0 5px;
|
||||
padding: 5px 5px;
|
||||
}
|
||||
|
||||
a.selected {
|
||||
color: @selected-tab-color;
|
||||
border-bottom: 2px solid @selected-tab-color;
|
||||
}
|
||||
}
|
||||
.content-container {
|
||||
.content {
|
||||
display: none;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.selected {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.emotion-content-container {
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 上传图片
|
||||
.upload-icon-container {
|
||||
color: #ccc;
|
||||
text-align: center;
|
||||
margin: 20px 20px 15px 20px !important;
|
||||
padding: 5px !important;
|
||||
font-size: 65px;
|
||||
cursor: pointer;
|
||||
border: 2px dotted #f1f1f1;
|
||||
display: block !important;
|
||||
|
||||
&:hover {
|
||||
color: #666;
|
||||
border-color: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
.wangEditor-modal {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background-color: #fff;
|
||||
|
||||
border-top: 1px solid #f1f1f1;
|
||||
box-shadow: 1px 3px 3px #999;
|
||||
|
||||
// for IE8
|
||||
border-top: 1px\9 solid\9 #ccc\9;
|
||||
border-left: 1px\9 solid\9 #ccc\9;
|
||||
border-bottom: 1px\9 solid\9 #999\9;
|
||||
border-right: 1px\9 solid\9 #999\9;
|
||||
|
||||
// 关闭按钮
|
||||
.wangEditor-modal-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin-top: -25px;
|
||||
margin-right: -25px;
|
||||
font-size: 1.5em;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'icomoon';
|
||||
src:url('../fonts/icomoon.eot?-qdfu1s');
|
||||
src:url('../fonts/icomoon.eot?#iefix-qdfu1s') format('embedded-opentype'),
|
||||
url('../fonts/icomoon.ttf?-qdfu1s') format('truetype'),
|
||||
url('../fonts/icomoon.woff?-qdfu1s') format('woff'),
|
||||
url('../fonts/icomoon.svg?-qdfu1s#icomoon') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[class^="wangeditor-menu-img-"], [class*=" wangeditor-menu-img-"] {
|
||||
font-family: 'icomoon';
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
|
||||
/* Better Font Rendering =========== */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.wangeditor-menu-img-link:before {content: "\e800";}
|
||||
.wangeditor-menu-img-unlink:before {content: "\e801";}
|
||||
.wangeditor-menu-img-code:before {content: "\e802";}
|
||||
.wangeditor-menu-img-cancel:before {content: "\e803";}
|
||||
.wangeditor-menu-img-terminal:before {content: "\e804";}
|
||||
.wangeditor-menu-img-angle-down:before {content: "\e805";}
|
||||
.wangeditor-menu-img-font:before {content: "\e806";}
|
||||
.wangeditor-menu-img-bold:before {content: "\e807";}
|
||||
.wangeditor-menu-img-italic:before {content: "\e808";}
|
||||
.wangeditor-menu-img-header:before {content: "\e809";}
|
||||
.wangeditor-menu-img-align-left:before {content: "\e80a";}
|
||||
.wangeditor-menu-img-align-center:before {content: "\e80b";}
|
||||
.wangeditor-menu-img-align-right:before {content: "\e80c";}
|
||||
.wangeditor-menu-img-list-bullet:before {content: "\e80d";}
|
||||
.wangeditor-menu-img-indent-left:before {content: "\e80e";}
|
||||
.wangeditor-menu-img-indent-right:before {content: "\e80f";}
|
||||
.wangeditor-menu-img-list-numbered:before {content: "\e810";}
|
||||
.wangeditor-menu-img-underline:before {content: "\e811";}
|
||||
.wangeditor-menu-img-table:before {content: "\e812";}
|
||||
.wangeditor-menu-img-eraser:before {content: "\e813";}
|
||||
.wangeditor-menu-img-text-height:before {content: "\e814";}
|
||||
.wangeditor-menu-img-brush:before {content: "\e815";}
|
||||
.wangeditor-menu-img-pencil:before {content: "\e816";}
|
||||
.wangeditor-menu-img-minus:before {content: "\e817";}
|
||||
.wangeditor-menu-img-picture:before {content: "\e818";}
|
||||
.wangeditor-menu-img-file-image:before {content: "\e819";}
|
||||
.wangeditor-menu-img-cw:before {content: "\e81a";}
|
||||
.wangeditor-menu-img-ccw:before {content: "\e81b";}
|
||||
.wangeditor-menu-img-music:before {content: "\e911";}
|
||||
.wangeditor-menu-img-play:before {content: "\e912";}
|
||||
.wangeditor-menu-img-location:before {content: "\e947";}
|
||||
.wangeditor-menu-img-happy:before {content: "\e9df";}
|
||||
.wangeditor-menu-img-sigma:before {content: "\ea67";}
|
||||
.wangeditor-menu-img-enlarge2:before {content: "\e98b";}
|
||||
.wangeditor-menu-img-shrink2:before {content: "\e98c";}
|
||||
.wangeditor-menu-img-newspaper:before{content: "\e904";}
|
||||
.wangeditor-menu-img-camera:before{content: "\e90f";}
|
||||
.wangeditor-menu-img-video-camera:before{content: "\e914";}
|
||||
.wangeditor-menu-img-file-zip:before{content: "\e92b";}
|
||||
.wangeditor-menu-img-stack:before{content: "\e92e";}
|
||||
.wangeditor-menu-img-credit-card:before{content: "\e93f";}
|
||||
.wangeditor-menu-img-address-book:before{content: "\e944";}
|
||||
.wangeditor-menu-img-envelop:before{content: "\e945";}
|
||||
.wangeditor-menu-img-drawer:before{content: "\e95c";}
|
||||
.wangeditor-menu-img-download:before{content: "\e960";}
|
||||
.wangeditor-menu-img-upload:before{content: "\e961";}
|
||||
.wangeditor-menu-img-lock:before{content: "\e98f";}
|
||||
.wangeditor-menu-img-unlocked:before{content: "\e990";}
|
||||
.wangeditor-menu-img-wrench:before{content: "\e991";}
|
||||
.wangeditor-menu-img-eye:before{content: "\e9ce";}
|
||||
.wangeditor-menu-img-eye-blocked:before{content: "\e9d1";}
|
||||
.wangeditor-menu-img-command:before{content: "\ea4e";}
|
||||
.wangeditor-menu-img-font2:before{content: "\ea5c";}
|
||||
.wangeditor-menu-img-libreoffice:before{content: "\eade";}
|
||||
.wangeditor-menu-img-quotes-left:before{content: "\e977";}
|
||||
.wangeditor-menu-img-strikethrough:before{content: "\ea65";}
|
||||
.wangeditor-menu-img-desktop:before{content: "\f108";}
|
||||
.wangeditor-menu-img-tablet:before{content: "\f10a";}
|
||||
.wangeditor-menu-img-search-plus:before {
|
||||
content: "\f00e";
|
||||
}
|
||||
.wangeditor-menu-img-search-minus:before {
|
||||
content: "\f010";
|
||||
}
|
||||
.wangeditor-menu-img-trash-o:before {
|
||||
content: "\f014";
|
||||
}
|
||||
.wangeditor-menu-img-align-justify:before {
|
||||
content: "\f039";
|
||||
}
|
||||
.wangeditor-menu-img-arrows-v:before {
|
||||
content: "\f07d";
|
||||
}
|
||||
.wangeditor-menu-img-sigma2:before {
|
||||
content: "\ea68";
|
||||
}
|
||||
.wangeditor-menu-img-omega:before {
|
||||
content: "\e900";
|
||||
}
|
||||
.wangeditor-menu-img-cancel-circle:before {
|
||||
content: "\e901";
|
||||
}
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #333;
|
||||
background: #f8f8f8;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.diff .hljs-header {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.css .rule .hljs-keyword,
|
||||
.hljs-winutils,
|
||||
.nginx .hljs-title,
|
||||
.hljs-subst,
|
||||
.hljs-request,
|
||||
.hljs-status {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-hexcolor,
|
||||
.ruby .hljs-constant {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-doctag,
|
||||
.tex .hljs-formula {
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-id,
|
||||
.scss .hljs-preprocessor {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-list .hljs-keyword,
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-type,
|
||||
.vhdl .hljs-literal,
|
||||
.tex .hljs-command {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-tag .hljs-title,
|
||||
.hljs-rule .hljs-property,
|
||||
.django .hljs-tag .hljs-keyword {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-attribute,
|
||||
.hljs-variable,
|
||||
.lisp .hljs-body,
|
||||
.hljs-name {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-regexp {
|
||||
color: #009926;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.ruby .hljs-symbol .hljs-string,
|
||||
.lisp .hljs-keyword,
|
||||
.clojure .hljs-keyword,
|
||||
.scheme .hljs-keyword,
|
||||
.tex .hljs-special,
|
||||
.hljs-prompt {
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
.hljs-built_in {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-preprocessor,
|
||||
.hljs-pragma,
|
||||
.hljs-pi,
|
||||
.hljs-doctype,
|
||||
.hljs-shebang,
|
||||
.hljs-cdata {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
.diff .hljs-change {
|
||||
background: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-chunk {
|
||||
color: #aaa;
|
||||
}
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="link" horiz-adv-x="950" d="M831.488 264.704q0 23.552-15.36 38.912l-118.784 118.784q-16.384 16.384-38.912 16.384-24.576 0-40.96-18.432 1.024-1.024 10.24-10.24t12.288-12.288 9.216-11.264 7.168-14.336 2.048-15.36q0-23.552-16.384-38.912t-38.912-16.384q-8.192 0-15.36 2.048t-14.336 7.168-11.264 9.216-12.288 12.288-10.24 10.24q-19.456-17.408-19.456-40.96t16.384-38.912l117.76-118.784q15.36-15.36 38.912-15.36 22.528 0 38.912 15.36l83.968 82.944q15.36 16.384 15.36 37.888zM430.080 668.16q0 22.528-15.36 38.912l-117.76 117.76q-16.384 16.384-38.912 16.384t-38.912-15.36l-83.968-83.968q-16.384-15.36-16.384-37.888t16.384-38.912l118.784-118.784q15.36-15.36 38.912-15.36t40.96 17.408q-2.048 2.048-11.264 11.264t-12.288 12.288-8.192 10.24-7.168 14.336-2.048 16.384q0 22.528 15.36 38.912t38.912 15.36q9.216 0 16.384-2.048t14.336-7.168 10.24-8.192 12.288-12.288 11.264-11.264q18.432 17.408 18.432 41.984zM942.080 264.704q0-68.608-49.152-115.712l-83.968-82.944q-47.104-48.128-115.712-48.128-69.632 0-116.736 49.152l-117.76 117.76q-47.104 48.128-47.104 116.736 0 69.632 50.176 118.784l-50.176 50.176q-49.152-50.176-118.784-50.176-68.608 0-116.736 48.128l-118.784 118.784q-48.128 48.128-48.128 116.736t48.128 115.712l83.968 83.968q48.128 47.104 116.736 47.104t116.736-48.128l116.736-118.784q48.128-47.104 48.128-115.712 0-70.656-50.176-119.808l50.176-50.176q49.152 50.176 118.784 50.176 68.608 0 116.736-48.128l118.784-118.784q48.128-48.128 48.128-116.736z" />
|
||||
<glyph unicode="" glyph-name="unlink" horiz-adv-x="950" d="M250.88 233.984l-146.432-146.432q-5.12-5.12-13.312-5.12-6.144 0-13.312 5.12-5.12 5.12-5.12 13.312t5.12 13.312l146.432 145.408q6.144 5.12 13.312 5.12t13.312-5.12q5.12-5.12 5.12-12.288t-5.12-13.312zM347.136 210.432v-183.296q0-8.192-5.12-13.312t-13.312-5.12-12.288 5.12-5.12 13.312v183.296q0 8.192 5.12 13.312t12.288 5.12 13.312-5.12 5.12-13.312zM219.136 338.432q0-8.192-5.12-13.312t-13.312-5.12h-182.272q-8.192 0-13.312 5.12t-5.12 13.312 5.12 13.312 13.312 5.12h182.272q8.192 0 13.312-5.12t5.12-13.312zM942.080 264.704q0-68.608-49.152-115.712l-83.968-82.944q-47.104-48.128-115.712-48.128-69.632 0-116.736 49.152l-190.464 191.488q-12.288 11.264-24.576 31.744l137.216 10.24 155.648-156.672q15.36-15.36 38.912-15.36t38.912 15.36l83.968 82.944q15.36 16.384 15.36 37.888 0 23.552-15.36 38.912l-156.672 157.696 10.24 136.192q20.48-12.288 31.744-23.552l192.512-192.512q48.128-49.152 48.128-116.736zM588.8 678.4l-136.192-10.24-155.648 156.672q-16.384 16.384-38.912 16.384t-38.912-15.36l-83.968-83.968q-16.384-15.36-16.384-37.888t16.384-38.912l156.672-156.672-10.24-137.216q-20.48 12.288-32.768 24.576l-191.488 191.488q-48.128 49.152-48.128 116.736 0 68.608 48.128 115.712l83.968 83.968q48.128 47.104 116.736 47.104t116.736-48.128l190.464-191.488q12.288-12.288 23.552-32.768zM951.296 631.296q0-8.192-5.12-13.312t-13.312-5.12h-183.296q-8.192 0-13.312 5.12t-5.12 13.312 5.12 12.288 13.312 5.12h183.296q8.192 0 13.312-5.12t5.12-12.288zM640 941.568v-182.272q0-8.192-5.12-13.312t-13.312-5.12-13.312 5.12-5.12 13.312v182.272q0 8.192 5.12 13.312t13.312 5.12 13.312-5.12 5.12-13.312zM872.448 855.552l-146.432-146.432q-6.144-5.12-13.312-5.12t-12.288 5.12q-5.12 6.144-5.12 13.312t5.12 13.312l145.408 145.408q6.144 5.12 13.312 5.12t13.312-5.12q5.12-5.12 5.12-12.288t-5.12-13.312z" />
|
||||
<glyph unicode="" glyph-name="code" horiz-adv-x="1097" d="M352.256 160.256l-28.672-28.672q-5.12-5.12-12.288-5.12t-13.312 5.12l-266.24 266.24q-6.144 6.144-6.144 13.312t6.144 13.312l266.24 266.24q5.12 6.144 13.312 6.144t12.288-6.144l28.672-28.672q6.144-5.12 6.144-13.312t-6.144-12.288l-224.256-225.28 224.256-224.256q6.144-6.144 6.144-13.312t-6.144-13.312zM690.176 770.56l-212.992-738.304q-2.048-7.168-9.216-11.264t-13.312-1.024l-34.816 9.216q-8.192 3.072-11.264 9.216t-2.048 14.336l212.992 737.28q3.072 8.192 9.216 11.264t13.312 2.048l35.84-10.24q7.168-2.048 11.264-9.216t1.024-13.312zM1065.984 397.824l-266.24-266.24q-6.144-5.12-13.312-5.12t-13.312 5.12l-28.672 28.672q-5.12 6.144-5.12 13.312t5.12 13.312l224.256 224.256-224.256 225.28q-5.12 5.12-5.12 12.288t5.12 13.312l28.672 28.672q6.144 6.144 13.312 6.144t13.312-6.144l266.24-266.24q5.12-5.12 5.12-13.312t-5.12-13.312z" />
|
||||
<glyph unicode="" glyph-name="cancel" horiz-adv-x="804" d="M741.376 204.288q0-22.528-15.36-38.912l-77.824-77.824q-16.384-15.36-38.912-15.36t-38.912 15.36l-167.936 168.96-167.936-168.96q-16.384-15.36-38.912-15.36t-38.912 15.36l-77.824 77.824q-16.384 16.384-16.384 38.912t16.384 38.912l167.936 167.936-167.936 167.936q-16.384 16.384-16.384 38.912t16.384 38.912l77.824 77.824q16.384 16.384 38.912 16.384t38.912-16.384l167.936-167.936 167.936 167.936q16.384 16.384 38.912 16.384t38.912-16.384l77.824-77.824q15.36-15.36 15.36-38.912t-15.36-38.912l-167.936-167.936 167.936-167.936q15.36-15.36 15.36-38.912z" />
|
||||
<glyph unicode="" glyph-name="terminal" horiz-adv-x="950" d="M333.824 397.824l-266.24-266.24q-5.12-5.12-12.288-5.12t-13.312 5.12l-28.672 28.672q-6.144 6.144-6.144 13.312t6.144 13.312l224.256 224.256-224.256 225.28q-6.144 5.12-6.144 12.288t6.144 13.312l28.672 28.672q5.12 6.144 13.312 6.144t12.288-6.144l266.24-266.24q6.144-5.12 6.144-13.312t-6.144-13.312zM951.296 136.704v-35.84q0-8.192-5.12-13.312t-13.312-5.12h-548.864q-8.192 0-13.312 5.12t-5.12 13.312v35.84q0 8.192 5.12 13.312t13.312 5.12h548.864q8.192 0 13.312-5.12t5.12-13.312z" />
|
||||
<glyph unicode="" glyph-name="angle-down" horiz-adv-x="657" d="M614.4 539.136q0-7.168-6.144-13.312l-266.24-266.24q-5.12-5.12-13.312-5.12t-12.288 5.12l-266.24 266.24q-6.144 6.144-6.144 13.312t6.144 13.312l27.648 28.672q6.144 6.144 13.312 6.144t13.312-6.144l224.256-224.256 225.28 224.256q5.12 6.144 13.312 6.144t12.288-6.144l28.672-28.672q6.144-5.12 6.144-13.312z" />
|
||||
<glyph unicode="" glyph-name="font" horiz-adv-x="950" d="M414.72 640.512l-97.28-257.024q18.432 0 77.824-1.024t91.136-1.024q11.264 0 32.768 1.024-49.152 144.384-104.448 258.048zM0 8.704l1.024 45.056q13.312 4.096 31.744 7.168t32.768 6.144 28.672 8.192 25.6 17.408 17.408 28.672l135.168 352.256 159.744 413.696h73.728q4.096-8.192 6.144-12.288l116.736-274.432q19.456-45.056 61.44-147.456t64.512-156.672q9.216-19.456 33.792-82.944t40.96-96.256q11.264-25.6 19.456-31.744 11.264-9.216 50.176-17.408t48.128-11.264q4.096-22.528 4.096-32.768 0-2.048-1.024-7.168t0-8.192q-35.84 0-108.544 5.12t-109.568 4.096q-43.008 0-122.88-4.096t-101.376-4.096q0 24.576 2.048 44.032l74.752 16.384q1.024 0 7.168 1.024t9.216 2.048 8.192 3.072 9.216 4.096 6.144 4.096 5.12 6.144 1.024 8.192q0 9.216-17.408 55.296t-40.96 101.376-24.576 57.344l-257.024 1.024q-14.336-33.792-44.032-111.616t-28.672-93.184q0-12.288 8.192-21.504t24.576-14.336 27.648-7.168 32.768-5.12 23.552-2.048q1.024-11.264 1.024-32.768 0-5.12-2.048-16.384-32.768 0-99.328 6.144t-99.328 6.144q-5.12 0-15.36-3.072t-12.288-2.048q-46.080-8.192-107.52-8.192z" />
|
||||
<glyph unicode="" glyph-name="bold" horiz-adv-x="804" d="M317.44 90.624q41.984-18.432 79.872-18.432 215.040 0 215.040 191.488 0 65.536-23.552 103.424-15.36 24.576-35.84 41.984t-37.888 26.624-46.080 14.336-48.128 6.144-54.272 1.024q-40.96 0-57.344-6.144 0-29.696 0-90.112t-1.024-91.136q0-4.096 0-37.888t0-55.296 2.048-48.128 7.168-37.888zM309.248 517.632q23.552-4.096 62.464-4.096 47.104 0 81.92 7.168t62.464 25.6 41.984 51.2 15.36 80.896q0 39.936-16.384 69.632t-46.080 47.104-61.44 24.576-70.656 8.192q-28.672 0-74.752-7.168 0-28.672 3.072-86.016t2.048-87.040q0-15.36 0-46.080t-1.024-45.056q0-26.624 1.024-38.912zM0 8.704l1.024 54.272q9.216 2.048 49.152 9.216t60.416 15.36q4.096 7.168 7.168 15.36t4.096 19.456 4.096 18.432 1.024 21.504 0 19.456v36.864q0 561.152-12.288 585.728-2.048 5.12-12.288 8.192t-25.6 6.144-28.672 4.096-27.648 3.072-17.408 2.048l-2.048 47.104q56.32 1.024 194.56 6.144t212.992 5.12q13.312 0 38.912 0t38.912 0q39.936 0 77.824-7.168t73.728-24.576 61.44-39.936 41.984-60.416 16.384-77.824q0-29.696-9.216-55.296t-22.528-40.96-36.864-32.768-41.984-25.6-48.128-22.528q88.064-20.48 147.456-76.8t58.368-142.336q0-56.32-20.48-102.4t-53.248-74.752-78.848-48.128-93.184-27.648-100.352-8.192q-25.6 0-75.776 2.048t-75.776 1.024q-60.416 0-175.104-6.144t-132.096-7.168z" />
|
||||
<glyph unicode="" glyph-name="italic" horiz-adv-x="585" d="M0 9.728l10.24 49.152q3.072 1.024 46.080 12.288t63.488 21.504q16.384 19.456 23.552 57.344 1.024 4.096 35.84 165.888t64.512 310.272 29.696 168.96v14.336q-13.312 7.168-30.72 11.264t-39.936 4.096-32.768 3.072l10.24 59.392q19.456-2.048 68.608-4.096t86.016-4.096 68.608-1.024q27.648 0 56.32 1.024t68.608 4.096 56.32 4.096q-2.048-22.528-10.24-51.2-17.408-6.144-58.368-16.384t-61.44-19.456q-5.12-10.24-8.192-23.552t-5.12-23.552-4.096-25.6-4.096-24.576q-15.36-83.968-50.176-239.616t-44.032-202.752q-1.024-5.12-7.168-32.768t-11.264-52.224-9.216-47.104-4.096-32.768l1.024-10.24q9.216-3.072 105.472-18.432-2.048-24.576-9.216-56.32-6.144 0-18.432-1.024t-18.432-1.024q-16.384 0-50.176 6.144t-49.152 6.144q-78.848 1.024-117.76 1.024-28.672 0-80.896-5.12t-69.632-6.144z" />
|
||||
<glyph unicode="" glyph-name="header" d="M961.536 8.704q-25.6 0-75.776 2.048t-76.8 2.048q-24.576 0-74.752-2.048t-75.776-2.048q-14.336 0-21.504 12.288t-7.168 25.6q0 17.408 9.216 26.624t22.528 9.216 29.696 4.096 25.6 9.216q18.432 11.264 18.432 79.872v223.232q0 12.288-1.024 17.408-7.168 3.072-28.672 3.072h-385.024q-22.528 0-29.696-3.072 0-5.12 0-17.408l-1.024-211.968q0-80.896 21.504-94.208 9.216-5.12 26.624-7.168t32.768-2.048 25.6-8.192 11.264-26.624q0-14.336-7.168-26.624t-20.48-13.312q-26.624 0-79.872 2.048t-78.848 2.048q-24.576 0-72.704-2.048t-72.704-2.048q-13.312 0-20.48 12.288t-7.168 25.6q0 17.408 9.216 25.6t20.48 10.24 26.624 4.096 24.576 9.216q18.432 13.312 18.432 81.92l-1.024 31.744v464.896q0 2.048 1.024 14.336t0 21.504-1.024 21.504-2.048 24.576-4.096 20.48-6.144 18.432-9.216 10.24q-8.192 5.12-25.6 6.144t-29.696 2.048-23.552 7.168-10.24 26.624q0 14.336 6.144 26.624t20.48 13.312q26.624 0 79.872-2.048t78.848-2.048q23.552 0 72.704 2.048t71.68 2.048q14.336 0 21.504-13.312t7.168-26.624q0-17.408-9.216-25.6t-22.528-8.192-28.672-2.048-24.576-7.168q-19.456-12.288-19.456-92.16l1.024-182.272q0-12.288 0-18.432 7.168-2.048 22.528-2.048h399.36q14.336 0 21.504 2.048 1.024 6.144 1.024 18.432v182.272q0 79.872-19.456 92.16-10.24 6.144-33.792 7.168t-37.888 7.168-14.336 28.672q0 14.336 7.168 26.624t21.504 13.312q24.576 0 75.776-2.048t74.752-2.048q24.576 0 73.728 2.048t73.728 2.048q14.336 0 21.504-13.312t7.168-26.624q0-17.408-10.24-25.6t-22.528-8.192-29.696-2.048-24.576-7.168q-20.48-13.312-20.48-92.16l1.024-538.624q0-67.584 19.456-79.872 9.216-6.144 25.6-7.168t30.72-3.072 23.552-9.216 10.24-24.576q0-15.36-6.144-27.648t-20.48-13.312z" />
|
||||
<glyph unicode="" glyph-name="align-left" d="M1024 192v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-950.272q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h950.272q15.36 0 25.6-11.264t11.264-25.6zM804.864 411.136v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-731.136q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h731.136q15.36 0 25.6-11.264t11.264-25.6zM951.296 631.296v-73.728q0-14.336-11.264-25.6t-25.6-11.264h-877.568q-15.36 0-25.6 11.264t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 10.24h877.568q14.336 0 25.6-10.24t11.264-25.6zM731.136 850.432v-73.728q0-14.336-10.24-25.6t-25.6-10.24h-658.432q-15.36 0-25.6 10.24t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 11.264h658.432q14.336 0 25.6-11.264t10.24-25.6z" />
|
||||
<glyph unicode="" glyph-name="align-center" d="M1024 192v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-950.272q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h950.272q15.36 0 25.6-11.264t11.264-25.6zM804.864 411.136v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-512q-14.336 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h512q15.36 0 25.6-11.264t11.264-25.6zM951.296 631.296v-73.728q0-14.336-11.264-25.6t-25.6-11.264h-804.864q-14.336 0-25.6 11.264t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 10.24h804.864q14.336 0 25.6-10.24t11.264-25.6zM731.136 850.432v-73.728q0-14.336-10.24-25.6t-25.6-10.24h-366.592q-14.336 0-25.6 10.24t-10.24 25.6v73.728q0 14.336 10.24 25.6t25.6 11.264h366.592q14.336 0 25.6-11.264t10.24-25.6z" />
|
||||
<glyph unicode="" glyph-name="align-right" d="M1024 192v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-950.272q-15.36 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h950.272q15.36 0 25.6-11.264t11.264-25.6zM1024 411.136v-72.704q0-15.36-11.264-25.6t-25.6-11.264h-731.136q-14.336 0-25.6 11.264t-11.264 25.6v72.704q0 15.36 11.264 25.6t25.6 11.264h731.136q15.36 0 25.6-11.264t11.264-25.6zM1024 631.296v-73.728q0-14.336-11.264-25.6t-25.6-11.264h-877.568q-14.336 0-25.6 11.264t-11.264 25.6v73.728q0 14.336 11.264 25.6t25.6 10.24h877.568q15.36 0 25.6-10.24t11.264-25.6zM1024 850.432v-73.728q0-14.336-11.264-25.6t-25.6-10.24h-658.432q-14.336 0-25.6 10.24t-10.24 25.6v73.728q0 14.336 10.24 25.6t25.6 11.264h658.432q15.36 0 25.6-11.264t11.264-25.6z" />
|
||||
<glyph unicode="" glyph-name="list-bullet" d="M219.136 155.136q0-45.056-31.744-77.824t-77.824-31.744-77.824 31.744-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824zM219.136 448q0-46.080-31.744-77.824t-77.824-31.744-77.824 31.744-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824zM1024 210.432v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h694.272q7.168 0 13.312-6.144t5.12-12.288zM219.136 740.864q0-46.080-31.744-77.824t-77.824-31.744-77.824 31.744-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824zM1024 503.296v-110.592q0-7.168-5.12-12.288t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 12.288v110.592q0 7.168 5.12 12.288t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-12.288zM1024 795.136v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-694.272q-8.192 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-13.312z" />
|
||||
<glyph unicode="" glyph-name="indent-left" d="M219.136 648.704v-328.704q0-7.168-5.12-13.312t-13.312-5.12q-7.168 0-12.288 5.12l-164.864 164.864q-5.12 5.12-5.12 13.312t5.12 13.312l164.864 163.84q5.12 5.12 12.288 5.12 8.192 0 13.312-5.12t5.12-13.312zM1024 210.432v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288zM1024 429.568v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-621.568q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 648.704v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-621.568q-7.168 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 868.864v-109.568q0-8.192-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288z" />
|
||||
<glyph unicode="" glyph-name="indent-right" d="M200.704 484.864q0-8.192-5.12-13.312l-163.84-164.864q-5.12-5.12-13.312-5.12-7.168 0-13.312 5.12t-5.12 13.312v328.704q0 8.192 5.12 13.312t13.312 5.12 13.312-5.12l163.84-163.84q5.12-5.12 5.12-13.312zM1024 210.432v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288zM1024 429.568v-109.568q0-7.168-5.12-13.312t-13.312-5.12h-621.568q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 648.704v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-621.568q-7.168 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h621.568q7.168 0 13.312-5.12t5.12-13.312zM1024 868.864v-109.568q0-8.192-5.12-13.312t-13.312-5.12h-987.136q-7.168 0-13.312 5.12t-5.12 13.312v109.568q0 7.168 5.12 12.288t13.312 6.144h987.136q7.168 0 13.312-6.144t5.12-12.288z" />
|
||||
<glyph unicode="" glyph-name="list-numbered" d="M218.112 34.304q0-46.080-31.744-71.68t-76.8-26.624q-61.44 0-98.304 37.888l31.744 50.176q28.672-25.6 61.44-25.6 16.384 0 28.672 8.192t12.288 24.576q0 35.84-60.416 31.744l-14.336 31.744q4.096 6.144 18.432 24.576t24.576 31.744 20.48 21.504v1.024q-9.216 0-27.648-1.024t-27.648 0v-30.72h-60.416v87.040h190.464v-50.176l-54.272-66.56q28.672-6.144 46.080-27.648t17.408-50.176zM219.136 392.704v-91.136h-206.848q-4.096 20.48-4.096 30.72 0 29.696 14.336 53.248t31.744 38.912 37.888 27.648 31.744 24.576 14.336 25.6q0 14.336-9.216 22.528t-22.528 7.168q-25.6 0-46.080-32.768l-48.128 33.792q13.312 28.672 40.96 45.056t60.416 16.384q40.96 0 69.632-23.552t28.672-64.512q0-28.672-19.456-52.224t-43.008-36.864-43.008-28.672-20.48-30.72h72.704v34.816h60.416zM1024 210.432v-109.568q0-8.192-5.12-13.312t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 13.312v109.568q0 8.192 5.12 13.312t13.312 5.12h694.272q7.168 0 13.312-6.144t5.12-12.288zM219.136 724.48v-57.344h-191.488v57.344h61.44q0 22.528 0 69.632t1.024 68.608v7.168h-1.024q-5.12-10.24-28.672-30.72l-40.96 43.008 77.824 72.704h60.416v-230.4h61.44zM1024 503.296v-110.592q0-7.168-5.12-12.288t-13.312-5.12h-694.272q-8.192 0-13.312 5.12t-5.12 12.288v110.592q0 7.168 5.12 12.288t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-12.288zM1024 795.136v-109.568q0-7.168-5.12-12.288t-13.312-6.144h-694.272q-8.192 0-13.312 6.144t-5.12 12.288v109.568q0 8.192 5.12 13.312t13.312 5.12h694.272q7.168 0 13.312-5.12t5.12-13.312z" />
|
||||
<glyph unicode="" glyph-name="underline" horiz-adv-x="878" d="M27.648 833.024q-21.504 1.024-25.6 2.048l-2.048 50.176q7.168 0 22.528 0 34.816 0 64.512-2.048 75.776-4.096 94.208-4.096 49.152 0 96.256 2.048 66.56 2.048 83.968 3.072 31.744 0 49.152 1.024l-1.024-8.192 1.024-36.864v-5.12q-33.792-5.12-70.656-5.12-33.792 0-45.056-14.336-7.168-7.168-7.168-74.752 0-8.192 0-18.432t0-15.36l1.024-131.072 8.192-159.744q3.072-70.656 28.672-114.688 20.48-33.792 55.296-53.248 50.176-26.624 100.352-26.624 59.392 0 109.568 16.384 31.744 10.24 56.32 28.672 27.648 20.48 37.888 36.864 20.48 31.744 29.696 64.512 12.288 41.984 12.288 131.072 0 45.056-2.048 73.728t-6.144 69.632-8.192 91.136l-2.048 33.792q-3.072 37.888-13.312 50.176-19.456 20.48-44.032 19.456l-57.344-1.024-8.192 2.048 1.024 49.152h48.128l116.736-6.144q44.032-2.048 112.64 6.144l10.24-2.048q3.072-21.504 3.072-28.672 0-4.096-2.048-17.408-25.6-7.168-48.128-8.192-41.984-6.144-45.056-9.216-8.192-9.216-8.192-23.552 0-4.096 0-15.36t1.024-17.408q5.12-11.264 13.312-226.304 3.072-111.616-9.216-174.080-8.192-43.008-23.552-69.632-21.504-36.864-63.488-70.656-43.008-32.768-104.448-50.176-62.464-19.456-145.408-19.456-95.232 0-162.816 26.624t-101.376 69.632q-34.816 43.008-48.128 111.616-9.216 45.056-9.216 135.168v190.464q0 107.52-9.216 121.856-14.336 20.48-83.968 21.504zM877.568 27.136v36.864q0 8.192-5.12 13.312t-13.312 5.12h-840.704q-8.192 0-13.312-5.12t-5.12-13.312v-36.864q0-8.192 5.12-13.312t13.312-5.12h840.704q8.192 0 13.312 5.12t5.12 13.312z" />
|
||||
<glyph unicode="" glyph-name="table" horiz-adv-x="950" d="M292.864 173.568v109.568q0 8.192-5.12 13.312t-13.312 5.12h-183.296q-7.168 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q8.192 0 13.312 5.12t5.12 13.312zM292.864 392.704v110.592q0 7.168-5.12 12.288t-13.312 5.12h-183.296q-7.168 0-13.312-5.12t-5.12-12.288v-110.592q0-7.168 5.12-12.288t13.312-5.12h183.296q8.192 0 13.312 5.12t5.12 12.288zM584.704 173.568v109.568q0 8.192-5.12 13.312t-12.288 5.12h-183.296q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q7.168 0 12.288 5.12t5.12 13.312zM292.864 612.864v109.568q0 8.192-5.12 13.312t-13.312 5.12h-183.296q-7.168 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q8.192 0 13.312 5.12t5.12 13.312zM584.704 392.704v110.592q0 7.168-5.12 12.288t-12.288 5.12h-183.296q-8.192 0-13.312-5.12t-5.12-12.288v-110.592q0-7.168 5.12-12.288t13.312-5.12h183.296q7.168 0 12.288 5.12t5.12 12.288zM877.568 173.568v109.568q0 8.192-5.12 13.312t-13.312 5.12h-182.272q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h182.272q8.192 0 13.312 5.12t5.12 13.312zM584.704 612.864v109.568q0 8.192-5.12 13.312t-12.288 5.12h-183.296q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h183.296q7.168 0 12.288 5.12t5.12 13.312zM877.568 392.704v110.592q0 7.168-5.12 12.288t-13.312 5.12h-182.272q-8.192 0-13.312-5.12t-5.12-12.288v-110.592q0-7.168 5.12-12.288t13.312-5.12h182.272q8.192 0 13.312 5.12t5.12 12.288zM877.568 612.864v109.568q0 8.192-5.12 13.312t-13.312 5.12h-182.272q-8.192 0-13.312-5.12t-5.12-13.312v-109.568q0-8.192 5.12-13.312t13.312-5.12h182.272q8.192 0 13.312 5.12t5.12 13.312zM951.296 795.136v-621.568q0-37.888-27.648-64.512t-64.512-26.624h-768q-36.864 0-64.512 26.624t-26.624 64.512v621.568q0 37.888 26.624 64.512t64.512 27.648h768q37.888 0 64.512-27.648t27.648-64.512z" />
|
||||
<glyph unicode="" glyph-name="eraser" horiz-adv-x="1097" d="M512 155.136l192.512 220.16h-439.296l-192.512-220.16h439.296zM1090.56 770.56q9.216-19.456 6.144-40.96t-17.408-36.864l-512-585.728q-22.528-24.576-55.296-24.576h-439.296q-21.504 0-38.912 11.264t-27.648 31.744q-8.192 19.456-5.12 40.96t17.408 36.864l512 585.728q21.504 24.576 54.272 24.576h439.296q21.504 0 39.936-11.264t26.624-31.744z" />
|
||||
<glyph unicode="" glyph-name="text-height" d="M996.352 155.136q19.456 0 24.576-10.24t-6.144-25.6l-72.704-92.16q-11.264-15.36-27.648-15.36t-27.648 15.36l-72.704 92.16q-11.264 15.36-6.144 25.6t23.552 10.24h46.080v585.728h-46.080q-18.432 0-23.552 10.24t6.144 25.6l72.704 92.16q11.264 15.36 27.648 15.36t27.648-15.36l72.704-92.16q11.264-15.36 6.144-25.6t-24.576-10.24h-45.056v-585.728h45.056zM46.080 886.272l30.72-15.36q7.168-3.072 120.832-3.072 25.6 0 75.776 1.024t74.752 1.024q21.504 0 61.44 0t61.44 0h167.936q3.072 0 12.288 0t11.264 0 9.216 1.024 10.24 5.12 8.192 10.24l24.576 1.024q2.048 0 7.168-1.024t8.192 0q1.024-63.488 1.024-191.488 0-46.080-2.048-62.464-22.528-8.192-38.912-10.24-14.336 24.576-31.744 72.704-1.024 5.12-6.144 27.648t-8.192 41.984-4.096 20.48q-3.072 4.096-7.168 7.168t-8.192 3.072-8.192 1.024-10.24 1.024-9.216-1.024q-9.216 0-37.888 1.024t-43.008 0-35.84-1.024-40.96-4.096q-5.12-46.080-4.096-76.8 0-54.272 1.024-222.208t1.024-260.096q0-9.216-1.024-40.96t0-52.224 7.168-38.912q22.528-12.288 70.656-24.576t68.608-21.504q2.048-22.528 2.048-28.672 0-8.192-1.024-16.384l-19.456-1.024q-44.032-1.024-124.928 5.12t-117.76 5.12q-28.672 0-87.040-5.12t-86.016-5.12q-2.048 29.696-2.048 29.696v5.12q9.216 15.36 34.816 24.576t56.32 17.408 45.056 15.36q10.24 23.552 10.24 218.112 0 58.368-1.024 173.056t-2.048 174.080v66.56q0 1.024 0 8.192t1.024 14.336-1.024 15.36-2.048 13.312-3.072 8.192q-6.144 7.168-92.16 7.168-18.432 0-53.248-7.168t-45.056-15.36q-11.264-7.168-19.456-40.96t-18.432-63.488-24.576-30.72q-23.552 15.36-31.744 25.6v218.112z" />
|
||||
<glyph unicode="" glyph-name="brush" d="M922.624 960q39.936 0 70.656-26.624t29.696-66.56q0-35.84-25.6-86.016-189.44-359.424-266.24-430.080-55.296-52.224-123.904-52.224-72.704 0-123.904 53.248t-52.224 124.928q0 73.728 53.248 121.856l364.544 330.752q33.792 30.72 73.728 30.72zM403.456 369.152q22.528-43.008 60.416-74.752t86.016-43.008l1.024-40.96q2.048-121.856-73.728-197.632t-199.68-76.8q-69.632 0-123.904 26.624t-88.064 72.704-49.152 104.448-16.384 125.952q4.096-3.072 23.552-17.408t35.84-25.6 32.768-20.48 26.624-9.216q23.552 0 31.744 20.48 14.336 37.888 32.768 64.512t39.936 43.008 50.176 27.648 58.368 14.336 71.68 6.144z" />
|
||||
<glyph unicode="" glyph-name="pencil" horiz-adv-x="878" d="M207.872 82.432l51.2 52.224-134.144 134.144-52.224-52.224v-61.44h73.728v-72.704h61.44zM505.856 612.864q0 12.288-12.288 12.288-5.12 0-9.216-4.096l-310.272-309.248q-4.096-4.096-4.096-10.24 0-12.288 13.312-12.288 5.12 0 9.216 4.096l310.272 309.248q3.072 4.096 3.072 10.24zM475.136 722.432l237.568-237.568-475.136-476.16h-237.568v238.592zM865.28 667.136q0-29.696-20.48-51.2l-95.232-95.232-237.568 238.592 95.232 94.208q20.48 21.504 51.2 21.504 29.696 0 52.224-21.504l134.144-134.144q20.48-22.528 20.48-52.224z" />
|
||||
<glyph unicode="" glyph-name="minus" horiz-adv-x="804" d="M804.864 539.136v-109.568q0-22.528-16.384-38.912t-38.912-15.36h-694.272q-23.552 0-38.912 15.36t-16.384 38.912v109.568q0 23.552 16.384 38.912t38.912 16.384h694.272q22.528 0 38.912-16.384t16.384-38.912z" />
|
||||
<glyph unicode="" glyph-name="picture" horiz-adv-x="1097" d="M365.568 631.296q0-46.080-31.744-77.824t-77.824-32.768-77.824 32.768-31.744 77.824 31.744 76.8 77.824 32.768 77.824-32.768 31.744-76.8zM951.296 411.136v-256h-804.864v109.568l182.272 183.296 92.16-91.136 291.84 291.84zM1005.568 813.568h-914.432q-7.168 0-12.288-5.12t-6.144-13.312v-694.272q0-8.192 6.144-13.312t12.288-5.12h914.432q7.168 0 13.312 5.12t5.12 13.312v694.272q0 7.168-5.12 13.312t-13.312 5.12zM1096.704 795.136v-694.272q0-37.888-26.624-64.512t-64.512-27.648h-914.432q-36.864 0-64.512 27.648t-26.624 64.512v694.272q0 37.888 26.624 64.512t64.512 27.648h914.432q37.888 0 64.512-27.648t26.624-64.512z" />
|
||||
<glyph unicode="" glyph-name="file-image" horiz-adv-x="878" d="M838.656 742.912q16.384-16.384 27.648-43.008t11.264-51.2v-657.408q0-23.552-15.36-38.912t-38.912-16.384h-768q-23.552 0-38.912 16.384t-16.384 38.912v913.408q0 23.552 16.384 38.912t38.912 16.384h512q22.528 0 50.176-11.264t43.008-27.648zM584.704 882.176v-215.040h215.040q-5.12 16.384-12.288 23.552l-179.2 179.2q-6.144 7.168-23.552 12.288zM804.864 8.704v585.728h-237.568q-23.552 0-38.912 15.36t-16.384 38.912v238.592h-439.296v-878.592h732.16zM731.136 264.704v-182.272h-584.704v109.568l109.568 109.568 72.704-72.704 220.16 219.136zM256 375.296q-46.080 0-77.824 31.744t-31.744 77.824 31.744 77.824 77.824 31.744 77.824-31.744 31.744-77.824-31.744-77.824-77.824-31.744z" />
|
||||
<glyph unicode="" glyph-name="cw" horiz-adv-x="878" d="M877.568 813.568v-256q0-14.336-10.24-25.6t-26.624-11.264h-256q-23.552 0-32.768 23.552-10.24 22.528 7.168 38.912l78.848 78.848q-83.968 78.848-198.656 78.848-59.392 0-113.664-23.552t-93.184-62.464-63.488-93.184-22.528-113.664 22.528-113.664 63.488-93.184 93.184-62.464 113.664-23.552q67.584 0 128 29.696t102.4 83.968q4.096 6.144 13.312 7.168 8.192 0 14.336-5.12l77.824-78.848q5.12-4.096 6.144-11.264t-5.12-13.312q-61.44-75.776-150.528-116.736t-186.368-41.984q-89.088 0-171.008 34.816t-139.264 94.208-94.208 140.288-34.816 169.984 34.816 169.984 94.208 140.288 139.264 94.208 171.008 34.816q83.968 0 161.792-31.744t140.288-90.112l73.728 73.728q16.384 18.432 39.936 8.192 22.528-9.216 22.528-33.792z" />
|
||||
<glyph unicode="" glyph-name="ccw" horiz-adv-x="878" d="M877.568 448q0-89.088-34.816-169.984t-93.184-140.288-140.288-94.208-169.984-34.816q-98.304 0-187.392 41.984t-150.528 116.736q-4.096 6.144-4.096 13.312t5.12 11.264l77.824 78.848q6.144 5.12 14.336 5.12 9.216-1.024 13.312-7.168 41.984-54.272 102.4-83.968t129.024-29.696q59.392 0 112.64 23.552t94.208 62.464 62.464 93.184 22.528 113.664-22.528 113.664-62.464 93.184-94.208 62.464-112.64 23.552q-56.32 0-107.52-20.48t-92.16-58.368l78.848-78.848q17.408-16.384 8.192-38.912-10.24-23.552-33.792-23.552h-256q-15.36 0-25.6 11.264t-11.264 25.6v256q0 24.576 22.528 33.792 22.528 10.24 39.936-8.192l73.728-73.728q61.44 58.368 140.288 90.112t162.816 31.744q89.088 0 169.984-34.816t140.288-94.208 93.184-140.288 34.816-169.984z" />
|
||||
<glyph unicode="" glyph-name="omega" d="M704 64h256l64 128v-256h-384v214.214c131.112 56.484 224 197.162 224 361.786 0 214.432-157.598 382.266-352 382.266-194.406 0-352-167.832-352-382.266 0-164.624 92.886-305.302 224-361.786v-214.214h-384v256l64-128h256v32.59c-187.63 66.46-320 227.402-320 415.41 0 247.424 229.23 448 512 448s512-200.576 512-448c0-188.008-132.37-348.95-320-415.41v-32.59z" />
|
||||
<glyph unicode="" glyph-name="cancel-circle" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM512 32c-229.75 0-416 186.25-416 416s186.25 416 416 416 416-186.25 416-416-186.25-416-416-416zM672 704l-160-160-160 160-96-96 160-160-160-160 96-96 160 160 160-160 96 96-160 160 160 160z" />
|
||||
<glyph unicode="" glyph-name="newspaper" d="M896 704v128h-896v-704c0-35.346 28.654-64 64-64h864c53.022 0 96 42.978 96 96v544h-128zM832 128h-768v640h768v-640zM128 640h640v-64h-640zM512 512h256v-64h-256zM512 384h256v-64h-256zM512 256h192v-64h-192zM128 512h320v-320h-320z" />
|
||||
<glyph unicode="" glyph-name="camera" d="M304 352c0-114.876 93.124-208 208-208s208 93.124 208 208-93.124 208-208 208-208-93.124-208-208zM960 704h-224c-16 64-32 128-96 128h-256c-64 0-80-64-96-128h-224c-35.2 0-64-28.8-64-64v-576c0-35.2 28.8-64 64-64h896c35.2 0 64 28.8 64 64v576c0 35.2-28.8 64-64 64zM512 68c-156.85 0-284 127.148-284 284 0 156.85 127.15 284 284 284 156.852 0 284-127.15 284-284 0-156.852-127.146-284-284-284zM960 512h-128v64h128v-64z" />
|
||||
<glyph unicode="" glyph-name="music" d="M960 960h64v-736c0-88.366-100.29-160-224-160s-224 71.634-224 160c0 88.368 100.29 160 224 160 62.684 0 119.342-18.4 160-48.040v368.040l-512-113.778v-494.222c0-88.366-100.288-160-224-160s-224 71.634-224 160c0 88.368 100.288 160 224 160 62.684 0 119.342-18.4 160-48.040v624.040l576 128z" />
|
||||
<glyph unicode="" glyph-name="play" d="M981.188 799.892c-143.632 20.65-302.332 32.108-469.186 32.108-166.86 0-325.556-11.458-469.194-32.108-27.53-107.726-42.808-226.75-42.808-351.892 0-125.14 15.278-244.166 42.808-351.89 143.638-20.652 302.336-32.11 469.194-32.11 166.854 0 325.552 11.458 469.186 32.11 27.532 107.724 42.812 226.75 42.812 351.89 0 125.142-15.28 244.166-42.812 351.892zM384.002 256v384l320-192-320-192z" />
|
||||
<glyph unicode="" glyph-name="video-camera" d="M384 672c0 88.366 71.634 160 160 160s160-71.634 160-160c0-88.366-71.634-160-160-160s-160 71.634-160 160zM0 672c0 88.366 71.634 160 160 160s160-71.634 160-160c0-88.366-71.634-160-160-160s-160 71.634-160 160zM768 352v96c0 35.2-28.8 64-64 64h-640c-35.2 0-64-28.8-64-64v-320c0-35.2 28.8-64 64-64h640c35.2 0 64 28.8 64 64v96l256-160v448l-256-160zM640 192h-512v192h512v-192z" />
|
||||
<glyph unicode="" glyph-name="file-zip" d="M917.806 730.924c-22.208 30.292-53.174 65.7-87.178 99.704s-69.412 64.964-99.704 87.178c-51.574 37.82-76.592 42.194-90.924 42.194h-496c-44.112 0-80-35.888-80-80v-864c0-44.112 35.884-80 80-80h736c44.112 0 80 35.888 80 80v624c0 14.332-4.372 39.35-42.194 90.924v0 0zM785.374 785.374c30.7-30.7 54.8-58.398 72.58-81.374h-153.954v153.946c22.98-17.78 50.678-41.878 81.374-72.572v0 0zM896 16c0-8.672-7.328-16-16-16h-736c-8.672 0-16 7.328-16 16v864c0 8.672 7.328 16 16 16 0 0 495.956 0.002 496 0v-224c0-17.672 14.322-32 32-32h224v-624zM256 896h128v-64h-128v64zM384 832h128v-64h-128v64zM256 768h128v-64h-128v64zM384 704h128v-64h-128v64zM256 640h128v-64h-128v64zM384 576h128v-64h-128v64zM256 512h128v-64h-128v64zM384 448h128v-64h-128v64zM256 112c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v160c0 26.4-21.6 48-48 48h-80v64h-128v-272zM448 192v-64h-128v64h128z" />
|
||||
<glyph unicode="" glyph-name="stack" d="M1024 640l-512 256-512-256 512-256 512 256zM512 811.030l342.058-171.030-342.058-171.030-342.058 171.030 342.058 171.030zM921.444 499.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722zM921.444 307.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722z" />
|
||||
<glyph unicode="" glyph-name="credit-card" d="M928 832h-832c-52.8 0-96-43.2-96-96v-576c0-52.8 43.2-96 96-96h832c52.8 0 96 43.2 96 96v576c0 52.8-43.2 96-96 96zM96 768h832c17.346 0 32-14.654 32-32v-96h-896v96c0 17.346 14.654 32 32 32zM928 128h-832c-17.346 0-32 14.654-32 32v288h896v-288c0-17.346-14.654-32-32-32zM128 320h64v-128h-64zM256 320h64v-128h-64zM384 320h64v-128h-64z" />
|
||||
<glyph unicode="" glyph-name="address-book" d="M192 960v-1024h768v1024h-768zM576 703.67c70.51 0 127.67-57.16 127.67-127.67s-57.16-127.67-127.67-127.67-127.67 57.16-127.67 127.67 57.16 127.67 127.67 127.67v0zM768 192h-384v64c0 70.696 57.306 128 128 128v0h128c70.696 0 128-57.304 128-128v-64zM64 896h96v-192h-96v192zM64 640h96v-192h-96v192zM64 384h96v-192h-96v192zM64 128h96v-192h-96v192z" />
|
||||
<glyph unicode="" glyph-name="envelop" d="M928 832h-832c-52.8 0-96-43.2-96-96v-640c0-52.8 43.2-96 96-96h832c52.8 0 96 43.2 96 96v640c0 52.8-43.2 96-96 96zM398.74 409.628l-270.74-210.892v501.642l270.74-290.75zM176.38 704h671.24l-335.62-252-335.62 252zM409.288 398.302l102.712-110.302 102.71 110.302 210.554-270.302h-626.528l210.552 270.302zM625.26 409.628l270.74 290.75v-501.642l-270.74 210.892z" />
|
||||
<glyph unicode="" glyph-name="location" d="M512 960c-176.732 0-320-143.268-320-320 0-320 320-704 320-704s320 384 320 704c0 176.732-143.27 320-320 320zM512 448c-106.040 0-192 85.96-192 192s85.96 192 192 192 192-85.96 192-192-85.96-192-192-192z" />
|
||||
<glyph unicode="" glyph-name="drawer" d="M1016.988 307.99l-256 320c-6.074 7.592-15.266 12.010-24.988 12.010h-448c-9.72 0-18.916-4.418-24.988-12.010l-256-320c-4.538-5.674-7.012-12.724-7.012-19.99v-288c0-35.346 28.654-64 64-64h896c35.348 0 64 28.654 64 64v288c0 7.266-2.472 14.316-7.012 19.99zM960 256h-224l-128-128h-192l-128 128h-224v20.776l239.38 299.224h417.24l239.38-299.224v-20.776zM736 448h-448c-17.672 0-32 14.328-32 32s14.328 32 32 32h448c17.674 0 32-14.328 32-32s-14.326-32-32-32zM800 320h-576c-17.672 0-32 14.326-32 32s14.328 32 32 32h576c17.674 0 32-14.326 32-32s-14.326-32-32-32z" />
|
||||
<glyph unicode="" glyph-name="download" d="M512 384l256 256h-192v256h-128v-256h-192zM744.726 488.728l-71.74-71.742 260.080-96.986-421.066-157.018-421.066 157.018 260.080 96.986-71.742 71.742-279.272-104.728v-256l512-192 512 192v256z" />
|
||||
<glyph unicode="" glyph-name="upload" d="M448 384h128v256h192l-256 256-256-256h192zM640 528v-98.712l293.066-109.288-421.066-157.018-421.066 157.018 293.066 109.288v98.712l-384-144v-256l512-192 512 192v256z" />
|
||||
<glyph unicode="" glyph-name="quotes-left" d="M225 512c123.712 0 224-100.29 224-224 0-123.712-100.288-224-224-224s-224 100.288-224 224l-1 32c0 247.424 200.576 448 448 448v-128c-85.474 0-165.834-33.286-226.274-93.726-11.634-11.636-22.252-24.016-31.83-37.020 11.438 1.8 23.16 2.746 35.104 2.746zM801 512c123.71 0 224-100.29 224-224 0-123.712-100.29-224-224-224s-224 100.288-224 224l-1 32c0 247.424 200.576 448 448 448v-128c-85.474 0-165.834-33.286-226.274-93.726-11.636-11.636-22.254-24.016-31.832-37.020 11.44 1.8 23.16 2.746 35.106 2.746z" />
|
||||
<glyph unicode="" glyph-name="enlarge2" d="M1024 960v-416l-160 160-192-192-96 96 192 192-160 160zM448 288l-192-192 160-160h-416v416l160-160 192 192z" />
|
||||
<glyph unicode="" glyph-name="shrink2" d="M448 384v-416l-160 160-192-192-96 96 192 192-160 160zM1024 864l-192-192 160-160h-416v416l160-160 192 192z" />
|
||||
<glyph unicode="" glyph-name="lock" d="M592 512h-16v192c0 105.87-86.13 192-192 192h-128c-105.87 0-192-86.13-192-192v-192h-16c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h544c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48zM192 704c0 35.29 28.71 64 64 64h128c35.29 0 64-28.71 64-64v-192h-256v192z" />
|
||||
<glyph unicode="" glyph-name="unlocked" d="M768 896c105.87 0 192-86.13 192-192v-192h-128v192c0 35.29-28.71 64-64 64h-128c-35.29 0-64-28.71-64-64v-192h16c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48h-544c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h400v192c0 105.87 86.13 192 192 192h128z" />
|
||||
<glyph unicode="" glyph-name="wrench" d="M1002.934 142.124l-460.552 394.76c21.448 40.298 33.618 86.282 33.618 135.116 0 159.058-128.942 288-288 288-29.094 0-57.172-4.332-83.646-12.354l166.39-166.39c24.89-24.89 24.89-65.62 0-90.51l-101.49-101.49c-24.89-24.89-65.62-24.89-90.51 0l-166.39 166.39c-8.022-26.474-12.354-54.552-12.354-83.646 0-159.058 128.942-288 288-288 48.834 0 94.818 12.17 135.116 33.62l394.76-460.552c22.908-26.724 62.016-28.226 86.904-3.338l101.492 101.492c24.888 24.888 23.386 63.994-3.338 86.902z" />
|
||||
<glyph unicode="" glyph-name="eye" d="M512 768c-223.318 0-416.882-130.042-512-320 95.118-189.958 288.682-320 512-320 223.312 0 416.876 130.042 512 320-95.116 189.958-288.688 320-512 320zM764.45 598.296c60.162-38.374 111.142-89.774 149.434-150.296-38.292-60.522-89.274-111.922-149.436-150.296-75.594-48.218-162.89-73.704-252.448-73.704-89.56 0-176.858 25.486-252.452 73.704-60.158 38.372-111.138 89.772-149.432 150.296 38.292 60.524 89.274 111.924 149.434 150.296 3.918 2.5 7.876 4.922 11.86 7.3-9.96-27.328-15.41-56.822-15.41-87.596 0-141.382 114.616-256 256-256 141.382 0 256 114.618 256 256 0 30.774-5.452 60.268-15.408 87.598 3.978-2.378 7.938-4.802 11.858-7.302v0zM512 544c0-53.020-42.98-96-96-96s-96 42.98-96 96 42.98 96 96 96 96-42.982 96-96z" />
|
||||
<glyph unicode="" glyph-name="eye-blocked" d="M945.942 945.942c-18.746 18.744-49.136 18.744-67.882 0l-202.164-202.164c-51.938 15.754-106.948 24.222-163.896 24.222-223.318 0-416.882-130.042-512-320 41.122-82.124 100.648-153.040 173.022-207.096l-158.962-158.962c-18.746-18.746-18.746-49.136 0-67.882 9.372-9.374 21.656-14.060 33.94-14.060s24.568 4.686 33.942 14.058l864 864c18.744 18.746 18.744 49.138 0 67.884zM416 640c42.24 0 78.082-27.294 90.92-65.196l-121.724-121.724c-37.902 12.838-65.196 48.68-65.196 90.92 0 53.020 42.98 96 96 96zM110.116 448c38.292 60.524 89.274 111.924 149.434 150.296 3.918 2.5 7.876 4.922 11.862 7.3-9.962-27.328-15.412-56.822-15.412-87.596 0-54.89 17.286-105.738 46.7-147.418l-60.924-60.924c-52.446 36.842-97.202 83.882-131.66 138.342zM768 518c0 27.166-4.256 53.334-12.102 77.898l-321.808-321.808c24.568-7.842 50.742-12.090 77.91-12.090 141.382 0 256 114.618 256 256zM830.026 670.026l-69.362-69.362c1.264-0.786 2.53-1.568 3.786-2.368 60.162-38.374 111.142-89.774 149.434-150.296-38.292-60.522-89.274-111.922-149.436-150.296-75.594-48.218-162.89-73.704-252.448-73.704-38.664 0-76.902 4.76-113.962 14.040l-76.894-76.894c59.718-21.462 123.95-33.146 190.856-33.146 223.31 0 416.876 130.042 512 320-45.022 89.916-112.118 166.396-193.974 222.026z" />
|
||||
<glyph unicode="" glyph-name="happy" d="M512-64c282.77 0 512 229.23 512 512s-229.23 512-512 512-512-229.23-512-512 229.23-512 512-512zM512 864c229.75 0 416-186.25 416-416s-186.25-416-416-416-416 186.25-416 416 186.25 416 416 416zM512 361.24c115.95 0 226.23 30.806 320 84.92-14.574-178.438-153.128-318.16-320-318.16-166.868 0-305.422 139.872-320 318.304 93.77-54.112 204.050-85.064 320-85.064zM256 608c0 53.019 28.654 96 64 96s64-42.981 64-96c0-53.019-28.654-96-64-96s-64 42.981-64 96zM640 608c0 53.019 28.654 96 64 96s64-42.981 64-96c0-53.019-28.654-96-64-96s-64 42.981-64 96z" />
|
||||
<glyph unicode="" glyph-name="command" d="M736 64c-88.224 0-160 71.776-160 160v96h-128v-96c0-88.224-71.776-160-160-160s-160 71.776-160 160 71.776 160 160 160h96v128h-96c-88.224 0-160 71.776-160 160s71.776 160 160 160 160-71.776 160-160v-96h128v96c0 88.224 71.776 160 160 160s160-71.776 160-160-71.776-160-160-160h-96v-128h96c88.224 0 160-71.776 160-160s-71.774-160-160-160zM640 320v-96c0-52.934 43.066-96 96-96s96 43.066 96 96-43.066 96-96 96h-96zM288 320c-52.934 0-96-43.066-96-96s43.066-96 96-96 96 43.066 96 96v96h-96zM448 384h128v128h-128v-128zM640 576h96c52.934 0 96 43.066 96 96s-43.066 96-96 96-96-43.066-96-96v-96zM288 768c-52.934 0-96-43.066-96-96s43.066-96 96-96h96v96c0 52.934-43.064 96-96 96z" />
|
||||
<glyph unicode="" glyph-name="font2" d="M799.596 943.792c-90.526 0-148.62 16.208-241.848 16.208-301.284 0-441.792-171.584-441.792-345.872 0-102.678 48.64-136.458 144.564-136.458-6.758 14.864-18.914 31.080-18.914 104.034 0 204.010 77.006 263.458 175.636 267.51 0 0-80.918-793.374-315.778-888.542v-24.672h316.594l108.026 512h197.844l44.072 128h-214.908l51.944 246.19c59.446-12.156 117.542-24.316 167.532-24.316 62.148 0 118.894 18.914 149.968 162.126-37.826-12.16-78.362-16.208-122.94-16.208z" />
|
||||
<glyph unicode="" glyph-name="strikethrough" d="M1024 448v-64h-234.506c27.504-38.51 42.506-82.692 42.506-128 0-70.878-36.66-139.026-100.58-186.964-59.358-44.518-137.284-69.036-219.42-69.036-82.138 0-160.062 24.518-219.42 69.036-63.92 47.938-100.58 116.086-100.58 186.964h128c0-69.382 87.926-128 192-128s192 58.618 192 128c0 69.382-87.926 128-192 128h-512v64h299.518c-2.338 1.654-4.656 3.324-6.938 5.036-63.92 47.94-100.58 116.086-100.58 186.964s36.66 139.024 100.58 186.964c59.358 44.518 137.282 69.036 219.42 69.036 82.136 0 160.062-24.518 219.42-69.036 63.92-47.94 100.58-116.086 100.58-186.964h-128c0 69.382-87.926 128-192 128s-192-58.618-192-128c0-69.382 87.926-128 192-128 78.978 0 154.054-22.678 212.482-64h299.518z" />
|
||||
<glyph unicode="" glyph-name="sigma" d="M941.606 225.292l44.394 94.708h38l-64-384h-960v74.242l331.546 391.212-331.546 331.546v227h980l44-256h-34.376l-18.72 38.88c-35.318 73.364-61.904 89.12-138.904 89.12h-662l353.056-353.056-297.42-350.944h542.364c116.008 0 146.648 41.578 173.606 97.292z" />
|
||||
<glyph unicode="" glyph-name="sigma2" d="M941.606 225.292l44.394 94.708h38l-64-384h-960v74.242l331.546 391.212-331.546 331.546v227h980l44-256h-34.376l-18.72 38.88c-35.318 73.364-61.904 89.12-138.904 89.12h-662l353.056-353.056-297.42-350.944h542.364c116.008 0 146.648 41.578 173.606 97.292z" />
|
||||
<glyph unicode="" glyph-name="libreoffice" d="M534.626 937.372c-12.444 12.444-37.026 22.628-54.626 22.628h-384c-17.6 0-32-14.4-32-32v-960c0-17.6 14.4-32 32-32h768c17.6 0 32 14.4 32 32v576c0 17.6-10.182 42.182-22.626 54.626l-338.748 338.746zM832 0h-704v896h351.158c2.916-0.48 8.408-2.754 10.81-4.478l337.556-337.554c1.722-2.402 3.996-7.894 4.476-10.81v-543.158zM864 960h-192c-17.6 0-21.818-10.182-9.374-22.626l210.746-210.746c12.446-12.446 22.628-8.228 22.628 9.372v192c0 17.6-14.4 32-32 32z" />
|
||||
<glyph unicode="" glyph-name="search-plus" horiz-adv-x="951" d="M585.143 493.714v-36.571q0-7.429-5.429-12.857t-12.857-5.429h-128v-128q0-7.429-5.429-12.857t-12.857-5.429h-36.571q-7.429 0-12.857 5.429t-5.429 12.857v128h-128q-7.429 0-12.857 5.429t-5.429 12.857v36.571q0 7.429 5.429 12.857t12.857 5.429h128v128q0 7.429 5.429 12.857t12.857 5.429h36.571q7.429 0 12.857-5.429t5.429-12.857v-128h128q7.429 0 12.857-5.429t5.429-12.857zM658.286 475.428q0 105.714-75.143 180.857t-180.857 75.143-180.857-75.143-75.143-180.857 75.143-180.857 180.857-75.143 180.857 75.143 75.143 180.857zM950.857 0q0-30.286-21.429-51.714t-51.714-21.429q-30.857 0-51.429 21.714l-196 195.429q-102.286-70.857-228-70.857-81.714 0-156.286 31.714t-128.571 85.714-85.714 128.571-31.714 156.286 31.714 156.286 85.714 128.571 128.571 85.714 156.286 31.714 156.286-31.714 128.571-85.714 85.714-128.571 31.714-156.286q0-125.714-70.857-228l196-196q21.143-21.143 21.143-51.429z" />
|
||||
<glyph unicode="" glyph-name="search-minus" horiz-adv-x="951" d="M585.143 493.714v-36.571q0-7.429-5.429-12.857t-12.857-5.429h-329.143q-7.429 0-12.857 5.429t-5.429 12.857v36.571q0 7.429 5.429 12.857t12.857 5.429h329.143q7.429 0 12.857-5.429t5.429-12.857zM658.286 475.428q0 105.714-75.143 180.857t-180.857 75.143-180.857-75.143-75.143-180.857 75.143-180.857 180.857-75.143 180.857 75.143 75.143 180.857zM950.857 0q0-30.286-21.429-51.714t-51.714-21.429q-30.857 0-51.429 21.714l-196 195.429q-102.286-70.857-228-70.857-81.714 0-156.286 31.714t-128.571 85.714-85.714 128.571-31.714 156.286 31.714 156.286 85.714 128.571 128.571 85.714 156.286 31.714 156.286-31.714 128.571-85.714 85.714-128.571 31.714-156.286q0-125.714-70.857-228l196-196q21.143-21.143 21.143-51.429z" />
|
||||
<glyph unicode="" glyph-name="trash-o" horiz-adv-x="805" d="M292.571 530.286v-329.143q0-8-5.143-13.143t-13.143-5.143h-36.571q-8 0-13.143 5.143t-5.143 13.143v329.143q0 8 5.143 13.143t13.143 5.143h36.571q8 0 13.143-5.143t5.143-13.143zM438.857 530.286v-329.143q0-8-5.143-13.143t-13.143-5.143h-36.571q-8 0-13.143 5.143t-5.143 13.143v329.143q0 8 5.143 13.143t13.143 5.143h36.571q8 0 13.143-5.143t5.143-13.143zM585.143 530.286v-329.143q0-8-5.143-13.143t-13.143-5.143h-36.571q-8 0-13.143 5.143t-5.143 13.143v329.143q0 8 5.143 13.143t13.143 5.143h36.571q8 0 13.143-5.143t5.143-13.143zM658.286 116.571v541.714h-512v-541.714q0-12.571 4-23.143t8.286-15.429 6-4.857h475.429q1.714 0 6 4.857t8.286 15.429 4 23.143zM274.286 731.428h256l-27.429 66.857q-4 5.143-9.714 6.286h-181.143q-5.714-1.143-9.714-6.286zM804.571 713.143v-36.571q0-8-5.143-13.143t-13.143-5.143h-54.857v-541.714q0-47.429-26.857-82t-64.571-34.571h-475.429q-37.714 0-64.571 33.429t-26.857 80.857v544h-54.857q-8 0-13.143 5.143t-5.143 13.143v36.571q0 8 5.143 13.143t13.143 5.143h176.571l40 95.429q8.571 21.143 30.857 36t45.143 14.857h182.857q22.857 0 45.143-14.857t30.857-36l40-95.429h176.571q8 0 13.143-5.143t5.143-13.143z" />
|
||||
<glyph unicode="" glyph-name="align-justify" d="M1024 182.857v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714zM1024 402.286v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714zM1024 621.714v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714zM1024 841.143v-73.143q0-14.857-10.857-25.714t-25.714-10.857h-950.857q-14.857 0-25.714 10.857t-10.857 25.714v73.143q0 14.857 10.857 25.714t25.714 10.857h950.857q14.857 0 25.714-10.857t10.857-25.714z" />
|
||||
<glyph unicode="" glyph-name="arrows-v" horiz-adv-x="439" d="M402.286 768q0-14.857-10.857-25.714t-25.714-10.857h-73.143v-585.143h73.143q14.857 0 25.714-10.857t10.857-25.714-10.857-25.714l-146.286-146.286q-10.857-10.857-25.714-10.857t-25.714 10.857l-146.286 146.286q-10.857 10.857-10.857 25.714t10.857 25.714 25.714 10.857h73.143v585.143h-73.143q-14.857 0-25.714 10.857t-10.857 25.714 10.857 25.714l146.286 146.286q10.857 10.857 25.714 10.857t25.714-10.857l146.286-146.286q10.857-10.857 10.857-25.714z" />
|
||||
<glyph unicode="" glyph-name="desktop" horiz-adv-x="1097" d="M1024 384v475.429q0 7.429-5.429 12.857t-12.857 5.429h-914.286q-7.429 0-12.857-5.429t-5.429-12.857v-475.429q0-7.429 5.429-12.857t12.857-5.429h914.286q7.429 0 12.857 5.429t5.429 12.857zM1097.143 859.428v-621.714q0-37.714-26.857-64.571t-64.571-26.857h-310.857q0-21.143 9.143-44.286t18.286-40.571 9.143-24.857q0-14.857-10.857-25.714t-25.714-10.857h-292.571q-14.857 0-25.714 10.857t-10.857 25.714q0 8 9.143 25.143t18.286 40 9.143 44.571h-310.857q-37.714 0-64.571 26.857t-26.857 64.571v621.714q0 37.714 26.857 64.571t64.571 26.857h914.286q37.714 0 64.571-26.857t26.857-64.571z" />
|
||||
<glyph unicode="" glyph-name="tablet" horiz-adv-x="658" d="M365.714 146.286q0 14.857-10.857 25.714t-25.714 10.857-25.714-10.857-10.857-25.714 10.857-25.714 25.714-10.857 25.714 10.857 10.857 25.714zM585.143 237.714v548.571q0 7.429-5.429 12.857t-12.857 5.429h-475.429q-7.429 0-12.857-5.429t-5.429-12.857v-548.571q0-7.429 5.429-12.857t12.857-5.429h475.429q7.429 0 12.857 5.429t5.429 12.857zM658.286 786.286v-621.714q0-37.714-26.857-64.571t-64.571-26.857h-475.429q-37.714 0-64.571 26.857t-26.857 64.571v621.714q0 37.714 26.857 64.571t64.571 26.857h475.429q37.714 0 64.571-26.857t26.857-64.571z" />
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 46 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,47 +0,0 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
// 用 createMenu 方法创建菜单
|
||||
E.createMenu(function (check) {
|
||||
|
||||
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
|
||||
var menuId = 'attach';
|
||||
|
||||
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
|
||||
if (!check(menuId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this 指向 editor 对象自身
|
||||
var editor = this;
|
||||
|
||||
// 创建 menu 对象
|
||||
var menu = new E.Menu({
|
||||
editor: editor, // 编辑器对象
|
||||
id: menuId, // 菜单id
|
||||
title: '附件', // 菜单标题
|
||||
|
||||
// 正常状态和选中状态下的dom对象,样式需要自定义
|
||||
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-paperclip" aria-hidden="true" name="release"></i></a>'),
|
||||
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-paperclip" aria-hidden="true" name="release"></i></a>')
|
||||
});
|
||||
|
||||
|
||||
// 菜单正常状态下,点击将触发该事件
|
||||
menu.clickEvent = function (e) {
|
||||
$("#uploadAttachModal").modal("show");
|
||||
};
|
||||
|
||||
|
||||
// 菜单选中状态下,点击将触发该事件
|
||||
menu.clickEventSelected = function (e) {
|
||||
|
||||
};
|
||||
// 增加到editor对象中
|
||||
editor.menus[menuId] = menu;
|
||||
});
|
||||
|
||||
})();
|
|
@ -1,47 +0,0 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
// 用 createMenu 方法创建菜单
|
||||
E.createMenu(function (check) {
|
||||
|
||||
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
|
||||
var menuId = 'history';
|
||||
|
||||
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
|
||||
if (!check(menuId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this 指向 editor 对象自身
|
||||
var editor = this;
|
||||
|
||||
// 创建 menu 对象
|
||||
var menu = new E.Menu({
|
||||
editor: editor, // 编辑器对象
|
||||
id: menuId, // 菜单id
|
||||
title: '历史', // 菜单标题
|
||||
|
||||
// 正常状态和选中状态下的dom对象,样式需要自定义
|
||||
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-history" aria-hidden="true" name="history"></i></a>'),
|
||||
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-history" aria-hidden="true" name="history"></i></a>')
|
||||
});
|
||||
|
||||
// 菜单正常状态下,点击将触发该事件
|
||||
menu.clickEvent = function (e) {
|
||||
window.documentHistory();
|
||||
};
|
||||
|
||||
// 菜单选中状态下,点击将触发该事件
|
||||
menu.clickEventSelected = function (e) {
|
||||
|
||||
};
|
||||
|
||||
|
||||
// 增加到editor对象中
|
||||
editor.menus[menuId] = menu;
|
||||
});
|
||||
|
||||
})();
|
|
@ -1,47 +0,0 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
// 用 createMenu 方法创建菜单
|
||||
E.createMenu(function (check) {
|
||||
|
||||
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
|
||||
var menuId = 'release';
|
||||
|
||||
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
|
||||
if (!check(menuId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this 指向 editor 对象自身
|
||||
var editor = this;
|
||||
|
||||
// 创建 menu 对象
|
||||
var menu = new E.Menu({
|
||||
editor: editor, // 编辑器对象
|
||||
id: menuId, // 菜单id
|
||||
title: '发布', // 菜单标题
|
||||
|
||||
// 正常状态和选中状态下的dom对象,样式需要自定义
|
||||
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-cloud-upload" aria-hidden="true" name="release"></i></a>'),
|
||||
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-cloud-upload" aria-hidden="true" name="release"></i></a>')
|
||||
});
|
||||
|
||||
// 菜单正常状态下,点击将触发该事件
|
||||
menu.clickEvent = function (e) {
|
||||
window.releaseBook();
|
||||
};
|
||||
|
||||
// 菜单选中状态下,点击将触发该事件
|
||||
menu.clickEventSelected = function (e) {
|
||||
|
||||
};
|
||||
|
||||
|
||||
// 增加到editor对象中
|
||||
editor.menus[menuId] = menu;
|
||||
});
|
||||
|
||||
})();
|
|
@ -1,47 +0,0 @@
|
|||
(function () {
|
||||
|
||||
// 获取 wangEditor 构造函数和 jquery
|
||||
var E = window.wangEditor;
|
||||
var $ = window.jQuery;
|
||||
|
||||
// 用 createMenu 方法创建菜单
|
||||
E.createMenu(function (check) {
|
||||
|
||||
// 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看
|
||||
var menuId = 'save';
|
||||
|
||||
// check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。
|
||||
if (!check(menuId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this 指向 editor 对象自身
|
||||
var editor = this;
|
||||
|
||||
// 创建 menu 对象
|
||||
var menu = new E.Menu({
|
||||
editor: editor, // 编辑器对象
|
||||
id: menuId, // 菜单id
|
||||
title: '保存', // 菜单标题
|
||||
|
||||
// 正常状态和选中状态下的dom对象,样式需要自定义
|
||||
$domNormal: $('<a href="#" tabindex="-1"><i class="fa fa-save" aria-hidden="true" name="save"></i></a>'),
|
||||
$domSelected: $('<a href="#" tabindex="-1" class="selected"><i class="fa fa-save" aria-hidden="true" name="save"></i></a>')
|
||||
});
|
||||
|
||||
// 菜单正常状态下,点击将触发该事件
|
||||
menu.clickEvent = function (e) {
|
||||
window.saveDocument();
|
||||
};
|
||||
|
||||
// 菜单选中状态下,点击将触发该事件
|
||||
menu.clickEventSelected = function (e) {
|
||||
|
||||
};
|
||||
|
||||
|
||||
// 增加到editor对象中
|
||||
editor.menus[menuId] = menu;
|
||||
});
|
||||
|
||||
})();
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* @description 入口文件
|
||||
* @author wangfupeng
|
||||
*/
|
||||
import './assets/style/common.less';
|
||||
import './assets/style/icon.less';
|
||||
import './assets/style/menus.less';
|
||||
import './assets/style/text.less';
|
||||
import './assets/style/panel.less';
|
||||
import './assets/style/droplist.less';
|
||||
import './utils/polyfill';
|
||||
import Editor from './editor/index';
|
||||
export * from './menus/menu-constructors/index';
|
||||
export default Editor;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
if ! [ -x "$(command -v rclone)" ]; then
|
||||
apt install rclone -y
|
||||
else
|
||||
whereis rclone
|
||||
fi
|
||||
|
||||
|
||||
export MINDOC_SYNC="${MINDOC_SYNC:=}"
|
||||
export SYNC_LIST="${SYNC_LIST:=}"
|
||||
export SYNC_ACTION="${SYNC_ACTION:=sync --dry-run}"
|
||||
export HOST_DIR=/mindoc-sync-host
|
||||
export DOCKER_DIR=/mindoc
|
||||
|
||||
function doSyncCopy() {
|
||||
if [ -d "${1}" ]
|
||||
then
|
||||
rclone $SYNC_ACTION --progress --exclude .git* --exclude .git/** "${1}" "${2}"
|
||||
fi
|
||||
}
|
||||
|
||||
function doSync() {
|
||||
case $MINDOC_SYNC in
|
||||
"docker2host")
|
||||
doSyncCopy "${DOCKER_DIR}/${1}" "${HOST_DIR}/${1}"
|
||||
;;
|
||||
"host2docker")
|
||||
doSyncCopy "${HOST_DIR}/${1}" "${DOCKER_DIR}/${1}"
|
||||
;;
|
||||
*)
|
||||
printenv | grep MINDOC_SYNC
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
export IFS=";"
|
||||
if ! [ -z "${SYNC_LIST}" ]; then
|
||||
for item in $SYNC_LIST; do
|
||||
doSync "${item}"
|
||||
done
|
||||
fi
|
|
@ -0,0 +1,571 @@
|
|||
// https://github.com/mattn/docx2md
|
||||
// License MIT
|
||||
package utils
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
_ "flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
_ "runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
// Relationship is
|
||||
type Relationship struct {
|
||||
Text string `xml:",chardata"`
|
||||
ID string `xml:"Id,attr"`
|
||||
Type string `xml:"Type,attr"`
|
||||
Target string `xml:"Target,attr"`
|
||||
TargetMode string `xml:"TargetMode,attr"`
|
||||
}
|
||||
|
||||
// Relationships is
|
||||
type Relationships struct {
|
||||
XMLName xml.Name `xml:"Relationships"`
|
||||
Text string `xml:",chardata"`
|
||||
Xmlns string `xml:"xmlns,attr"`
|
||||
Relationship []Relationship `xml:"Relationship"`
|
||||
}
|
||||
|
||||
// TextVal is
|
||||
type TextVal struct {
|
||||
Text string `xml:",chardata"`
|
||||
Val string `xml:"val,attr"`
|
||||
}
|
||||
|
||||
// NumberingLvl is
|
||||
type NumberingLvl struct {
|
||||
Text string `xml:",chardata"`
|
||||
Ilvl string `xml:"ilvl,attr"`
|
||||
Tplc string `xml:"tplc,attr"`
|
||||
Tentative string `xml:"tentative,attr"`
|
||||
Start TextVal `xml:"start"`
|
||||
NumFmt TextVal `xml:"numFmt"`
|
||||
LvlText TextVal `xml:"lvlText"`
|
||||
LvlJc TextVal `xml:"lvlJc"`
|
||||
PPr struct {
|
||||
Text string `xml:",chardata"`
|
||||
Ind struct {
|
||||
Text string `xml:",chardata"`
|
||||
Left string `xml:"left,attr"`
|
||||
Hanging string `xml:"hanging,attr"`
|
||||
} `xml:"ind"`
|
||||
} `xml:"pPr"`
|
||||
RPr struct {
|
||||
Text string `xml:",chardata"`
|
||||
U struct {
|
||||
Text string `xml:",chardata"`
|
||||
Val string `xml:"val,attr"`
|
||||
} `xml:"u"`
|
||||
RFonts struct {
|
||||
Text string `xml:",chardata"`
|
||||
Hint string `xml:"hint,attr"`
|
||||
} `xml:"rFonts"`
|
||||
} `xml:"rPr"`
|
||||
}
|
||||
|
||||
// Numbering is
|
||||
type Numbering struct {
|
||||
XMLName xml.Name `xml:"numbering"`
|
||||
Text string `xml:",chardata"`
|
||||
Wpc string `xml:"wpc,attr"`
|
||||
Cx string `xml:"cx,attr"`
|
||||
Cx1 string `xml:"cx1,attr"`
|
||||
Mc string `xml:"mc,attr"`
|
||||
O string `xml:"o,attr"`
|
||||
R string `xml:"r,attr"`
|
||||
M string `xml:"m,attr"`
|
||||
V string `xml:"v,attr"`
|
||||
Wp14 string `xml:"wp14,attr"`
|
||||
Wp string `xml:"wp,attr"`
|
||||
W10 string `xml:"w10,attr"`
|
||||
W string `xml:"w,attr"`
|
||||
W14 string `xml:"w14,attr"`
|
||||
W15 string `xml:"w15,attr"`
|
||||
W16se string `xml:"w16se,attr"`
|
||||
Wpg string `xml:"wpg,attr"`
|
||||
Wpi string `xml:"wpi,attr"`
|
||||
Wne string `xml:"wne,attr"`
|
||||
Wps string `xml:"wps,attr"`
|
||||
Ignorable string `xml:"Ignorable,attr"`
|
||||
AbstractNum []struct {
|
||||
Text string `xml:",chardata"`
|
||||
AbstractNumID string `xml:"abstractNumId,attr"`
|
||||
RestartNumberingAfterBreak string `xml:"restartNumberingAfterBreak,attr"`
|
||||
Nsid TextVal `xml:"nsid"`
|
||||
MultiLevelType TextVal `xml:"multiLevelType"`
|
||||
Tmpl TextVal `xml:"tmpl"`
|
||||
Lvl []NumberingLvl `xml:"lvl"`
|
||||
} `xml:"abstractNum"`
|
||||
Num []struct {
|
||||
Text string `xml:",chardata"`
|
||||
NumID string `xml:"numId,attr"`
|
||||
AbstractNumID TextVal `xml:"abstractNumId"`
|
||||
} `xml:"num"`
|
||||
}
|
||||
|
||||
type file struct {
|
||||
rels Relationships
|
||||
num Numbering
|
||||
r *zip.ReadCloser
|
||||
embed bool
|
||||
list map[string]int
|
||||
name string
|
||||
}
|
||||
|
||||
// Node is
|
||||
type Node struct {
|
||||
XMLName xml.Name
|
||||
Attrs []xml.Attr `xml:"-"`
|
||||
Content []byte `xml:",innerxml"`
|
||||
Nodes []Node `xml:",any"`
|
||||
}
|
||||
|
||||
// UnmarshalXML is
|
||||
func (n *Node) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
n.Attrs = start.Attr
|
||||
type node Node
|
||||
|
||||
return d.DecodeElement((*node)(n), &start)
|
||||
}
|
||||
|
||||
func escape(s, set string) string {
|
||||
replacer := []string{}
|
||||
for _, r := range []rune(set) {
|
||||
rs := string(r)
|
||||
replacer = append(replacer, rs, `\`+rs)
|
||||
}
|
||||
return strings.NewReplacer(replacer...).Replace(s)
|
||||
}
|
||||
|
||||
func (zf *file) extract(rel *Relationship, w io.Writer) error {
|
||||
err := os.MkdirAll(
|
||||
filepath.Join("uploads",
|
||||
strings.TrimSuffix(zf.name, ".docx"),
|
||||
filepath.Dir(rel.Target)),
|
||||
0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range zf.r.File {
|
||||
if f.Name != "word/"+rel.Target {
|
||||
continue
|
||||
}
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
b := make([]byte, f.UncompressedSize64)
|
||||
n, err := rc.Read(b)
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
if zf.embed {
|
||||
fmt.Fprintf(w, "![](data:image/png;base64,%s)",
|
||||
base64.StdEncoding.EncodeToString(b[:n]))
|
||||
} else {
|
||||
err = ioutil.WriteFile(
|
||||
filepath.Join("uploads",
|
||||
strings.TrimSuffix(zf.name, ".docx"),
|
||||
rel.Target),
|
||||
b, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(w, "![](%s)", "/"+filepath.Join(
|
||||
"uploads",
|
||||
strings.TrimSuffix(zf.name, ".docx"),
|
||||
escape(rel.Target, "()")))
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func attr(attrs []xml.Attr, name string) (string, bool) {
|
||||
for _, attr := range attrs {
|
||||
if attr.Name.Local == name {
|
||||
return attr.Value, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (zf *file) walk(node *Node, w io.Writer) error {
|
||||
switch node.XMLName.Local {
|
||||
case "hyperlink":
|
||||
fmt.Fprint(w, "[")
|
||||
var cbuf bytes.Buffer
|
||||
for _, n := range node.Nodes {
|
||||
if err := zf.walk(&n, &cbuf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, escape(cbuf.String(), "[]"))
|
||||
fmt.Fprint(w, "]")
|
||||
|
||||
fmt.Fprint(w, "(")
|
||||
if id, ok := attr(node.Attrs, "id"); ok {
|
||||
for _, rel := range zf.rels.Relationship {
|
||||
if id == rel.ID {
|
||||
fmt.Fprint(w, escape(rel.Target, "()"))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, ")")
|
||||
case "t":
|
||||
fmt.Fprint(w, string(node.Content))
|
||||
case "pPr":
|
||||
code := false
|
||||
for _, n := range node.Nodes {
|
||||
switch n.XMLName.Local {
|
||||
case "ind":
|
||||
if left, ok := attr(n.Attrs, "left"); ok {
|
||||
if i, err := strconv.Atoi(left); err == nil && i > 0 {
|
||||
fmt.Fprint(w, strings.Repeat(" ", i/360))
|
||||
}
|
||||
}
|
||||
case "pStyle":
|
||||
if val, ok := attr(n.Attrs, "val"); ok {
|
||||
if strings.HasPrefix(val, "Heading") {
|
||||
if i, err := strconv.Atoi(val[7:]); err == nil && i > 0 {
|
||||
fmt.Fprint(w, strings.Repeat("#", i)+" ")
|
||||
}
|
||||
} else if val == "Code" {
|
||||
code = true
|
||||
} else {
|
||||
if i, err := strconv.Atoi(val); err == nil && i > 0 {
|
||||
fmt.Fprint(w, strings.Repeat("#", i)+" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
case "numPr":
|
||||
numID := ""
|
||||
ilvl := ""
|
||||
numFmt := ""
|
||||
start := 1
|
||||
ind := 0
|
||||
for _, nn := range n.Nodes {
|
||||
if nn.XMLName.Local == "numId" {
|
||||
if val, ok := attr(nn.Attrs, "val"); ok {
|
||||
numID = val
|
||||
}
|
||||
}
|
||||
if nn.XMLName.Local == "ilvl" {
|
||||
if val, ok := attr(nn.Attrs, "val"); ok {
|
||||
ilvl = val
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, num := range zf.num.Num {
|
||||
if numID != num.NumID {
|
||||
continue
|
||||
}
|
||||
for _, abnum := range zf.num.AbstractNum {
|
||||
if abnum.AbstractNumID != num.AbstractNumID.Val {
|
||||
continue
|
||||
}
|
||||
for _, ablvl := range abnum.Lvl {
|
||||
if ablvl.Ilvl != ilvl {
|
||||
continue
|
||||
}
|
||||
if i, err := strconv.Atoi(ablvl.Start.Val); err == nil {
|
||||
start = i
|
||||
}
|
||||
if i, err := strconv.Atoi(ablvl.PPr.Ind.Left); err == nil {
|
||||
ind = i / 360
|
||||
}
|
||||
numFmt = ablvl.NumFmt.Val
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprint(w, strings.Repeat(" ", ind))
|
||||
switch numFmt {
|
||||
case "decimal", "aiueoFullWidth":
|
||||
key := fmt.Sprintf("%s:%d", numID, ind)
|
||||
cur, ok := zf.list[key]
|
||||
if !ok {
|
||||
zf.list[key] = start
|
||||
} else {
|
||||
zf.list[key] = cur + 1
|
||||
}
|
||||
fmt.Fprintf(w, "%d. ", zf.list[key])
|
||||
case "bullet":
|
||||
fmt.Fprint(w, "* ")
|
||||
}
|
||||
}
|
||||
}
|
||||
if code {
|
||||
fmt.Fprint(w, "`")
|
||||
}
|
||||
for _, n := range node.Nodes {
|
||||
if err := zf.walk(&n, w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if code {
|
||||
fmt.Fprint(w, "`")
|
||||
}
|
||||
case "tbl":
|
||||
var rows [][]string
|
||||
for _, tr := range node.Nodes {
|
||||
if tr.XMLName.Local != "tr" {
|
||||
continue
|
||||
}
|
||||
var cols []string
|
||||
for _, tc := range tr.Nodes {
|
||||
if tc.XMLName.Local != "tc" {
|
||||
continue
|
||||
}
|
||||
var cbuf bytes.Buffer
|
||||
if err := zf.walk(&tc, &cbuf); err != nil {
|
||||
return err
|
||||
}
|
||||
cols = append(cols, strings.Replace(cbuf.String(), "\n", "", -1))
|
||||
}
|
||||
rows = append(rows, cols)
|
||||
}
|
||||
maxcol := 0
|
||||
for _, cols := range rows {
|
||||
if len(cols) > maxcol {
|
||||
maxcol = len(cols)
|
||||
}
|
||||
}
|
||||
widths := make([]int, maxcol)
|
||||
for _, row := range rows {
|
||||
for i := 0; i < maxcol; i++ {
|
||||
if i < len(row) {
|
||||
width := runewidth.StringWidth(row[i])
|
||||
if widths[i] < width {
|
||||
widths[i] = width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, row := range rows {
|
||||
if i == 0 {
|
||||
for j := 0; j < maxcol; j++ {
|
||||
fmt.Fprint(w, "|")
|
||||
fmt.Fprint(w, strings.Repeat(" ", widths[j]))
|
||||
}
|
||||
fmt.Fprint(w, "|\n")
|
||||
for j := 0; j < maxcol; j++ {
|
||||
fmt.Fprint(w, "|")
|
||||
fmt.Fprint(w, strings.Repeat("-", widths[j]))
|
||||
}
|
||||
fmt.Fprint(w, "|\n")
|
||||
}
|
||||
for j := 0; j < maxcol; j++ {
|
||||
fmt.Fprint(w, "|")
|
||||
if j < len(row) {
|
||||
width := runewidth.StringWidth(row[j])
|
||||
fmt.Fprint(w, escape(row[j], "|"))
|
||||
fmt.Fprint(w, strings.Repeat(" ", widths[j]-width))
|
||||
} else {
|
||||
fmt.Fprint(w, strings.Repeat(" ", widths[j]))
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, "|\n")
|
||||
}
|
||||
fmt.Fprint(w, "\n")
|
||||
case "r":
|
||||
bold := false
|
||||
italic := false
|
||||
strike := false
|
||||
for _, n := range node.Nodes {
|
||||
if n.XMLName.Local != "rPr" {
|
||||
continue
|
||||
}
|
||||
for _, nn := range n.Nodes {
|
||||
switch nn.XMLName.Local {
|
||||
case "b":
|
||||
bold = true
|
||||
case "i":
|
||||
italic = true
|
||||
case "strike":
|
||||
strike = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if strike {
|
||||
fmt.Fprint(w, "~~")
|
||||
}
|
||||
if bold {
|
||||
fmt.Fprint(w, "**")
|
||||
}
|
||||
if italic {
|
||||
fmt.Fprint(w, "*")
|
||||
}
|
||||
var cbuf bytes.Buffer
|
||||
for _, n := range node.Nodes {
|
||||
if err := zf.walk(&n, &cbuf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, escape(cbuf.String(), `*~\`))
|
||||
if italic {
|
||||
fmt.Fprint(w, "*")
|
||||
}
|
||||
if bold {
|
||||
fmt.Fprint(w, "**")
|
||||
}
|
||||
if strike {
|
||||
fmt.Fprint(w, "~~")
|
||||
}
|
||||
case "p":
|
||||
for _, n := range node.Nodes {
|
||||
if err := zf.walk(&n, w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
case "blip":
|
||||
if id, ok := attr(node.Attrs, "embed"); ok {
|
||||
for _, rel := range zf.rels.Relationship {
|
||||
if id != rel.ID {
|
||||
continue
|
||||
}
|
||||
if err := zf.extract(&rel, w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
case "Fallback":
|
||||
case "txbxContent":
|
||||
var cbuf bytes.Buffer
|
||||
for _, n := range node.Nodes {
|
||||
if err := zf.walk(&n, &cbuf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w, "\n```\n"+cbuf.String()+"```")
|
||||
default:
|
||||
for _, n := range node.Nodes {
|
||||
if err := zf.walk(&n, w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readFile(f *zip.File) (*Node, error) {
|
||||
rc, err := f.Open()
|
||||
defer rc.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(rc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var node Node
|
||||
err = xml.Unmarshal(b, &node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &node, nil
|
||||
}
|
||||
|
||||
func findFile(files []*zip.File, target string) *zip.File {
|
||||
for _, f := range files {
|
||||
if ok, _ := path.Match(target, f.Name); ok {
|
||||
return f
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Docx2md(arg string, embed bool) (string, error) {
|
||||
r, err := zip.OpenReader(arg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
var rels Relationships
|
||||
var num Numbering
|
||||
|
||||
for _, f := range r.File {
|
||||
switch f.Name {
|
||||
case "word/_rels/document.xml.rels":
|
||||
rc, err := f.Open()
|
||||
defer rc.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(rc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = xml.Unmarshal(b, &rels)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case "word/numbering.xml":
|
||||
rc, err := f.Open()
|
||||
defer rc.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(rc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = xml.Unmarshal(b, &num)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f := findFile(r.File, "word/document*.xml")
|
||||
if f == nil {
|
||||
return "", errors.New("incorrect document")
|
||||
}
|
||||
node, err := readFile(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fileNames := strings.Split(arg, "/")
|
||||
fileName := fileNames[len(fileNames)-1]
|
||||
// make sure the file name
|
||||
if !strings.HasSuffix(fileName, ".docx") {
|
||||
log.Fatal("File name must end with .docx")
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
zf := &file{
|
||||
r: r,
|
||||
rels: rels,
|
||||
num: num,
|
||||
embed: embed,
|
||||
list: make(map[string]int),
|
||||
name: fileName,
|
||||
}
|
||||
err = zf.walk(node, &buf)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/mindoc-org/mindoc/conf"
|
||||
)
|
||||
|
||||
func StripTags(s string) string {
|
||||
func StripTags(s string) string {
|
||||
|
||||
//将HTML标签全转换成小写
|
||||
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
|
||||
|
@ -33,8 +33,9 @@ func StripTags(s string) string {
|
|||
|
||||
return src
|
||||
}
|
||||
|
||||
//自动提取文章摘要
|
||||
func AutoSummary(body string,l int) string {
|
||||
func AutoSummary(body string, l int) string {
|
||||
|
||||
//匹配图片,如果图片语法是在代码块中,这里同样会处理
|
||||
re := regexp.MustCompile(`<p>(.*?)</p>`)
|
||||
|
@ -42,11 +43,11 @@ func AutoSummary(body string,l int) string {
|
|||
contents := re.FindAllString(body, -1)
|
||||
|
||||
if len(contents) <= 0 {
|
||||
return ""
|
||||
return ""
|
||||
}
|
||||
content := ""
|
||||
for _,s := range contents {
|
||||
b := strings.Replace(StripTags(s),"\n","", -1)
|
||||
for _, s := range contents {
|
||||
b := strings.Replace(StripTags(s), "\n", "", -1)
|
||||
|
||||
if l <= 0 {
|
||||
break
|
||||
|
@ -70,7 +71,9 @@ func SafetyProcessor(html string) string {
|
|||
docQuery.Find("applet").Remove()
|
||||
docQuery.Find("frame").Remove()
|
||||
docQuery.Find("meta").Remove()
|
||||
docQuery.Find("iframe").Remove()
|
||||
if !conf.GetEnableIframe() {
|
||||
docQuery.Find("iframe").Remove()
|
||||
}
|
||||
docQuery.Find("*").Each(func(i int, selection *goquery.Selection) {
|
||||
|
||||
if href, ok := selection.Attr("href"); ok && strings.HasPrefix(href, "javascript:") {
|
||||
|
@ -117,10 +120,9 @@ func SafetyProcessor(html string) string {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if html, err := docQuery.Html(); err == nil {
|
||||
return strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(html), "<html><head></head><body>"), "</body></html>")
|
||||
return strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(html), "<html><head></head><body>"), "</body></html>")
|
||||
}
|
||||
}
|
||||
return html
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,15 @@ package pagination
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"html/template"
|
||||
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/i18n"
|
||||
)
|
||||
|
||||
//Pagination 分页器
|
||||
|
@ -19,7 +22,7 @@ type Pagination struct {
|
|||
}
|
||||
|
||||
//NewPagination 新建分页器
|
||||
func NewPagination(req *http.Request, total int, pernum int,baseUrl string) *Pagination {
|
||||
func NewPagination(req *http.Request, total int, pernum int, baseUrl string) *Pagination {
|
||||
return &Pagination{
|
||||
Request: req,
|
||||
Total: total,
|
||||
|
@ -49,6 +52,8 @@ func (p *Pagination) Pages() string {
|
|||
//计算总页数
|
||||
var totalPageNum = int(math.Ceil(float64(p.Total) / float64(p.Pernum)))
|
||||
|
||||
lang := p.getLang()
|
||||
|
||||
//首页链接
|
||||
var firstLink string
|
||||
//上一页链接
|
||||
|
@ -62,20 +67,20 @@ func (p *Pagination) Pages() string {
|
|||
|
||||
//首页和上一页链接
|
||||
if pagenum > 1 {
|
||||
firstLink = fmt.Sprintf(`<li><a href="%s">首页</a></li>`, p.pageURL("1"))
|
||||
prevLink = fmt.Sprintf(`<li><a href="%s">上一页</a></li>`, p.pageURL(strconv.Itoa(pagenum-1)))
|
||||
firstLink = fmt.Sprintf(`<li><a href="%s">%s</a></li>`, p.pageURL("1"), i18n.Tr(lang, "page.first"))
|
||||
prevLink = fmt.Sprintf(`<li><a href="%s">%s</a></li>`, p.pageURL(strconv.Itoa(pagenum-1)), i18n.Tr(lang, "page.prev"))
|
||||
} else {
|
||||
firstLink = `<li class="disabled"><a href="#">首页</a></li>`
|
||||
prevLink = `<li class="disabled"><a href="#">上一页</a></li>`
|
||||
firstLink = fmt.Sprintf(`<li class="disabled"><a href="#">%s</a></li>`, i18n.Tr(lang, "page.first"))
|
||||
prevLink = fmt.Sprintf(`<li class="disabled"><a href="#">%s</a></li>`, i18n.Tr(lang, "page.prev"))
|
||||
}
|
||||
|
||||
//末页和下一页
|
||||
if pagenum < totalPageNum {
|
||||
lastLink = fmt.Sprintf(`<li><a href="%s">末页</a></li>`, p.pageURL(strconv.Itoa(totalPageNum)))
|
||||
nextLink = fmt.Sprintf(`<li><a href="%s">下一页</a></li>`, p.pageURL(strconv.Itoa(pagenum+1)))
|
||||
lastLink = fmt.Sprintf(`<li><a href="%s">%s</a></li>`, p.pageURL(strconv.Itoa(totalPageNum)), i18n.Tr(lang, "page.last"))
|
||||
nextLink = fmt.Sprintf(`<li><a href="%s">%s</a></li>`, p.pageURL(strconv.Itoa(pagenum+1)), i18n.Tr(lang, "page.next"))
|
||||
} else {
|
||||
lastLink = `<li class="disabled"><a href="#">末页</a></li>`
|
||||
nextLink = `<li class="disabled"><a href="#">下一页</a></li>`
|
||||
lastLink = fmt.Sprintf(`<li class="disabled"><a href="#">%s</a></li>`, i18n.Tr(lang, "page.last"))
|
||||
nextLink = fmt.Sprintf(`<li class="disabled"><a href="#">%s</a></li>`, i18n.Tr(lang, "page.next"))
|
||||
}
|
||||
|
||||
//生成中间页码链接
|
||||
|
@ -112,28 +117,18 @@ func (p *Pagination) pageURL(page string) string {
|
|||
return u.String()
|
||||
}
|
||||
|
||||
type Page struct {
|
||||
PageNo int `json:"PageNo"`
|
||||
PageSize int `json:"PageSize"`
|
||||
TotalPage int `json:"TotalPage"`
|
||||
TotalCount int `json:"TotalCount"`
|
||||
FirstPage bool `json:"FirstPage"`
|
||||
LastPage bool `json:"LastPage"`
|
||||
List interface{} `json:"List"`
|
||||
}
|
||||
|
||||
func PageUtil(count int, pageNo int, pageSize int, list interface{}) Page {
|
||||
tp := count / pageSize
|
||||
if count%pageSize > 0 {
|
||||
tp = count/pageSize + 1
|
||||
func (p *Pagination) getLang() string {
|
||||
lang, _ := web.AppConfig.String("default_lang")
|
||||
ulang := p.Request.FormValue("lang")
|
||||
if len(ulang) == 0 {
|
||||
clang, err := p.Request.Cookie("lang")
|
||||
if err != nil {
|
||||
return lang
|
||||
}
|
||||
ulang = clang.Value
|
||||
}
|
||||
return Page {
|
||||
PageNo: pageNo,
|
||||
PageSize: pageSize,
|
||||
TotalPage: tp,
|
||||
TotalCount: count,
|
||||
FirstPage: pageNo == 1,
|
||||
LastPage: pageNo == tp,
|
||||
List: list,
|
||||
if !i18n.IsExist(ulang) {
|
||||
return lang
|
||||
}
|
||||
return ulang
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<meta name="renderer" content="webkit" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="MinDoc" />
|
||||
<title>找回密码 - Powered by MinDoc</title>
|
||||
<title>{{i18n .Lang "common.account_recovery"}} - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
|
@ -35,13 +35,13 @@
|
|||
<div class="login-body">
|
||||
<form role="form" method="post" id="findPasswordForm">
|
||||
{{ .xsrfdata }}
|
||||
<h3 class="text-center">找回密码</h3>
|
||||
<h3 class="text-center">{{i18n .Lang "common.account_recovery"}}</h3>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-at"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control" placeholder="邮箱" name="email" id="email" autocomplete="off">
|
||||
<input type="text" class="form-control" placeholder="{{i18n .Lang "common.email"}}" name="email" id="email" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -49,14 +49,14 @@
|
|||
<div class="input-group-addon">
|
||||
<i class="fa fa-check-square"></i>
|
||||
</div>
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="验证码" autocomplete="off">
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="{{i18n .Lang "common.captcha"}}" autocomplete="off">
|
||||
</div>
|
||||
<img id="captcha-img" style="width: 140px;height: 40px;display: inline-block;float: right" src="{{urlfor "AccountController.Captcha"}}" onclick="this.src='{{urlfor "AccountController.Captcha"}}?key=login&t='+(new Date()).getTime();" title="点击换一张">
|
||||
<img id="captcha-img" style="width: 140px;height: 40px;display: inline-block;float: right" src="{{urlfor "AccountController.Captcha"}}" onclick="this.src='{{urlfor "AccountController.Captcha"}}?key=login&t='+(new Date()).getTime();" title="{{i18n .Lang "message.click_to_change"}}">
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" id="btnSendMail" class="btn btn-success" style="width: 100%" data-loading-text="正在处理..." autocomplete="off">找回密码</button>
|
||||
<button type="submit" id="btnSendMail" class="btn btn-success" style="width: 100%" data-loading-text="{{i18n .Lang "message.processing"}}" autocomplete="off">{{i18n .Lang "common.account_recovery"}}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
@ -88,7 +88,7 @@
|
|||
|
||||
var email = $.trim($("#email").val());
|
||||
if(email === ""){
|
||||
$("#email").tooltip({placement:"auto",title : "邮箱不能为空",trigger : 'manual'})
|
||||
$("#email").tooltip({placement:"auto",title : "{{i18n .Lang "message.email_empty"}}",trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
$btn.button('reset');
|
||||
|
@ -97,7 +97,7 @@
|
|||
}
|
||||
var code = $.trim($("#code").val());
|
||||
if(code === ""){
|
||||
$("#code").tooltip({title : '验证码不能为空',trigger : 'manual'})
|
||||
$("#code").tooltip({title : '{{i18n .Lang "message.captcha_empty"}}',trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
$btn.button('reset');
|
||||
|
@ -113,14 +113,14 @@
|
|||
layer.msg(res.message);
|
||||
$("#btnSendMail").button('reset');
|
||||
}else{
|
||||
alert("邮件发送成功,请登录邮箱查看。")
|
||||
alert("{{i18n .Lang "message.email_sent"}}")
|
||||
window.location = res.data;
|
||||
}
|
||||
},
|
||||
error :function () {
|
||||
$("#captcha-img").click();
|
||||
$("#code").val('');
|
||||
layer.msg('系统错误');
|
||||
layer.msg('{{i18n .Lang "message.system_error"}}');
|
||||
$("#btnSendMail").button('reset');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="SmartWiki" />
|
||||
<title>找回密码 - Powered by MinDoc</title>
|
||||
<meta name="author" content="MinDoc" />
|
||||
<title>{{i18n .Lang "common.account_recovery"}} - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
|
@ -37,14 +37,14 @@
|
|||
{{ .xsrfdata }}
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<input type="hidden" name="mail" value="{{.Email}}">
|
||||
<h3 class="text-center">找回密码</h3>
|
||||
<h3 class="text-center">{{i18n .Lang "common.account_recovery"}}</h3>
|
||||
<div class="form-group">
|
||||
<label for="newPasswd">新密码</label>
|
||||
<input type="password" class="form-control" name="password1" id="newPassword" maxlength="20" placeholder="新密码" autocomplete="off">
|
||||
<label for="newPasswd">{{i18n .Lang "common.new_password"}}</label>
|
||||
<input type="password" class="form-control" name="password1" id="newPassword" maxlength="20" placeholder="{{i18n .Lang "common.new_password"}}" autocomplete="off">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="configPasswd">确认密码</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="password2" maxlength="20" placeholder="确认密码" autocomplete="off">
|
||||
<label for="configPasswd">{{i18n .Lang "common.confirm_password"}}</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="password2" maxlength="20" placeholder="{{i18n .Lang "common.confirm_password"}}" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -52,13 +52,13 @@
|
|||
<div class="input-group-addon">
|
||||
<i class="fa fa-check-square"></i>
|
||||
</div>
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="验证码" autocomplete="off">
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="{{i18n .Lang "common.captcha"}}" autocomplete="off">
|
||||
</div>
|
||||
<img id="captcha-img" style="width: 140px;height: 40px;display: inline-block;float: right" src="{{urlfor "AccountController.Captcha"}}" onclick="this.src='{{urlfor "AccountController.Captcha"}}?key=login&t='+(new Date()).getTime();" title="点击换一张">
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" id="btnSendMail" class="btn btn-success" style="width: 100%" data-loading-text="正在处理..." autocomplete="off">找回密码</button>
|
||||
<button type="submit" id="btnSendMail" class="btn btn-success" style="width: 100%" data-loading-text="{{i18n .Lang "message.processing"}}" autocomplete="off">{{i18n .Lang "common.account_recovery"}}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
@ -92,26 +92,26 @@
|
|||
var code = $.trim($("#code").val());
|
||||
|
||||
if(newPassword === ""){
|
||||
$("#newPassword").tooltip({placement:"auto",title : "密码不能为空",trigger : 'manual'})
|
||||
$("#newPassword").tooltip({placement:"auto",title : "{{i18n .Lang "message.password_empty"}}",trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
|
||||
return false;
|
||||
|
||||
}else if(confirmPassword === ""){
|
||||
$("#confirmPassword").tooltip({placement:"auto",title : "确认密码不能为空",trigger : 'manual'})
|
||||
$("#confirmPassword").tooltip({placement:"auto",title : "{{i18n .Lang "message.confirm_password_empty"}}",trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
|
||||
return false;
|
||||
}else if(newPassword !== confirmPassword) {
|
||||
$("#confirmPassword").tooltip({placement:"auto",title : "确认密码输入不正确",trigger : 'manual'})
|
||||
$("#confirmPassword").tooltip({placement:"auto",title : "{{i18n .Lang "message.incorrect_confirm_password"}}",trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
|
||||
return false;
|
||||
}else if(code === ""){
|
||||
$("#code").tooltip({title : '验证码不能为空',trigger : 'manual'})
|
||||
$("#code").tooltip({title : '{{i18n .Lang "message.captcha_empty"}}',trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
|
||||
|
@ -134,7 +134,7 @@
|
|||
error :function () {
|
||||
$("#captcha-img").click();
|
||||
$("#code").val('');
|
||||
layer.msg('系统错误');
|
||||
layer.msg('{{i18n .Lang "message.system_error"}}');
|
||||
$("#btnSendMail").button('reset');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<meta name="renderer" content="webkit" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="MinDoc" />
|
||||
<title>用户登录 - Powered by MinDoc</title>
|
||||
<title>{{i18n .Lang "common.login"}} - Powered by MinDoc</title>
|
||||
<meta name="keywords" content="MinDoc,文档在线管理系统,WIKI,wiki,wiki在线,文档在线管理,接口文档在线管理,接口文档管理">
|
||||
<meta name="description" content="MinDoc文档在线管理系统 {{.site_description}}">
|
||||
<!-- Bootstrap -->
|
||||
|
@ -30,13 +30,13 @@
|
|||
<div class="login-body">
|
||||
<form role="form" method="post">
|
||||
{{ .xsrfdata }}
|
||||
<h3 class="text-center">用户登录</h3>
|
||||
<h3 class="text-center">{{i18n .Lang "common.login"}}</h3>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-user"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control" placeholder="邮箱 / 用户名" name="account" id="account" autocomplete="off">
|
||||
<input type="text" class="form-control" placeholder="{{i18n .Lang "common.email"}} / {{i18n .Lang "common.username"}}" name="account" id="account" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -44,7 +44,7 @@
|
|||
<div class="input-group-addon">
|
||||
<i class="fa fa-lock"></i>
|
||||
</div>
|
||||
<input type="password" class="form-control" placeholder="密码" name="password" id="password" autocomplete="off">
|
||||
<input type="password" class="form-control" placeholder="{{i18n .Lang "common.password"}}" name="password" id="password" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
{{if .ENABLED_CAPTCHA }}
|
||||
|
@ -54,38 +54,38 @@
|
|||
<div class="input-group-addon">
|
||||
<i class="fa fa-check-square"></i>
|
||||
</div>
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="验证码" autocomplete="off">
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="{{i18n .Lang "common.captcha"}}" autocomplete="off">
|
||||
</div>
|
||||
<img id="captcha-img" style="width: 140px;height: 40px;display: inline-block;float: right" src="{{urlfor "AccountController.Captcha"}}" onclick="this.src='{{urlfor "AccountController.Captcha"}}?key=login&t='+(new Date()).getTime();" title="点击换一张">
|
||||
<img id="captcha-img" style="width: 140px;height: 40px;display: inline-block;float: right" src="{{urlfor "AccountController.Captcha"}}" onclick="this.src='{{urlfor "AccountController.Captcha"}}?key=login&t='+(new Date()).getTime();" title={{i18n .Lang "message.click_to_change"}}>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="is_remember" value="yes"> 保持登录
|
||||
<input type="checkbox" name="is_remember" value="yes"> {{i18n .Lang "common.keep_login"}}
|
||||
</label>
|
||||
<a href="{{urlfor "AccountController.FindPassword" }}" style="display: inline-block;float: right">忘记密码?</a>
|
||||
<a href="{{urlfor "AccountController.FindPassword" }}" style="display: inline-block;float: right">{{i18n .Lang "common.forgot_password"}}</a>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" id="btn-login" class="btn btn-success" style="width: 100%" data-loading-text="正在登录..." autocomplete="off">立即登录</button>
|
||||
<button type="button" id="btn-login" class="btn btn-success" style="width: 100%" data-loading-text="{{i18n .Lang "common.logging_in"}}" autocomplete="off">{{i18n .Lang "common.login"}}</button>
|
||||
</div>
|
||||
{{if .ENABLE_QR_DINGTALK}}
|
||||
<div class="form-group">
|
||||
<a id="btn-dingtalk-qr" class="btn btn-default" style="width: 100%" data-loading-text="" autocomplete="off">钉钉扫码登录</a>
|
||||
<a id="btn-dingtalk-qr" class="btn btn-default" style="width: 100%" data-loading-text="" autocomplete="off">{{i18n .Lang "common.dingtalk_login"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .ENABLED_REGISTER}}
|
||||
{{if ne .ENABLED_REGISTER "false"}}
|
||||
<div class="form-group">
|
||||
还没有账号?<a href="{{urlfor "AccountController.Register" }}" title="立即注册">立即注册</a>
|
||||
{{i18n .Lang "message.no_account_yet"}} <a href="{{urlfor "AccountController.Register" }}" title={{i18n .Lang "common.register"}}>{{i18n .Lang "common.register"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</form>
|
||||
<div class="form-group dingtalk-container" style="display: none;">
|
||||
<div id="dingtalk-qr-container"></div>
|
||||
<a class="btn btn-default btn-dingtalk" style="width: 100%" data-loading-text="" autocomplete="off">返回账号密码登录</a>
|
||||
<a class="btn btn-default btn-dingtalk" style="width: 100%" data-loading-text="" autocomplete="off">{{i18n .Lang "message.return_account_login"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -196,19 +196,19 @@
|
|||
var code = $("#code").val();
|
||||
|
||||
if (account === "") {
|
||||
$("#account").tooltip({ placement: "auto", title: "账号不能为空", trigger: 'manual' })
|
||||
$("#account").tooltip({ placement: "auto", title: "{{i18n .Lang "message.account_empty"}}", trigger: 'manual' })
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
$btn.button('reset');
|
||||
return false;
|
||||
} else if (password === "") {
|
||||
$("#password").tooltip({ title: '密码不能为空', trigger: 'manual' })
|
||||
$("#password").tooltip({ title: '{{i18n .Lang "message.password_empty"}}', trigger: 'manual' })
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
$btn.button('reset');
|
||||
return false;
|
||||
} else if (code !== undefined && code === "") {
|
||||
$("#code").tooltip({ title: '验证码不能为空', trigger: 'manual' })
|
||||
$("#code").tooltip({ title: '{{i18n .Lang "message.captcha_empty"}}', trigger: 'manual' })
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
$btn.button('reset');
|
||||
|
@ -236,7 +236,7 @@
|
|||
error: function () {
|
||||
$("#captcha-img").click();
|
||||
$("#code").val('');
|
||||
layer.msg('系统错误');
|
||||
layer.msg('{{i18n .Lang "message.system_error"}}');
|
||||
$btn.button('reset');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="SmartWiki" />
|
||||
<title>用户注册 - Powered by MinDoc</title>
|
||||
<meta name="author" content="MinDoc" />
|
||||
<title>{{i18n .Lang "common.new_account"}} - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
|
@ -35,13 +35,13 @@
|
|||
<div class="login-body">
|
||||
<form role="form" method="post" id="registerForm">
|
||||
{{ .xsrfdata }}
|
||||
<h3 class="text-center">用户注册</h3>
|
||||
<h3 class="text-center">{{i18n .Lang "common.new_account"}}</h3>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-user"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control" placeholder="用户名" name="account" id="account" autocomplete="off">
|
||||
<input type="text" class="form-control" placeholder="{{i18n .Lang "common.username"}}" name="account" id="account" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -49,7 +49,7 @@
|
|||
<div class="input-group-addon">
|
||||
<i class="fa fa-lock"></i>
|
||||
</div>
|
||||
<input type="password" class="form-control" placeholder="密码" name="password1" id="password1" autocomplete="off">
|
||||
<input type="password" class="form-control" placeholder="{{i18n .Lang "common.password"}}" name="password1" id="password1" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -57,13 +57,13 @@
|
|||
<div class="input-group-addon">
|
||||
<i class="fa fa-lock"></i>
|
||||
</div>
|
||||
<input type="password" class="form-control" placeholder="确认密码" name="password2" id="password2" autocomplete="off">
|
||||
<input type="password" class="form-control" placeholder="{{i18n .Lang "common.confirm_password"}}" name="password2" id="password2" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon" style="padding: 6px 9px;"><i class="fa fa-envelope"></i></div>
|
||||
<input type="email" class="form-control" placeholder="用户邮箱" name="email" id="email" autocomplete="off">
|
||||
<input type="email" class="form-control" placeholder="{{i18n .Lang "common.email"}}" name="email" id="email" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -72,18 +72,18 @@
|
|||
<div class="input-group-addon">
|
||||
<i class="fa fa-check-square"></i>
|
||||
</div>
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="验证码" autocomplete="off">
|
||||
<input type="text" name="code" id="code" class="form-control" style="width: 150px" maxlength="5" placeholder="{{i18n .Lang "common.captcha"}}" autocomplete="off">
|
||||
</div>
|
||||
<img id="captcha-img" style="width: 140px;height: 40px;display: inline-block;float: right" src="{{urlfor "AccountController.Captcha"}}" onclick="this.src='{{urlfor "AccountController.Captcha"}}?key=login&t='+(new Date()).getTime();" title="点击换一张">
|
||||
<img id="captcha-img" style="width: 140px;height: 40px;display: inline-block;float: right" src="{{urlfor "AccountController.Captcha"}}" onclick="this.src='{{urlfor "AccountController.Captcha"}}?key=login&t='+(new Date()).getTime();" title="{{i18n .Lang "message.click_to_change"}}">
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" id="btnRegister" class="btn btn-success" style="width: 100%" data-loading-text="正在注册..." autocomplete="off">立即注册</button>
|
||||
<button type="submit" id="btnRegister" class="btn btn-success" style="width: 100%" data-loading-text="{{i18n .Lang "message.processing"}}" autocomplete="off">{{i18n .Lang "common.register"}}</button>
|
||||
</div>
|
||||
{{if ne .ENABLED_REGISTER "false"}}
|
||||
<div class="form-group">
|
||||
已有账号?<a href="{{urlfor "AccountController.Login" }}" title="立即登录">立即登录</a>
|
||||
{{i18n .Lang "message.has_account"}} <a href="{{urlfor "AccountController.Login" }}" title="{{i18n .Lang "common.login"}}">{{i18n .Lang "common.login"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</form>
|
||||
|
@ -117,28 +117,28 @@
|
|||
var email = $.trim($("#email").val());
|
||||
|
||||
if(account === ""){
|
||||
$("#account").focus().tooltip({placement:"auto",title : "账号不能为空",trigger : 'manual'})
|
||||
$("#account").focus().tooltip({placement:"auto",title : "{{i18n .Lang "message.account_empty"}}",trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
return false;
|
||||
|
||||
}else if(password === ""){
|
||||
$("#password").focus().tooltip({title : '密码不能为空',trigger : 'manual'})
|
||||
$("#password").focus().tooltip({title : '{{i18n .Lang "message.password_empty"}}',trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
return false;
|
||||
}else if(confirmPassword !== password){
|
||||
$("#confirm_password").focus().tooltip({title : '确认密码不正确',trigger : 'manual'})
|
||||
$("#confirm_password").focus().tooltip({title : '{{i18n .Lang "message.confirm_password_empty"}}',trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
return false;
|
||||
}else if(email === ""){
|
||||
$("#email").focus().tooltip({title : '邮箱不能为空',trigger : 'manual'})
|
||||
$("#email").focus().tooltip({title : '{{i18n .Lang "message.email_empty"}}',trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
return false;
|
||||
}else if(code !== undefined && code === ""){
|
||||
$("#code").focus().tooltip({title : '验证码不能为空',trigger : 'manual'})
|
||||
$("#code").focus().tooltip({title : '{{i18n .Lang "message.captcha_empty"}}',trigger : 'manual'})
|
||||
.tooltip('show')
|
||||
.parents('.form-group').addClass('has-error');
|
||||
return false;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
|
||||
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/editor.md/lib/mermaid/mermaid.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/editor.md/lib/sequence/sequence-diagram-min.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/css/kancloud.css" "version"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/editor.md/css/editormd.preview.css"}}" rel="stylesheet">
|
||||
|
@ -82,13 +81,13 @@
|
|||
<div class="blog-meta">
|
||||
<div class="item user_img"><img src="{{cdnimg .Model.MemberAvatar}}" align="{{.Model.CreateName}}"> </div>
|
||||
<div class="item"> {{.Model.CreateName}}</div>
|
||||
<div class="item">发布于</div>
|
||||
<div class="item">{{i18n .Lang "blog.posted_on"}}</div>
|
||||
<div class="item">{{date .Model.Created "Y-m-d H:i:s"}}</div>
|
||||
<div class="item">{{.Model.ModifyRealName}}</div>
|
||||
<div class="item">修改于</div>
|
||||
<div class="item">{{i18n .Lang "blog.modified_on"}}</div>
|
||||
<div class="item">{{date .Model.Modified "Y-m-d H:i:s"}}</div>
|
||||
{{if eq .Member.MemberId .Model.MemberId}}
|
||||
<div class="item"><a href='{{urlfor "BlogController.ManageEdit" ":id" .Model.BlogId}}' title="文章编辑"><i class="fa fa-edit"></i> 编辑</a></div>
|
||||
<div class="item"><a href='{{urlfor "BlogController.ManageEdit" ":id" .Model.BlogId}}' title="{{i18n .Lang "blog.edit_blog"}}"><i class="fa fa-edit"></i> {{i18n .Lang "common.edit"}}</a></div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -96,7 +95,7 @@
|
|||
<div class="article-body markdown-body editormd-preview-container content">
|
||||
{{.Content}}
|
||||
{{if .Model.AttachList}}
|
||||
<div class="attach-list"><strong>附件</strong><ul>
|
||||
<div class="attach-list"><strong>{{i18n .Lang "blog.attachment"}}</strong><ul>
|
||||
{{range $index,$item := .Model.AttachList}}
|
||||
<li><a href="{{$item.HttpPath}}" title="{{$item.FileName}}">{{$item.FileName}}</a> </li>
|
||||
{{end}}
|
||||
|
@ -106,20 +105,20 @@
|
|||
</div>
|
||||
<div class="row blog-footer">
|
||||
<p>
|
||||
<span>上一篇</span>
|
||||
<span>{{i18n .Lang "blog.prev"}}</span>
|
||||
{{if .Previous}}
|
||||
<a href="{{urlfor "BlogController.Index" ":id" .Previous.BlogId}}" title="{{.Previous.BlogTitle}}">{{.Previous.BlogTitle}}
|
||||
</a>
|
||||
{{else}}
|
||||
无
|
||||
{{i18n .Lang "blog.no"}}
|
||||
{{end}}
|
||||
</p>
|
||||
<p>
|
||||
<span>下一篇</span>
|
||||
<span>{{i18n .Lang "blog.next"}}</span>
|
||||
{{if .Next}}
|
||||
<a href="{{urlfor "BlogController.Index" ":id" .Next.BlogId}}" title="{{.Next.BlogTitle}}">{{.Next.BlogTitle}}</a>
|
||||
{{else}}
|
||||
无
|
||||
{{i18n .Lang "blog.no"}}
|
||||
{{end}}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>请输入文章密码 - Powered by MinDoc</title>
|
||||
<title>{{i18n .Lang "doc.input_pwd"}} - Powered by MinDoc</title>
|
||||
<script src="{{cdnjs "static/jquery/1.12.4/jquery.min.js"}}"></script>
|
||||
<script src="{{cdnjs "static/js/jquery.form.js"}}"></script>
|
||||
<style type="text/css">
|
||||
|
@ -99,14 +99,14 @@
|
|||
<form action="{{urlfor "BlogController.Index" ":id" .Model.BlogId}}" method="post" id="auth_form">
|
||||
<input type="hidden" value="{{.Model.BlogId}}" name="blogId" />
|
||||
<div class="tit">
|
||||
请输入浏览密码
|
||||
{{i18n .Lang "doc.input_pwd"}}
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<input type="password" name="password" placeholder="浏览密码" class="inp"/>
|
||||
<input type="password" name="password" placeholder="{{i18n .Lang "blog.access_pass"}}" class="inp"/>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<span id="error" style="color: #919191; font-size: 13px;"></span>
|
||||
<input type="submit" value="提交" class="button"/>
|
||||
<input type="submit" value="{{i18n .Lang "doc.commit"}}" class="button"/>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</form>
|
||||
|
@ -117,7 +117,7 @@ $("#auth_form").ajaxForm({
|
|||
beforeSerialize: function () {
|
||||
var pwd = $("#auth_form input[name='password']").val();
|
||||
if (pwd === "") {
|
||||
$("#error").html("请输入密码");
|
||||
$("#error").html("{{i18n .Lang "doc.input_pwd"}}");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>文章列表 - Powered by MinDoc</title>
|
||||
<title>{{i18n .Lang "blog.blog_list"}} - Powered by MinDoc</title>
|
||||
<meta name="keywords" content="MinDoc,文档在线管理系统,WIKI,wiki,wiki在线,文档在线管理,接口文档在线管理,接口文档管理">
|
||||
<meta name="description" content="MinDoc文档在线管理系统 {{.site_description}}">
|
||||
<!-- Bootstrap -->
|
||||
|
@ -30,20 +30,20 @@
|
|||
<div class="manual-list">
|
||||
{{range $index,$item := .Lists}}
|
||||
<div class="search-item">
|
||||
<div class="title">{{if eq $item.BlogStatus "password"}}<span class="label">密</span>{{end}} <a href="{{urlfor "BlogController.Index" ":id" $item.BlogId}}" title="{{$item.BlogTitle}}">{{$item.BlogTitle}}</a> </div>
|
||||
<div class="title">{{if eq $item.BlogStatus "password"}}<span class="label">{{i18n $.Lang "blog.encrypt"}}</span>{{end}} <a href="{{urlfor "BlogController.Index" ":id" $item.BlogId}}" title="{{$item.BlogTitle}}">{{$item.BlogTitle}}</a> </div>
|
||||
<div class="description">
|
||||
{{$item.BlogExcerpt}}
|
||||
</div>
|
||||
{{/*<div class="site">{{urlfor "BlogController.Index" ":id" $item.BlogId}}</div>*/}}
|
||||
<div class="source">
|
||||
<span class="item">作者:{{$item.CreateName}}</span>
|
||||
<span class="item">更新时间:{{date_format $item.Modified "2006-01-02 15:04:05"}}</span>
|
||||
<span class="item">{{i18n $.Lang "blog.author"}}:{{$item.CreateName}}</span>
|
||||
<span class="item">{{i18n $.Lang "blog.update_time"}}:{{date_format $item.Modified "2006-01-02 15:04:05"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="search-empty">
|
||||
<img src="{{cdnimg "/static/images/search_empty.png"}}" class="empty-image">
|
||||
<span class="empty-text">暂无文章</span>
|
||||
<span class="empty-text">{{i18n $.Lang "blog.no_blog"}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
<nav class="pagination-container">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>编辑文章 - Powered by MinDoc</title>
|
||||
<title>{{i18n .Lang "blog.edit_title"}} - Powered by MinDoc</title>
|
||||
<script type="text/javascript">
|
||||
window.baseUrl = "{{.BaseUrl}}";
|
||||
window.katex = { js: "{{cdnjs "/static/katex/katex"}}",css: "{{cdncss "/static/katex/katex"}}"};
|
||||
|
@ -18,12 +18,13 @@
|
|||
window.blogVersion = {{.Model.Version}};
|
||||
window.removeAttachURL = "{{urlfor "BlogController.RemoveAttachment" ":id" .Model.BlogId}}";
|
||||
window.highlightStyle = "{{.HighlightStyle}}";
|
||||
window.lang = {{i18n $.Lang "common.js_lang"}};
|
||||
</script>
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/jstree/3.3.4/themes/default/style.min.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/editor.md/css/editormd.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/editor.md/css/editormd.css" "version"}}" rel="stylesheet">
|
||||
|
||||
<link href="{{cdncss "/static/css/jstree.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/webuploader/webuploader.css"}}" rel="stylesheet">
|
||||
|
@ -35,50 +36,50 @@
|
|||
<div class="m-manual manual-editor">
|
||||
<div class="manual-head" id="editormd-tools" style="min-width: 1200px; position:absolute;">
|
||||
<div class="editormd-group">
|
||||
<a href="{{urlfor "BlogController.ManageList"}}" data-toggle="tooltip" data-title="返回"><i class="fa fa-chevron-left" aria-hidden="true"></i></a>
|
||||
<a href="{{urlfor "BlogController.ManageList"}}" data-toggle="tooltip" data-title="{{i18n .Lang "doc.backward"}}"><i class="fa fa-chevron-left" aria-hidden="true"></i></a>
|
||||
</div>
|
||||
<div class="editormd-group">
|
||||
<a href="javascript:;" id="markdown-save" data-toggle="tooltip" data-title="保存" class="disabled save"><i class="fa fa-save" aria-hidden="true" name="save"></i></a>
|
||||
<a href="javascript:;" id="markdown-save" data-toggle="tooltip" data-title="{{i18n .Lang "doc.save"}}" class="disabled save"><i class="fa fa-save" aria-hidden="true" name="save"></i></a>
|
||||
</div>
|
||||
<div class="editormd-group">
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="撤销 (Ctrl-Z)"><i class="fa fa-undo first" name="undo" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="重做 (Ctrl-Y)"><i class="fa fa-repeat last" name="redo" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.undo"}} (Ctrl-Z)"><i class="fa fa-undo first" name="undo" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.redo"}} (Ctrl-Y)"><i class="fa fa-repeat last" name="redo" unselectable="on"></i></a>
|
||||
</div>
|
||||
<div class="editormd-group">
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="粗体"><i class="fa fa-bold first" name="bold" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="斜体"><i class="fa fa-italic item" name="italic" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="删除线"><i class="fa fa-strikethrough last" name="del" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.bold"}}"><i class="fa fa-bold first" name="bold" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.italic"}}"><i class="fa fa-italic item" name="italic" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.strikethrough"}}"><i class="fa fa-strikethrough last" name="del" unselectable="on"></i></a>
|
||||
</div>
|
||||
<div class="editormd-group">
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="标题一"><i class="fa editormd-bold first" name="h1" unselectable="on">H1</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="标题二"><i class="fa editormd-bold item" name="h2" unselectable="on">H2</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="标题三"><i class="fa editormd-bold item" name="h3" unselectable="on">H3</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="标题四"><i class="fa editormd-bold item" name="h4" unselectable="on">H4</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="标题五"><i class="fa editormd-bold item" name="h5" unselectable="on">H5</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="标题六"><i class="fa editormd-bold last" name="h6" unselectable="on">H6</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h1"}}"><i class="fa editormd-bold first" name="h1" unselectable="on">H1</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h2"}}"><i class="fa editormd-bold item" name="h2" unselectable="on">H2</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h3"}}"><i class="fa editormd-bold item" name="h3" unselectable="on">H3</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h4"}}"><i class="fa editormd-bold item" name="h4" unselectable="on">H4</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h5"}}"><i class="fa editormd-bold item" name="h5" unselectable="on">H5</i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h6"}}"><i class="fa editormd-bold last" name="h6" unselectable="on">H6</i></a>
|
||||
</div>
|
||||
<div class="editormd-group">
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="无序列表"><i class="fa fa-list-ul first" name="list-ul" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="有序列表"><i class="fa fa-list-ol item" name="list-ol" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="横线"><i class="fa fa-minus last" name="hr" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.unorder_list"}}"><i class="fa fa-list-ul first" name="list-ul" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.order_list"}}"><i class="fa fa-list-ol item" name="list-ol" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.hline"}}"><i class="fa fa-minus last" name="hr" unselectable="on"></i></a>
|
||||
</div>
|
||||
<div class="editormd-group">
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="链接"><i class="fa fa-link first" name="link" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="引用链接"><i class="fa fa-anchor item" name="reference-link" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="添加图片"><i class="fa fa-picture-o item" name="image" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="行内代码"><i class="fa fa-code item" name="code" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="代码块" unselectable="on"><i class="fa fa-file-code-o item" name="code-block" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="添加表格"><i class="fa fa-table item" name="table" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="引用"><i class="fa fa-quote-right item" name="quote" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="GFM 任务列表"><i class="fa fa-tasks item" name="tasks" aria-hidden="true"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="附件"><i class="fa fa-paperclip item" aria-hidden="true" name="attachment"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="模板"><i class="fa fa-tachometer last" name="template"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.link"}}"><i class="fa fa-link first" name="link" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.ref_link"}}"><i class="fa fa-anchor item" name="reference-link" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.add_pic"}}"><i class="fa fa-picture-o item" name="image" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.code"}}"><i class="fa fa-code item" name="code" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.code_block"}}" unselectable="on"><i class="fa fa-file-code-o item" name="code-block" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.table"}}"><i class="fa fa-table item" name="table" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.quote"}}"><i class="fa fa-quote-right item" name="quote" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.gfm_task"}}"><i class="fa fa-tasks item" name="tasks" aria-hidden="true"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.attachment"}}"><i class="fa fa-paperclip item" aria-hidden="true" name="attachment"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.template"}}"><i class="fa fa-tachometer last" name="template"></i></a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="editormd-group pull-right">
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="关闭实时预览"><i class="fa fa-eye-slash first" name="watch" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="使用帮助"><i class="fa fa-question-circle-o last" aria-hidden="true" name="help"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.close_preview"}}"><i class="fa fa-eye-slash first" name="watch" unselectable="on"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.help"}}"><i class="fa fa-question-circle-o last" aria-hidden="true" name="help"></i></a>
|
||||
</div>
|
||||
|
||||
<div class="editormd-group">
|
||||
|
@ -94,7 +95,7 @@
|
|||
<div id="docEditor" class="manual-editormd-active"><textarea style="display: none">{{str2html .Model.BlogContent}}</textarea> </div>
|
||||
</div>
|
||||
<div class="manual-editor-status">
|
||||
<div id="attachInfo" class="item">0 个附件</div>
|
||||
<div id="attachInfo" class="item">0 {{i18n .Lang "doc.attachments"}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -109,7 +110,7 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="myModalLabel">上传附件</h4>
|
||||
<h4 class="modal-title" id="myModalLabel">{{i18n .Lang "doc.upload_attachment"}}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="attach-drop-panel">
|
||||
|
@ -146,8 +147,8 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<span id="add-error-message" class="error-message"></span>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary" id="btnUploadAttachFile" data-dismiss="modal">确定</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n .Lang "common.cancel"}}</button>
|
||||
<button type="button" class="btn btn-primary" id="btnUploadAttachFile" data-dismiss="modal">{{i18n .Lang "common.confirm"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -156,44 +157,44 @@
|
|||
<!-- Modal -->
|
||||
|
||||
|
||||
<div class="modal fade" id="documentTemplateModal" tabindex="-1" role="dialog" aria-labelledby="请选择模板类型" aria-hidden="true">
|
||||
<div class="modal fade" id="documentTemplateModal" tabindex="-1" role="dialog" aria-labelledby="{{i18n .Lang "doc.choose_template_type"}}" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-title">请选择模板类型</h4>
|
||||
<h4 class="modal-title" id="modal-title">{{i18n .Lang "doc.choose_template_type"}}</h4>
|
||||
</div>
|
||||
<div class="modal-body template-list">
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<a data-type="normal" href="javascript:;"><i class="fa fa-file-o"></i></a>
|
||||
<h3><a data-type="normal" href="javascript:;">普通文档</a></h3>
|
||||
<h3><a data-type="normal" href="javascript:;">{{i18n .Lang "doc.normal_tpl"}}</a></h3>
|
||||
<ul>
|
||||
<li>默认类型</li>
|
||||
<li>简单的文本文档</li>
|
||||
<li>{{i18n .Lang "doc.tpl_default_type"}}</li>
|
||||
<li>{{i18n .Lang "doc.tpl_plain_text"}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<a data-type="api" href="javascript:;"><i class="fa fa-file-code-o"></i></a>
|
||||
<h3><a data-type="api" href="javascript:;">API文档</a></h3>
|
||||
<h3><a data-type="api" href="javascript:;">{{i18n .Lang "doc.api_tpl"}}</a></h3>
|
||||
<ul>
|
||||
<li>用于API文档速写</li>
|
||||
<li>支持代码高亮</li>
|
||||
<li>{{i18n .Lang "doc.for_api_doc"}}</li>
|
||||
<li>{{i18n .Lang "doc.code_highlight"}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<a data-type="code" href="javascript:;"><i class="fa fa-book"></i></a>
|
||||
|
||||
<h3><a data-type="code" href="javascript:;">数据字典</a></h3>
|
||||
<h3><a data-type="code" href="javascript:;">{{i18n .Lang "doc.data_dict"}}</a></h3>
|
||||
<ul>
|
||||
<li>用于数据字典显示</li>
|
||||
<li>表格支持</li>
|
||||
<li>{{i18n .Lang "doc.for_data_dict"}}</li>
|
||||
<li>{{i18n .Lang "doc.form_support"}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n .Lang "common.cancel"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -212,7 +213,7 @@
|
|||
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
||||
<script src="{{cdnjs "/static/webuploader/webuploader.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/jstree/3.3.4/jstree.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/editor.md/editormd.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/editor.md/editormd.min.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
||||
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/array.js" "version"}}" type="text/javascript"></script>
|
||||
|
@ -220,6 +221,13 @@
|
|||
<script src="{{cdnjs "/static/js/blog.js" "version"}}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
editLangPath = {{cdnjs "/static/editor.md/languages/"}} + lang
|
||||
if(lang != 'zh-CN') {
|
||||
editormd.loadScript(editLangPath, function(){
|
||||
window.editor.lang = editormd.defaults.lang;
|
||||
window.editor.recreate()
|
||||
});
|
||||
}
|
||||
window.vueApp.lists = {{.AttachList}};
|
||||
$("#attachInfo").on("click",function () {
|
||||
$("#uploadAttachModal").modal("show");
|
||||
|
@ -245,7 +253,7 @@
|
|||
attachment_id : file.id,
|
||||
file_size : file.size,
|
||||
file_name : file.name,
|
||||
message : "正在上传"
|
||||
message : "{{i18n .Lang "doc.uploading"}}"
|
||||
};
|
||||
window.vueApp.lists.push(item);
|
||||
|
||||
|
@ -254,7 +262,8 @@
|
|||
var item = window.vueApp.lists[i];
|
||||
if(item.attachment_id == file.id){
|
||||
item.state = "error";
|
||||
item.message = "上传失败:" + reason;
|
||||
item.message = "{{i18n .Lang "message.upload_failed"}}:" + reason;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,7 +273,7 @@
|
|||
var item = window.vueApp.lists[index];
|
||||
if(item.attachment_id === file.id){
|
||||
if(res.errcode === 0) {
|
||||
window.vueApp.lists.splice(index, 1, res.attach?res.attach:res.data);
|
||||
window.vueApp.lists.splice(index, 1, res.attach ? res.attach : res.data);
|
||||
}else{
|
||||
item.message = res.message;
|
||||
item.state = "error";
|
||||
|
@ -278,7 +287,7 @@
|
|||
$percent.css( 'width', percentage * 100 + '%' );
|
||||
}).on("error", function (type) {
|
||||
if(type === "F_EXCEED_SIZE"){
|
||||
layer.msg("文件超过了限定大小");
|
||||
layer.msg("{{i18n .Lang "message.upload_file_size_limit"}}");
|
||||
}
|
||||
console.log(type);
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>我的文章 - Powered by MinDoc</title>
|
||||
<title>{{i18n .Lang "common.my_blog"}} - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
|
||||
|
@ -27,16 +27,16 @@
|
|||
<div class="row">
|
||||
<div class="page-left">
|
||||
<ul class="menu">
|
||||
<li {{if eq .ControllerName "BookController"}}class="active"{{end}}><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 我的项目</a> </li>
|
||||
<li {{if eq .ControllerName "BlogController"}}class="active"{{end}}><a href="{{urlfor "BlogController.ManageList"}}" class="item"><i class="fa fa-file" aria-hidden="true"></i> 我的文章</a> </li>
|
||||
<li {{if eq .ControllerName "BookController"}}class="active"{{end}}><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> {{i18n .Lang "common.my_project"}}</a> </li>
|
||||
<li {{if eq .ControllerName "BlogController"}}class="active"{{end}}><a href="{{urlfor "BlogController.ManageList"}}" class="item"><i class="fa fa-file" aria-hidden="true"></i> {{i18n .Lang "common.my_blog"}}</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="page-right">
|
||||
<div class="m-box">
|
||||
<div class="box-head">
|
||||
<strong class="box-title">文章列表</strong>
|
||||
<strong class="box-title">{{i18n .Lang "blog.blog_list"}}</strong>
|
||||
|
||||
<a href="{{urlfor "BlogController.ManageSetting"}}" class="btn btn-success btn-sm pull-right">添加文章</a>
|
||||
<a href="{{urlfor "BlogController.ManageSetting"}}" class="btn btn-success btn-sm pull-right">{{i18n .Lang "blog.add_blog"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body" id="blogList">
|
||||
|
@ -46,7 +46,7 @@
|
|||
<div class="content">
|
||||
<a class="header" href="{{urlfor "BlogController.Index" ":id" $item.BlogId}}" target="_blank">
|
||||
{{if eq $item.BlogStatus "password"}}
|
||||
<div class="ui teal label horizontal" data-tooltip="加密">密</div>
|
||||
<div class="ui teal label horizontal" data-tooltip="{{i18n $.Lang "blog.encryption"}}">{{i18n $.Lang "blog.encrypt"}}</div>
|
||||
{{end}}
|
||||
{{$item.BlogTitle}}
|
||||
</a>
|
||||
|
@ -57,16 +57,16 @@
|
|||
<div>
|
||||
<div class="ui horizontal small list">
|
||||
<div class="item"><i class="fa fa-clock-o"></i> {{date $item.Modified "Y-m-d H:i:s"}}</div>
|
||||
<div class="item"><a href="{{urlfor "BlogController.ManageEdit" ":id" $item.BlogId}}" title="文章编辑" target="_blank"><i class="fa fa-edit"></i> 编辑</a></div>
|
||||
<div class="item"><a class="delete-btn" title="删除文章" data-id="{{$item.BlogId}}"><i class="fa fa-trash"></i> 删除</a></div>
|
||||
<div class="item"><a href="{{urlfor "BlogController.ManageSetting" ":id" $item.BlogId}}" title="文章设置" class="setting-btn"><i class="fa fa-gear"></i> 设置</a></div>
|
||||
<div class="item"><a href="{{urlfor "BlogController.ManageEdit" ":id" $item.BlogId}}" title="{{i18n $.Lang "blog.edit_blog"}}" target="_blank"><i class="fa fa-edit"></i> {{i18n $.Lang "blog.edit"}}</a></div>
|
||||
<div class="item"><a class="delete-btn" title="{{i18n $.Lang "blog.delete_blog"}}" data-id="{{$item.BlogId}}"><i class="fa fa-trash"></i> {{i18n $.Lang "blog.delete"}}</a></div>
|
||||
<div class="item"><a href="{{urlfor "BlogController.ManageSetting" ":id" $item.BlogId}}" title="{{i18n $.Lang "blog.setting_blog"}}" class="setting-btn"><i class="fa fa-gear"></i> {{i18n $.Lang "common.setting"}}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="text-center">暂无文章</div>
|
||||
<div class="text-center">{{i18n .Lang "blog.no_blog"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<nav class="pagination-container">
|
||||
|
@ -88,17 +88,17 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">删除文章</h4>
|
||||
<h4 class="modal-title">{{i18n .Lang "blog.delete_blog"}}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<span style="font-size: 14px;font-weight: 400;">确定删除文章吗?</span>
|
||||
<span style="font-size: 14px;font-weight: 400;">{{i18n .Lang "message.confirm_delete_blog"}}</span>
|
||||
<p></p>
|
||||
<p class="text error-message">删除文章后将无法找回。</p>
|
||||
<p class="text error-message">{{i18n .Lang "message.delete_blog_tips"}}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<span id="form-error-message2" class="error-message"></span>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||
<button type="submit" id="btnDeleteBlog" class="btn btn-primary" data-loading-text="删除中...">确定删除</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n .Lang "common.cancel"}}</button>
|
||||
<button type="submit" id="btnDeleteBlog" class="btn btn-primary" data-loading-text="{{i18n .Lang "message.process"}}">{{i18n .Lang "common.confirm_delete"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -140,7 +140,7 @@
|
|||
},
|
||||
error : function () {
|
||||
layer.close(index);
|
||||
layer.msg('服务器异常');
|
||||
layer.msg({{i18n .Lang "message.system_error"}});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -166,7 +166,7 @@
|
|||
$("#btnDeleteBlog").button("reset");
|
||||
},
|
||||
error : function () {
|
||||
showError("服务器异常","#form-error-message2");
|
||||
showError({{i18n .Lang "message.system_error"}},"#form-error-message2");
|
||||
$("#btnDeleteBlog").button("reset");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>文章设置 - Powered by MinDoc</title>
|
||||
<title>{{i18n .Lang "blog.blog_setting"}} - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
|
@ -25,14 +25,14 @@
|
|||
<div class="row">
|
||||
<div class="page-left">
|
||||
<ul class="menu">
|
||||
<li {{if eq .ControllerName "BookController"}}class="active"{{end}}><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 我的项目</a> </li>
|
||||
<li {{if eq .ControllerName "BlogController"}}class="active"{{end}}><a href="{{urlfor "BlogController.ManageList"}}" class="item"><i class="fa fa-file" aria-hidden="true"></i> 我的文章</a> </li>
|
||||
<li {{if eq .ControllerName "BookController"}}class="active"{{end}}><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> {{i18n .Lang "common.my_project"}}</a> </li>
|
||||
<li {{if eq .ControllerName "BlogController"}}class="active"{{end}}><a href="{{urlfor "BlogController.ManageList"}}" class="item"><i class="fa fa-file" aria-hidden="true"></i> {{i18n .Lang "common.my_blog"}}</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="page-right">
|
||||
<div class="m-box">
|
||||
<div class="box-head">
|
||||
<strong class="box-title"> 文章设置</strong>
|
||||
<strong class="box-title"> {{i18n .Lang "blog.blog_setting"}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
|
@ -42,58 +42,58 @@
|
|||
<input type="hidden" name="document_id" value="{{.Model.DocumentId}}">
|
||||
<input type="hidden" name="order_index" value="{{.Model.OrderIndex}}">
|
||||
<div class="form-group">
|
||||
<label>文章标题</label>
|
||||
<input type="text" class="form-control" name="title" id="title" placeholder="文章标题" value="{{.Model.BlogTitle}}">
|
||||
<label>{{i18n .Lang "blog.title"}}</label>
|
||||
<input type="text" class="form-control" name="title" id="title" placeholder="{{i18n .Lang "blog.title"}}" value="{{.Model.BlogTitle}}">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label>文章类型</label>
|
||||
<label>{{i18n .Lang "blog.type"}}</label>
|
||||
<div class="radio">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" {{if eq .Model.BlogType 0}}checked{{end}} name="blog_type" value="0">普通文章<span class="text"></span>
|
||||
<input type="radio" {{if eq .Model.BlogType 0}}checked{{end}} name="blog_type" value="0">{{i18n .Lang "blog.normal_blog"}}<span class="text"></span>
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" {{if eq .Model.BlogType 1}}checked{{end}} name="blog_type" value="1">链接文章<span class="text"></span>
|
||||
<input type="radio" {{if eq .Model.BlogType 1}}checked{{end}} name="blog_type" value="1">{{i18n .Lang "blog.link_blog"}}<span class="text"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="blogLinkDocument"{{if ne .Model.BlogType 1}} style="display: none;" {{end}}>
|
||||
<label>关联文档</label>
|
||||
<label>{{i18n .Lang "blog.ref_doc"}}</label>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" placeholder="请输入项目标识" name="bookIdentify" value="{{.Model.BookIdentify}}">
|
||||
<input type="text" class="form-control" placeholder="{{i18n .Lang "message.input_proj_id_pls"}}" name="bookIdentify" value="{{.Model.BookIdentify}}">
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" placeholder="请输入文档标识" name="documentIdentify" value="{{.Model.DocumentIdentify}}">
|
||||
<input type="text" class="form-control" placeholder="{{i18n .Lang "message.input_doc_id_pls"}}" name="documentIdentify" value="{{.Model.DocumentIdentify}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>文章状态</label>
|
||||
<label>{{i18n .Lang "blog.blog_status"}}</label>
|
||||
<div class="radio">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" {{if eq .Model.BlogStatus "public"}}checked{{end}} name="status" value="public">公开<span class="text"></span>
|
||||
<input type="radio" {{if eq .Model.BlogStatus "public"}}checked{{end}} name="status" value="public">{{i18n .Lang "blog.public"}}<span class="text"></span>
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" {{if eq .Model.BlogStatus "password"}}checked{{end}} name="status" value="password">加密<span class="text"></span>
|
||||
<input type="radio" {{if eq .Model.BlogStatus "password"}}checked{{end}} name="status" value="password">{{i18n .Lang "blog.encryption"}}<span class="text"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"{{if eq .Model.BlogStatus "public"}} style="display: none;"{{end}} id="blogPassword">
|
||||
<label>文章密码</label>
|
||||
<input type="password" class="form-control" name="password" id="password" placeholder="文章密码" value="{{.Model.Password}}" maxlength="20">
|
||||
<label>{{i18n .Lang "blog.blog_pwd"}}</label>
|
||||
<input type="password" class="form-control" name="password" id="password" placeholder="{{i18n .Lang "blog.blog_pwd"}}" value="{{.Model.Password}}" maxlength="20">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>文章摘要</label>
|
||||
<textarea rows="3" class="form-control" name="excerpt" style="height: 90px" placeholder="项目描述">{{.Model.BlogExcerpt}}</textarea>
|
||||
<p class="text">文章摘要不超过500个字符</p>
|
||||
<label>{{i18n .Lang "blog.blog_digest"}}</label>
|
||||
<textarea rows="3" class="form-control" name="excerpt" style="height: 90px" placeholder="{{i18n .Lang "blog.blog_digest"}}">{{.Model.BlogExcerpt}}</textarea>
|
||||
<p class="text">{{i18n .Lang "message.blog_digest_tips"}}</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" id="btnSaveBlogInfo" class="btn btn-success" data-loading-text="保存中...">保存</button>
|
||||
<a href="{{.Referer}}" title="返回" class="btn btn-info">返回</a>
|
||||
<button type="submit" id="btnSaveBlogInfo" class="btn btn-success" data-loading-text="{{i18n .Lang "message.processing"}}">{{i18n .Lang "common.save"}}</button>
|
||||
<a href="{{.Referer}}" title="{{i18n .Lang "doc.backward"}}" class="btn btn-info">{{i18n .Lang "doc.backward"}}</a>
|
||||
<span id="form-error-message" class="error-message"></span>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -119,19 +119,19 @@
|
|||
var title = $.trim($("#title").val());
|
||||
|
||||
if (title === ""){
|
||||
return showError("文章标题不能为空");
|
||||
return showError("{{i18n .Lang "message.blog_title_empty"}}");
|
||||
}
|
||||
$("#btnSaveBlogInfo").button("loading");
|
||||
},success : function ($res) {
|
||||
if($res.errcode === 0) {
|
||||
showSuccess("保存成功");
|
||||
showSuccess("{{i18n .Lang "message.success"}}");
|
||||
$("#blogId").val($res.data.blog_id);
|
||||
}else{
|
||||
showError($res.message);
|
||||
}
|
||||
$("#btnSaveBlogInfo").button("reset");
|
||||
}, error : function () {
|
||||
showError("服务器异常.");
|
||||
showError("{{i18n .Lang "message.system_error"}}");
|
||||
$("#btnSaveBlogInfo").button("reset");
|
||||
}
|
||||
}).find("input[name='status']").change(function () {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>概要 - Powered by MinDoc</title>
|
||||
<title>{{i18n $.Lang "blog.summary"}} - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||
|
@ -26,11 +26,11 @@
|
|||
<div class="row">
|
||||
<div class="page-left">
|
||||
<ul class="menu">
|
||||
<li class="active"><a href="{{urlfor "BookController.Dashboard" ":key" .Model.Identify}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
|
||||
<li class="active"><a href="{{urlfor "BookController.Dashboard" ":key" .Model.Identify}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> {{i18n $.Lang "blog.summary"}}</a> </li>
|
||||
{{if eq .Model.RoleId 0 1}}
|
||||
<li><a href="{{urlfor "BookController.Users" ":key" .Model.Identify}}" class="item"><i class="fa fa-user" aria-hidden="true"></i> 成员</a> </li>
|
||||
<li><a href="{{urlfor "BookController.Team" ":key" .Model.Identify}}" class="item"><i class="fa fa-group" aria-hidden="true"></i> 团队</a> </li>
|
||||
<li><a href="{{urlfor "BookController.Setting" ":key" .Model.Identify}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
|
||||
<li><a href="{{urlfor "BookController.Users" ":key" .Model.Identify}}" class="item"><i class="fa fa-user" aria-hidden="true"></i> {{i18n $.Lang "blog.member"}}</a> </li>
|
||||
<li><a href="{{urlfor "BookController.Team" ":key" .Model.Identify}}" class="item"><i class="fa fa-group" aria-hidden="true"></i> {{i18n $.Lang "blog.team"}}</a> </li>
|
||||
<li><a href="{{urlfor "BookController.Setting" ":key" .Model.Identify}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> {{i18n $.Lang "common.setting"}}</a> </li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
|
@ -40,19 +40,19 @@
|
|||
<div class="box-head">
|
||||
<strong class="box-title">
|
||||
{{if eq .Model.PrivatelyOwned 0}}
|
||||
<i class="fa fa-unlock" aria-hidden="true" title="公开项目" data-toggle="tooltip"></i>
|
||||
<i class="fa fa-unlock" aria-hidden="true" title="{{i18n $.Lang "blog.public_project"}}" data-toggle="tooltip"></i>
|
||||
{{else}}
|
||||
<i class="fa fa-lock" aria-hidden="true" title="私有项目" data-toggle="tooltip"></i>
|
||||
<i class="fa fa-lock" aria-hidden="true" title="{{i18n $.Lang "blog.private_project"}}" data-toggle="tooltip"></i>
|
||||
{{end}}
|
||||
{{.Model.BookName}}
|
||||
</strong>
|
||||
{{if ne .Model.RoleId 3}}
|
||||
<a href="{{urlfor "DocumentController.Edit" ":key" .Model.Identify ":id" ""}}" class="btn btn-default btn-sm pull-right" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑</a>
|
||||
<a href="{{urlfor "DocumentController.Edit" ":key" .Model.Identify ":id" ""}}" class="btn btn-default btn-sm pull-right" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> {{i18n $.Lang "blog.edit"}}</a>
|
||||
{{end}}
|
||||
<a href="{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" target="_blank"><i class="fa fa-eye"></i> 阅读</a>
|
||||
<a href="{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" target="_blank"><i class="fa fa-eye"></i> {{i18n $.Lang "blog.read"}}</a>
|
||||
|
||||
{{if eq .Model.RoleId 0 1 2}}
|
||||
<button class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" id="btnRelease"><i class="fa fa-upload" aria-hidden="true"></i> 发布</button>
|
||||
<button class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" id="btnRelease"><i class="fa fa-upload" aria-hidden="true"></i> {{i18n $.Lang "blog.publish"}}</button>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,32 +65,32 @@
|
|||
</div>
|
||||
|
||||
<div class="list">
|
||||
<span class="title">创建者:</span>
|
||||
<span class="title">{{i18n $.Lang "blog.creator"}}:</span>
|
||||
<span class="body">{{.Model.CreateName}}</span>
|
||||
</div>
|
||||
<div class="list">
|
||||
<span class="title">文档数量:</span>
|
||||
<span class="body">{{.Model.DocCount}} 篇</span>
|
||||
<span class="title">{{i18n $.Lang "blog.doc_amount"}}:</span>
|
||||
<span class="body">{{.Model.DocCount}} {{i18n $.Lang "blog.doc_unit"}}</span>
|
||||
</div>
|
||||
<div class="list">
|
||||
<span class="title">创建时间:</span>
|
||||
<span class="title">{{i18n $.Lang "blog.create_time"}}:</span>
|
||||
<span class="body"> {{date_format .Model.CreateTime "2006-01-02 15:04:05"}} </span>
|
||||
</div>
|
||||
<div class="list">
|
||||
<span class="title">修改时间:</span>
|
||||
<span class="title">{{i18n $.Lang "blog.update_time"}}:</span>
|
||||
<span class="body"> {{date_format .Model.CreateTime "2006-01-02 15:04:05"}} </span>
|
||||
</div>
|
||||
<div class="list">
|
||||
<span class="title">担任角色:</span>
|
||||
<span class="title">{{i18n $.Lang "blog.project_role"}}:</span>
|
||||
<span class="body">{{.Model.RoleName}}</span>
|
||||
</div>
|
||||
<!-- {{/* <div class="list">
|
||||
<span class="title">评论数量:</span>
|
||||
<span class="body">{{.Model.CommentCount}} 条</span>
|
||||
<span class="title">{{i18n $.Lang "blog.comment_amount"}}:</span>
|
||||
<span class="body">{{.Model.CommentCount}} {{i18n $.Lang "blog.comment_unit"}}</span>
|
||||
</div>*/}}
|
||||
-->
|
||||
<div class="list">
|
||||
<span class="title">文档标签:</span>
|
||||
<span class="title">{{i18n $.Lang "blog.project_desc"}}:</span>
|
||||
<span class="body">{{.Model.Label}}</span>
|
||||
</div>
|
||||
<div class="summary">{{.Description}} </div>
|
||||
|
@ -116,7 +116,7 @@
|
|||
dataType : "json",
|
||||
success : function (res) {
|
||||
if(res.errcode === 0){
|
||||
layer.msg("发布任务已推送到任务队列,稍后将在后台执行。");
|
||||
layer.msg("{{i18n $.Lang "message.publish_to_queue"}}");
|
||||
}else{
|
||||
layer.msg(res.message);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>我的项目 - Powered by MinDoc</title>
|
||||
<title>{{i18n $.Lang "common.my_project"}} - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
|
||||
|
@ -28,30 +28,30 @@
|
|||
<div class="row">
|
||||
<div class="page-left">
|
||||
<ul class="menu">
|
||||
<li {{if eq .ControllerName "BookController"}}class="active"{{end}}><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 我的项目</a> </li>
|
||||
<li {{if eq .ControllerName "BlogController"}}class="active"{{end}}><a href="{{urlfor "BlogController.ManageList"}}" class="item"><i class="fa fa-file" aria-hidden="true"></i> 我的文章</a> </li>
|
||||
<li {{if eq .ControllerName "BookController"}}class="active"{{end}}><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> {{i18n $.Lang "common.my_project"}}</a> </li>
|
||||
<li {{if eq .ControllerName "BlogController"}}class="active"{{end}}><a href="{{urlfor "BlogController.ManageList"}}" class="item"><i class="fa fa-file" aria-hidden="true"></i> {{i18n $.Lang "common.my_blog"}}</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="page-right">
|
||||
<div class="m-box">
|
||||
<div class="box-head">
|
||||
<strong class="box-title">项目列表</strong>
|
||||
<strong class="box-title">{{i18n $.Lang "blog.project_list"}}</strong>
|
||||
|
||||
<button type="button" data-toggle="modal" data-target="#addBookDialogModal" class="btn btn-success btn-sm pull-right">添加项目</button>
|
||||
<button type="button" data-toggle="modal" data-target="#importBookDialogModal" class="btn btn-primary btn-sm pull-right" style="margin-right: 5px;">导入项目</button>
|
||||
<button type="button" data-toggle="modal" data-target="#addBookDialogModal" class="btn btn-success btn-sm pull-right">{{i18n $.Lang "blog.add_project"}}</button>
|
||||
<button type="button" data-toggle="modal" data-target="#importBookDialogModal" class="btn btn-primary btn-sm pull-right" style="margin-right: 5px;">{{i18n $.Lang "blog.import_project"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body" id="bookList">
|
||||
<div class="book-list">
|
||||
<template v-if="lists.length <= 0">
|
||||
<div class="text-center">暂无数据</div>
|
||||
<div class="text-center">{{i18n $.Lang "message.no_data"}}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
||||
<div class="list-item" v-for="item in lists">
|
||||
<div class="book-title">
|
||||
<div class="pull-left">
|
||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="项目概要" data-toggle="tooltip">
|
||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="{{i18n $.Lang "blog.project_summary"}}" data-toggle="tooltip">
|
||||
<template v-if="item.privately_owned == 0">
|
||||
<i class="fa fa-unlock" aria-hidden="true"></i>
|
||||
</template>
|
||||
|
@ -63,28 +63,28 @@
|
|||
</div>
|
||||
<div class="pull-right">
|
||||
<div class="btn-group">
|
||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" class="btn btn-default">设置</a>
|
||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" class="btn btn-default">{{i18n $.Lang "common.setting"}}</a>
|
||||
|
||||
<a href="javascript:;" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" target="_blank">阅读</a></li>
|
||||
<li><a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" target="_blank">{{i18n $.Lang "blog.read"}}</a></li>
|
||||
<template v-if="item.role_id != 3">
|
||||
<li><a :href="'{{.BaseUrl}}/api/' + item.identify + '/edit'" target="_blank">编辑</a></li>
|
||||
<li><a :href="'{{.BaseUrl}}/api/' + item.identify + '/edit'" target="_blank">{{i18n $.Lang "blog.edit"}}</a></li>
|
||||
</template>
|
||||
<template v-if="item.role_id == 0">
|
||||
<li><a :href="'javascript:deleteBook(\''+item.identify+'\');'">删除</a></li>
|
||||
<li><a :href="'javascript:copyBook(\''+item.identify+'\');'">复制</a></li>
|
||||
<li><a :href="'javascript:deleteBook(\''+item.identify+'\');'">{{i18n $.Lang "blog.delete"}}</a></li>
|
||||
<li><a :href="'javascript:copyBook(\''+item.identify+'\');'">{{i18n $.Lang "blog.copy"}}</a></li>
|
||||
</template>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
{{/*<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="查看文档" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> 查看文档</a>*/}}
|
||||
{{/*<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="{{i18n $.Lang "blog.view"}}" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> {{i18n $.Lang "blog.view"}}</a>*/}}
|
||||
{{/*<template v-if="item.role_id != 3">*/}}
|
||||
{{/*<a :href="'/api/' + item.identify + '/edit'" title="编辑文档" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a>*/}}
|
||||
{{/*<a :href="'/api/' + item.identify + '/edit'" title="{{i18n $.Lang "blog.edit_doc"}}" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> {{i18n $.Lang "blog.edit_doc"}}</a>*/}}
|
||||
{{/*</template>*/}}
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -94,21 +94,21 @@
|
|||
|
||||
</template>
|
||||
<template v-else="">
|
||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="项目概要" style="font-size: 12px;">
|
||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="{{i18n $.Lang "blog.project_summary"}}" style="font-size: 12px;">
|
||||
${item.description}
|
||||
</a>
|
||||
</template>
|
||||
</div>
|
||||
<div class="info">
|
||||
<span title="创建时间" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-clock-o"></i>
|
||||
<span title="{{i18n $.Lang "blog.create_time"}}" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-clock-o"></i>
|
||||
${(new Date(item.create_time)).format("yyyy-MM-dd hh:mm:ss")}
|
||||
|
||||
</span>
|
||||
<span title="创建者" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user"></i> ${item.create_name}</span>
|
||||
<span title="文档数量" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pie-chart"></i> ${item.doc_count}</span>
|
||||
<span title="项目角色" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user-secret"></i> ${item.role_name}</span>
|
||||
<span title="{{i18n $.Lang "blog.creator"}}" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user"></i> ${item.create_name}</span>
|
||||
<span title="{{i18n $.Lang "blog.doc_amount"}}" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pie-chart"></i> ${item.doc_count}</span>
|
||||
<span title="{{i18n $.Lang "blog.project_role"}}" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user-secret"></i> ${item.role_name}</span>
|
||||
<template v-if="item.last_modify_text !== ''">
|
||||
<span title="最后编辑" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> 最后编辑: ${item.last_modify_text}</span>
|
||||
<span title="{{i18n $.Lang "blog.last_edit"}}" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> {{i18n $.Lang "blog.last_edit"}}: ${item.last_modify_text}</span>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
|
@ -133,49 +133,49 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="myModalLabel">添加项目</h4>
|
||||
<h4 class="modal-title" id="myModalLabel">{{i18n $.Lang "blog.add_project"}}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<div class="pull-left" style="width: 620px">
|
||||
<div class="form-group required">
|
||||
<label class="text-label col-sm-2">项目空间</label>
|
||||
<label class="text-label col-sm-2">{{i18n $.Lang "common.project_space"}}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="js-data-example-ajax-add form-control" multiple="multiple" name="itemId" id="itemId">
|
||||
{{if .Item}}<option value="{{.Item.ItemId}}" selected>{{.Item.ItemName}}</option> {{end}}
|
||||
</select>
|
||||
<p class="text">每个项目必须归属一个项目空间,超级管理员可在后台管理和维护</p>
|
||||
<p class="text">{{i18n $.Lang "message.project_must_belong_space"}}</p>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label class="text-label col-sm-2">项目标题</label>
|
||||
<label class="text-label col-sm-2">{{i18n $.Lang "blog.project_title"}}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" placeholder="标题(不超过100字)" name="book_name" id="bookName">
|
||||
<p class="text">项目名称不能超过100字符</p>
|
||||
<input type="text" class="form-control" placeholder="{{i18n $.Lang "message.project_title_placeholder"}}" name="book_name" id="bookName">
|
||||
<p class="text">{{i18n $.Lang "message.project_title_tips"}}</p>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label class="text-label col-sm-2">项目标识</label>
|
||||
<label class="text-label col-sm-2">{{i18n $.Lang "blog.project_id"}}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" placeholder="项目唯一标识(不超过50字)" name="identify" id="identify">
|
||||
<p class="text">文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号.</p>
|
||||
<input type="text" class="form-control" placeholder="{{i18n $.Lang "message.project_id_placeholder"}}" name="identify" id="identify">
|
||||
<p class="text">{{i18n $.Lang "message.project_id_tips"}}</p>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<textarea name="description" id="description" class="form-control" placeholder="描述信息不超过500个字符" style="height: 90px;"></textarea>
|
||||
<textarea name="description" id="description" class="form-control" placeholder="{{i18n $.Lang "message.project_desc_placeholder"}}" style="height: 90px;"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-6">
|
||||
<div class="col-lg-4">
|
||||
<label>
|
||||
<input type="radio" name="privately_owned" value="0" checked> 公开<span class="text">(任何人都可以访问)</span>
|
||||
<input type="radio" name="privately_owned" value="0" checked> {{i18n $.Lang "blog.public"}}<span class="text">{{i18n $.Lang "message.project_public_desc"}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="col-lg-8">
|
||||
<label>
|
||||
<input type="radio" name="privately_owned" value="1"> 私有<span class="text">(只要参与者或使用令牌才能访问)</span>
|
||||
<input type="radio" name="privately_owned" value="1"> {{i18n $.Lang "blog.private"}}<span class="text">{{i18n $.Lang "message.project_private_desc"}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -183,7 +183,7 @@
|
|||
</div>
|
||||
<div class="pull-right text-center" style="width: 235px;">
|
||||
<canvas id="bookCover" height="230px" width="170px"><img src="{{cdnimg "/static/images/book.jpg"}}"> </canvas>
|
||||
<p class="text">项目图片可在项目设置中修改</p>
|
||||
<p class="text">{{i18n $.Lang "message.project_cover_desc"}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -192,8 +192,8 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<span id="form-error-message"></span>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-success" id="btnSaveDocument" data-loading-text="保存中...">保存</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n $.Lang "common.cancel"}}</button>
|
||||
<button type="button" class="btn btn-success" id="btnSaveDocument" data-loading-text="{{i18n $.Lang "common.processing"}}">{{i18n $.Lang "common.save"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -207,48 +207,48 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">导入项目</h4>
|
||||
<h4 class="modal-title">{{i18n $.Lang "blog.import_project"}}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<div class="form-group required">
|
||||
<label class="text-label">项目空间</label>
|
||||
<label class="text-label">{{i18n $.Lang "common.project_space"}}</label>
|
||||
<select class="js-data-example-ajax-import form-control" multiple="multiple" name="itemId">
|
||||
{{if .Item}}<option value="{{.Item.ItemId}}" selected>{{.Item.ItemName}}</option> {{end}}
|
||||
</select>
|
||||
<p class="text">每个项目必须归属一个项目空间,超级管理员可在后台管理和维护</p>
|
||||
<p class="text">{{i18n $.Lang "message.project_must_belong_space"}}</p>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label class="text-label">项目标题</label>
|
||||
<input type="text" class="form-control" placeholder="项目标题(不超过100字)" name="book_name" maxlength="100" value="">
|
||||
<p class="text">项目名称不能超过100字符</p>
|
||||
<label class="text-label">{{i18n $.Lang "blog.project_title"}}</label>
|
||||
<input type="text" class="form-control" placeholder="{{i18n $.Lang "message.project_title_placeholder"}}" name="book_name" maxlength="100" value="">
|
||||
<p class="text">{{i18n $.Lang "blog.project_title_tips"}}</p>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label class="text-label">项目标识</label>
|
||||
<input type="text" class="form-control" placeholder="项目唯一标识(不超过50字)" name="identify" value="">
|
||||
<label class="text-label">{{i18n $.Lang "blog.project_id"}}</label>
|
||||
<input type="text" class="form-control" placeholder="{{i18n $.Lang "message.project_id_placeholder"}}" name="identify" value="">
|
||||
<div class="clearfix"></div>
|
||||
<p class="text">文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号.</p>
|
||||
<p class="text">{{i18n $.Lang "blog.project_id_tips"}}</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="text-label">项目描述</label>
|
||||
<textarea name="description" id="description" class="form-control" placeholder="描述信息不超过500个字符" style="height: 90px;"></textarea>
|
||||
<label class="text-label">{{i18n $.Lang "blog.project_desc"}}</label>
|
||||
<textarea name="description" id="description" class="form-control" placeholder="{{i18n $.Lang "message.project_desc_placeholder"}}" style="height: 90px;"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-6">
|
||||
<div class="col-lg-4">
|
||||
<label>
|
||||
<input type="radio" name="privately_owned" value="0" checked> 公开<span class="text">(任何人都可以访问)</span>
|
||||
<input type="radio" name="privately_owned" value="0" checked> {{i18n $.Lang "blog.public"}}<span class="text">{{i18n $.Lang "message.project_public_desc"}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="col-lg-8">
|
||||
<label>
|
||||
<input type="radio" name="privately_owned" value="1"> 私有<span class="text">(只要参与者或使用令牌才能访问)</span>
|
||||
<input type="radio" name="privately_owned" value="1"> {{i18n $.Lang "blog.private"}}<span class="text">{{i18n $.Lang "message.project_private_desc"}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="file-loading">
|
||||
<input id="import-book-upload" name="import-file" type="file" accept=".zip">
|
||||
<input id="import-book-upload" name="import-file" type="file" accept=".zip,.docx">
|
||||
</div>
|
||||
<div id="kartik-file-errors"></div>
|
||||
</div>
|
||||
|
@ -257,8 +257,8 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<span id="import-book-form-error-message" style="background-color: #ffffff;border: none;margin: 0;padding: 0;"></span>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-success" id="btnImportBook" data-loading-text="创建中...">创建</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n $.Lang "common.cancel"}}</button>
|
||||
<button type="button" class="btn btn-success" id="btnImportBook" data-loading-text="{{i18n $.Lang "common.processing"}}">{{i18n $.Lang "common.create"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -273,17 +273,17 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">删除项目</h4>
|
||||
<h4 class="modal-title">{{i18n $.Lang "blog.delete_project"}}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<span style="font-size: 14px;font-weight: 400;">确定删除项目吗?</span>
|
||||
<span style="font-size: 14px;font-weight: 400;">{{i18n $.Lang "message.confirm_delete_project"}}</span>
|
||||
<p></p>
|
||||
<p class="text error-message">删除项目后将无法找回。</p>
|
||||
<p class="text error-message">{{i18n $.Lang "message.warning_delete_project"}}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<span id="form-error-message2" class="error-message"></span>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||
<button type="submit" id="btnDeleteBook" class="btn btn-primary" data-loading-text="删除中...">确定删除</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n $.Lang "common.cancel"}}</button>
|
||||
<button type="submit" id="btnDeleteBook" class="btn btn-primary" data-loading-text="{{i18n $.Lang "common.processing"}}">{{i18n $.Lang "common.confirm_delete"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -415,7 +415,7 @@
|
|||
},
|
||||
error : function () {
|
||||
layer.close(index);
|
||||
layer.msg('服务器异常');
|
||||
layer.msg('{{i18n $.Lang "message.system_error"}}');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -426,9 +426,9 @@
|
|||
* */
|
||||
$("#addBookDialogModal").on("show.bs.modal",function () {
|
||||
window.bookDialogModal = $(this).find("#addBookDialogForm").html();
|
||||
drawBookCover("bookCover","默认封面");
|
||||
drawBookCover("bookCover","{{i18n $.Lang "blog.default_cover"}}");
|
||||
$('.js-data-example-ajax-add').select2({
|
||||
language: "zh-CN",
|
||||
language: "{{i18n $.Lang "common.js_lang"}}",
|
||||
minimumInputLength : 1,
|
||||
minimumResultsForSearch: Infinity,
|
||||
maximumSelectionLength:1,
|
||||
|
@ -464,9 +464,9 @@
|
|||
'showUpload' : false,
|
||||
'required': true,
|
||||
'validateInitialCount': true,
|
||||
"language" : "zh",
|
||||
'allowedFileExtensions': ['zip'],
|
||||
'msgPlaceholder' : '请选择Zip文件',
|
||||
"language" : "{{i18n $.Lang "common.upload_lang"}}",
|
||||
'allowedFileExtensions': ['zip', 'docx'],
|
||||
'msgPlaceholder' : '{{i18n $.Lang "message.file_type_placeholder"}}',
|
||||
'elErrorContainer' : "#import-book-form-error-message",
|
||||
'uploadExtraData' : function () {
|
||||
var book = {};
|
||||
|
@ -480,7 +480,7 @@
|
|||
}
|
||||
});
|
||||
$('.js-data-example-ajax-import').select2({
|
||||
language: "zh-CN",
|
||||
language: "{{i18n $.Lang "common.js_lang"}}",
|
||||
minimumInputLength : 1,
|
||||
minimumResultsForSearch: Infinity,
|
||||
maximumSelectionLength:1,
|
||||
|
@ -513,27 +513,27 @@
|
|||
|
||||
var itemId = $("#itemId").val();
|
||||
if (itemId <= 0) {
|
||||
return showError("请选择项目空间")
|
||||
return showError("{{i18n $.Lang "message.project_space_empty"}}")
|
||||
}
|
||||
var bookName = $.trim($("#bookName").val());
|
||||
if (bookName === "") {
|
||||
return showError("项目标题不能为空")
|
||||
return showError("{{i18n $.Lang "message.project_title_empty"}}")
|
||||
}
|
||||
if (bookName.length > 100) {
|
||||
return showError("项目标题必须小于100字符");
|
||||
return showError("{{i18n $.Lang "message.project_title_tips"}}");
|
||||
}
|
||||
|
||||
var identify = $.trim($("#identify").val());
|
||||
if (identify === "") {
|
||||
return showError("项目标识不能为空");
|
||||
return showError("{{i18n $.Lang "message.project_id_empty"}}");
|
||||
}
|
||||
if (identify.length > 50) {
|
||||
return showError("项目标识必须小于50字符");
|
||||
return showError("{{i18n $.Lang "message.project_id_length"}}");
|
||||
}
|
||||
var description = $.trim($("#description").val());
|
||||
|
||||
if (description.length > 500) {
|
||||
return showError("描述信息不超过500个字符");
|
||||
return showError("{{i18n $.Lang "message.project_desc_placeholder"}}");
|
||||
}
|
||||
|
||||
$this.button("loading");
|
||||
|
@ -567,7 +567,7 @@
|
|||
$this.button("reset");
|
||||
}).error(function () {
|
||||
$this.button("reset");
|
||||
return showError("服务器异常");
|
||||
return showError("{{i18n $.Lang "message.system_error"}}");
|
||||
});
|
||||
return false;
|
||||
}).on("blur","#bookName",function () {
|
||||
|
@ -581,30 +581,30 @@
|
|||
|
||||
var itemId = $then.find("input[name='itemId']").val();
|
||||
if (itemId <= 0) {
|
||||
return showError("请选择项目空间")
|
||||
return showError("{{i18n $.Lang "message.project_space_empty"}}")
|
||||
}
|
||||
|
||||
var bookName = $.trim($then.find("input[name='book_name']").val());
|
||||
|
||||
if (bookName === "") {
|
||||
return showError("项目标题不能为空","#import-book-form-error-message");
|
||||
return showError("{{i18n $.Lang "message.project_title_empty"}}","#import-book-form-error-message");
|
||||
}
|
||||
if (bookName.length > 100) {
|
||||
return showError("项目标题必须小于100字符","#import-book-form-error-message");
|
||||
return showError("{{i18n $.Lang "message.project_title_tips"}}","#import-book-form-error-message");
|
||||
}
|
||||
|
||||
var identify = $.trim($then.find("input[name='identify']").val());
|
||||
if (identify === "") {
|
||||
return showError("项目标识不能为空","#import-book-form-error-message");
|
||||
return showError("{{i18n $.Lang "message.project_id_empty"}}","#import-book-form-error-message");
|
||||
}
|
||||
var description = $.trim($then.find('textarea[name="description"]').val());
|
||||
if (description.length > 500) {
|
||||
return showError("描述信息不超过500个字符","#import-book-form-error-message");
|
||||
return showError("{{i18n $.Lang "message.project_decs_placeholder"}}","#import-book-form-error-message");
|
||||
}
|
||||
var filesCount = $('#import-book-upload').fileinput('getFilesCount');
|
||||
|
||||
if (filesCount <= 0) {
|
||||
return showError("请选择需要上传的文件","#import-book-form-error-message");
|
||||
return showError("{{i18n $.Lang "message.import_file_empty"}}","#import-book-form-error-message");
|
||||
}
|
||||
//$("#importBookDialogForm").submit();
|
||||
$("#btnImportBook").button("loading");
|
||||
|
@ -636,7 +636,7 @@
|
|||
$("#btnDeleteBook").button("reset");
|
||||
},
|
||||
error : function () {
|
||||
showError("服务器异常","#form-error-message2");
|
||||
showError("{{i18n $.Lang "message.system_error"}}","#form-error-message2");
|
||||
$("#btnDeleteBook").button("reset");
|
||||
}
|
||||
});
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue