diff --git a/build.bat b/build.bat
index 7fd3febe9f43817ff5a76776abc60e2b7d1357d7..2f7d9715456d2eeeac7c157866063c14e4fef329 100755
--- a/build.bat
+++ b/build.bat
@@ -4,7 +4,7 @@ set dist_dir=dist
set app_name=torna
-set version="1.14.5"
+set version="1.15.0"
set build_folder=%app_name%-%version%
diff --git a/build.sh b/build.sh
index 1e424b71e325cbb61707e907cee4a8313a8601df..2c482a8196a1f09f128a1815631466cae766711d 100644
--- a/build.sh
+++ b/build.sh
@@ -6,7 +6,7 @@ dist_dir="dist"
# 执行文件名称
app_name="torna"
-version="1.14.5"
+version="1.15.0"
build_folder="${app_name}-${version}"
diff --git a/changelog.md b/changelog.md
index 53ed17b0ab6de29caa9f0efcd57cdde67cf5b15f..28e77b4d9a8b09b74597f6a9bf5969fa1e53bd1d 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,16 @@
# 更新日志
+## 1.15.0
+
+- 【新增】新增分享配置时可选调试环境 [pr](https://gitee.com/durcframework/torna/pulls/28)
+- 【新增】接口文档编辑和查看描述以及备注的地方使用富文本编辑器 [pr](https://gitee.com/durcframework/torna/pulls/32)
+- 【新增】调试页面新增自定义修改请求类型或者参数 [#I545M6](https://gitee.com/durcframework/torna/issues/I545M6)
+- 【优化】推送失败打印具体文档信息
+- 【优化】代理调试新增对https的支持 [pr](https://gitee.com/durcframework/torna/pulls/30)
+- 【修复】postman上传get请求类型失败 [pr](https://gitee.com/durcframework/torna/pulls/31)
+- 【修复】编辑文档响应参数的时候敲回车会报错 [#I57TQ3](https://gitee.com/durcframework/torna/issues/I57TQ3)
+- 【修复】用户为空间成员,非项目成员;浏览模式下访问公开项目显示以上异常 [#I57UMS](https://gitee.com/durcframework/torna/issues/I57UMS)
+
## 1.14.5
- 【修复】修复导出和query参数展示bug
diff --git a/front/src/components/DocExportDialog/index.vue b/front/src/components/DocExportDialog/index.vue
index 3e3867781688cc3e3b7546d464ce8f0f2099f70c..0e22c02ed97285b87a2b69316fce6f4ab9ea3482 100644
--- a/front/src/components/DocExportDialog/index.vue
+++ b/front/src/components/DocExportDialog/index.vue
@@ -23,6 +23,7 @@
html
markdown
+ word
@@ -52,7 +53,8 @@ const EXPORT_STYLE = {
}
const EXPORT_TYPE = {
HTML: 'html',
- MARKDOWN: 'md'
+ MARKDOWN: 'md',
+ WORD: 'word'
}
export default {
components: { DocTree },
@@ -113,6 +115,13 @@ export default {
ExportUtil.exportMarkdownMultiPages(docInfoList)
}
break
+ case EXPORT_TYPE.WORD:
+ if (style === EXPORT_STYLE.ALL_IN_ONE) {
+ ExportUtil.exportWordAllInOne(docInfoList)
+ } else {
+ ExportUtil.exportWordMultiPages(docInfoList)
+ }
+ break
default:
}
}
diff --git a/front/src/utils/convert-word.js b/front/src/utils/convert-word.js
new file mode 100644
index 0000000000000000000000000000000000000000..17646dc9923413f8c1504ddf71cc4d0f8945e5ca
--- /dev/null
+++ b/front/src/utils/convert-word.js
@@ -0,0 +1,213 @@
+import {
+ convert_tree,
+ create_response_example,
+ get_effective_url,
+ get_style_config, init_docInfo,
+ StringBuilder
+} from '@/utils/common'
+import { isDubbo, isHttp, isShowRequestExample } from '@/utils/convert-common'
+import { Enums } from '@/utils/enums'
+
+export const word_wrapper = `
+
+
+
+
+
+
+ Print
+ {body}`
+
+const WordUtil = {
+ toWordByData(docInfoList, title) {
+ // title = title || $ts('document')
+ const treeData = convert_tree(docInfoList, '')
+ const content = new StringBuilder()
+ const appendHtml = (doc_info) => {
+ init_docInfo(doc_info)
+ content.append(WordUtil.toWord(doc_info))
+ }
+ treeData.forEach(docInfo => {
+ const children = docInfo.children
+ if (children && children.length > 0) {
+ // 一级标题
+ content.append(`${docInfo.name}
`)
+ children.forEach(child => {
+ appendHtml(child)
+ })
+ } else {
+ appendHtml(docInfo)
+ }
+ })
+ return content.toString()
+ },
+ toWord(docInfo) {
+ const sb = new StringBuilder()
+ sb.append(`${docInfo.name}
`)
+ const appendCode = (str) => {
+ sb.append('')
+ sb.append(`\n\n${str}\n
\n`)
+ sb.append('
')
+ }
+ // 维护人
+ docInfo.author && sb.append(`${$ts('maintainer')}:${docInfo.author}
`)
+ // URL
+ if (isHttp(docInfo)) {
+ sb.append(`URL
`)
+ const debugEnvs = docInfo.debugEnvs || []
+ if (debugEnvs.length > 0) {
+ const ul = new StringBuilder('')
+ docInfo.debugEnvs.forEach(hostConfig => {
+ const baseUrl = hostConfig.url
+ const url = get_effective_url(baseUrl, docInfo.url)
+ ul.append(`- ${hostConfig.name}: ${docInfo.httpMethod} ${url}
`)
+ })
+ ul.append('
')
+ sb.append(ul.toString())
+ } else {
+ sb.append(`${docInfo.httpMethod} ${docInfo.url}`)
+ }
+ } else if (isDubbo(docInfo)) {
+ sb.append(`${$ts('method')}:${docInfo.url}
`)
+ }
+ // 描述
+ sb.append(`${$ts('description')}:${docInfo.description}
`)
+
+ isHttp(docInfo) && sb.append(`ContentType:${docInfo.contentType}
`)
+
+ if (isHttp(docInfo)) {
+ if (docInfo.pathParams && docInfo.pathParams.length > 0) {
+ sb.append(`${$ts('pathVariable')}
`)
+ sb.append(createTable(docInfo.pathParams, Enums.PARAM_STYLE.path))
+ }
+ if (docInfo.headerParams && docInfo.headerParams.length > 0) {
+ sb.append(`${$ts('requestHeader')}
`)
+ sb.append(createTable(docInfo.headerParams, Enums.PARAM_STYLE.header))
+ }
+ }
+ sb.append(`${$ts('requestParams')}
`)
+ if (docInfo.queryParams && docInfo.queryParams.length > 0) {
+ sb.append('Query Parameter
')
+ sb.append(createTable(docInfo.queryParams, Enums.PARAM_STYLE.request))
+ }
+ if (docInfo.requestParams && docInfo.requestParams.length > 0) {
+ sb.append('Body Parameter
')
+ sb.append(createTable(docInfo.requestParams, Enums.PARAM_STYLE.request))
+ }
+ if (isShowRequestExample(docInfo)) {
+ sb.append(`${$ts('requestExample')}
`)
+ const requestExample = create_response_example(docInfo.requestParams)
+ appendCode(JSON.stringify(requestExample, null, 4))
+ }
+ sb.append(`${$ts('responseParam')}
`)
+ sb.append(createTable(docInfo.responseParams, Enums.PARAM_STYLE.response))
+
+ if (isHttp(docInfo)) {
+ sb.append(`${$ts('responseExample')}
`)
+ const responseExample = create_response_example(docInfo.responseParams)
+ appendCode(JSON.stringify(responseExample, null, 4))
+ }
+
+ sb.append(`${$ts('errorCode')}
`)
+ sb.append(createTable(docInfo.errorCodeParams, Enums.PARAM_STYLE.code))
+ return sb.toString()
+ }
+}
+
+function createTable(params, style) {
+ if (!params || params.length === 0) {
+ return $ts('empty')
+ }
+ const rowConfig = get_style_config()[style + '']
+ if (!rowConfig) {
+ return ''
+ }
+ const headers = rowConfig.map(config => config.label)
+ const headerContent = `\n${createHeader(headers)}`
+ const trContent = `\n${createBody(params, rowConfig)}`
+ const tableContent = [
+ '\n',
+ headerContent,
+ trContent,
+ '\n
'
+ ]
+ return tableContent.join('')
+}
+
+function createHeader(tds) {
+ const thHtml = []
+ tds.forEach(content => {
+ thHtml.push(thWrapper(content))
+ })
+ return `\n${thHtml.join('')}\n
`
+}
+
+const thWrapper = (content) => {
+ return `${content} | \n`
+}
+
+function createBody(params, rowConfig, prefix = '', level = 1) {
+ let rows = []
+ for (const param of params) {
+ const tds = []
+ for (const config of rowConfig) {
+ let value = param[config.prop]
+ if (config.prop === 'required') {
+ value = value ? $ts('yes') : $ts('no')
+ }
+ tds.push(value)
+ }
+ rows.push(createBodyTr(tds, prefix, level))
+ if (param.children && param.children.length > 0) {
+ const childrenRows = createBody(param.children, rowConfig, '└ ', level + 1)
+ rows = rows.concat(childrenRows)
+ }
+ }
+ return rows.join('\n')
+}
+
+function createBodyTr(tds, prefix, level) {
+ if (level > 1) {
+ const padding = []
+ console.log('level:', level)
+ console.log('cishu :', Math.pow(level, 2))
+ for (let i = 1; i < level; i++) {
+ padding.push(' ')
+ }
+ prefix = padding.join('') + prefix
+ }
+ const tdHtml = []
+ tds.forEach((content, index) => {
+ if (index === 0) {
+ content = prefix + content
+ }
+ tdHtml.push(tdWrapper(content))
+ })
+ return `\n${tdHtml.join('')}\n
`
+}
+
+const tdWrapper = (content) => {
+ return `${content} | \n`
+}
+export default WordUtil
diff --git a/front/src/utils/export.js b/front/src/utils/export.js
index 45ab92ed73d1fa8c47c128ca5ff5a95c532dfca6..6596a78704c732d4c85651e957a1565b09724b4a 100644
--- a/front/src/utils/export.js
+++ b/front/src/utils/export.js
@@ -1,6 +1,7 @@
import JSZip from 'jszip'
import HtmlUtil from '@/utils/convert-html'
import MarkdownUtil from '@/utils/convert-markdown'
+import WordUtil, { word_wrapper } from '@/utils/convert-word'
import { convert_tree, download_text, format_string, init_docInfo } from '@/utils/common'
import { saveAs } from 'file-saver'
@@ -141,6 +142,21 @@ const ExportUtil = {
})
})
},
+ /**
+ * 导出一个页面为word
+ * @param docInfo
+ */
+ exportWordSinglePage(docInfo) {
+ export_single_page(docInfo, docInfo => {
+ return `${docInfo.name}-${new Date().getTime()}.doc`
+ }, docInfo => {
+ const content = WordUtil.toWord(docInfo)
+ return format_string(word_wrapper, {
+ title: docInfo.name,
+ body: content
+ })
+ })
+ },
/**
* 导出全部markdown为单页
* @param docInfoList docInfoList
@@ -158,6 +174,32 @@ const ExportUtil = {
return `${docInfo.name}.md`
}, MarkdownUtil.toMarkdown)
},
+ /**
+ * 导出全部 word 为单页
+ * @param docInfoList docInfoList
+ */
+ exportWordAllInOne(docInfoList) {
+ const content = WordUtil.toWordByData(docInfoList)
+ const html = format_string(word_wrapper, {
+ body: content
+ })
+ download_text(`export-${new Date().getTime()}.doc`, html)
+ },
+ /**
+ * 导出全部 word 为多页
+ * @param docInfoList docInfoList
+ */
+ exportWordMultiPages(docInfoList) {
+ do_export_multi_docs(docInfoList, docInfo => {
+ return `${docInfo.name}.doc`
+ }, docInfo => {
+ const content = WordUtil.toWord(docInfo)
+ return format_string(word_wrapper, {
+ title: docInfo.name,
+ body: content
+ })
+ })
+ },
/**
* 导出全部Html为单页
* @param docInfoList docInfoList
diff --git a/front/src/utils/global.js b/front/src/utils/global.js
index d71eb254d151690216ef1e88af2594b75f661580..ef752252455996c7cf8d7b00b093f673405413bd 100644
--- a/front/src/utils/global.js
+++ b/front/src/utils/global.js
@@ -18,7 +18,7 @@ import { Enums } from './enums'
import { add_init } from './init'
// eslint-disable-next-line
-const VERSION="1.14.5"
+const VERSION="1.15.0"
const SPACE_ID_KEY = 'torna.spaceid'
const PROJECT_ID_KEY = 'torna.projectid'
const TORNA_FROM = 'torna.from'
diff --git a/front/src/utils/i18n/languages/en-us.js b/front/src/utils/i18n/languages/en-us.js
index 7b6e4a86f3ad0ca69364a2bef57a84d3442dfbc1..dec3c33ef20b184c7661bf51277ae8f89acd17b0 100644
--- a/front/src/utils/i18n/languages/en-us.js
+++ b/front/src/utils/i18n/languages/en-us.js
@@ -288,6 +288,7 @@ const MAPPING = {
'clickSubscribe': 'Click Subscribe',
'exportMarkdown': 'As markdown',
'exportHtml': 'As html',
+ 'exportWord': 'As word',
'createdOn': 'Created on',
'lastModifiedBy': 'last modified on',
'noHeader': 'No header',
diff --git a/front/src/utils/i18n/languages/zh-cn.js b/front/src/utils/i18n/languages/zh-cn.js
index 1d23c6bdc3e149d95f180d79bde81b54353973bc..4d5e90c782f0898318eecb0787ad0cb157282957 100644
--- a/front/src/utils/i18n/languages/zh-cn.js
+++ b/front/src/utils/i18n/languages/zh-cn.js
@@ -289,6 +289,7 @@ const MAPPING = {
'clickSubscribe': '点击关注',
'exportMarkdown': '导出markdown',
'exportHtml': '导出html',
+ 'exportWord': '导出word',
'createdOn': '创建于',
'lastModifiedBy': '最后修改于',
'noHeader': '无Header',
diff --git a/front/src/views/doc/DocView/index.vue b/front/src/views/doc/DocView/index.vue
index 3fb1b04a99073623a458fb866687854651ed289c..67c73f196e9826a1314fe60a83bd40b32bd9f551 100644
--- a/front/src/views/doc/DocView/index.vue
+++ b/front/src/views/doc/DocView/index.vue
@@ -20,6 +20,7 @@
{{ $ts('exportMarkdown') }}
{{ $ts('exportHtml') }}
+ {{ $ts('exportWord') }}
@@ -330,6 +331,9 @@ export default {
onExportHtml() {
ExportUtil.exportHtmlSinglePage(this.docInfo)
},
+ onExportWord() {
+ ExportUtil.exportWordSinglePage(this.docInfo)
+ },
onSubscribe() {
if (!this.isSubscribe) {
this.post('/user/subscribe/doc/subscribe', { sourceId: this.docInfo.id }, resp => {
diff --git a/front/src/views/doc/DubboView/index.vue b/front/src/views/doc/DubboView/index.vue
index 60914fa3384cea2a8f00c2c2f21f340a435b315c..bfb8c4ca0d2ab8b8594ac24c787ec4b11ee9ca95 100644
--- a/front/src/views/doc/DubboView/index.vue
+++ b/front/src/views/doc/DubboView/index.vue
@@ -19,6 +19,7 @@
{{ $ts('exportMarkdown') }}
{{ $ts('exportHtml') }}
+ {{ $ts('exportWord') }}
@@ -178,6 +179,9 @@ export default {
onExportHtml() {
ExportUtil.exportHtmlSinglePage(this.docInfo)
},
+ onExportWord() {
+ ExportUtil.exportWordSinglePage(this.docInfo)
+ },
onSubscribe() {
if (!this.isSubscribe) {
this.post('/user/subscribe/doc/subscribe', { sourceId: this.docInfo.id }, resp => {
diff --git a/pom.xml b/pom.xml
index 8d29df9b4efd164170dfbe92cd0d3e4fe987a2f0..6287f884bb6f87a77a749edbba79a3abed1be17f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
- 1.14.5
+ 1.15.0
1.8
diff --git a/release.sh b/release.sh
index b8d5019f3d354d7b731ccad242b91e0063558221..fd2e6ff1cb7373b0e39de85adaaeb1ffac70d568 100644
--- a/release.sh
+++ b/release.sh
@@ -6,7 +6,7 @@ dist_dir="dist"
# 执行文件名称
app_name="torna"
-version="1.14.5"
+version="1.15.0"
build_folder="${app_name}-${version}"