js+html点击按钮实现word文档下载,自定义文档格式【附全部代码】

时间:2025-03-28 09:08:22
function handleWordExport() { // 正在下载word文件中,请稍后... showMessage('正在下载word文件中,请稍后...'); this.download('接口文档', data) } function showMessage(text) { const messageBox = document.querySelector('.message-box'); messageBox.classList.add('active'); messageBox.innerHTML = `<p>${text}</p>`; setTimeout(() => { messageBox.classList.remove('active'); }, 3000); // 3秒后自动关闭提示框 } /** * 文档处理(World) * Created by xiangshaolin on 2022/12/14. */ /** * 生成Word文档 * @param content * @return {string} */ function createWord(content) { let wordContent = [] createWordHeader(wordContent) createApiInfo(content, wordContent) createWordFooter(wordContent) return wordContent.join('\n') } /** * 生成Word文档 * @param content * @return {string} */ function createWordHeader(wordContent) { let wordHeader = `<!DOCTYPE HTML PUBLIC "-// W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> <style type="text/css"> .doc-body { width: 90%; margin: 20px auto; font-family:"宋体"; font-size: 16px; } .doc-row { position: relative; height: auto; margin-right: 0; margin-left: 0; zoom: 1; display: block; box-sizing: border-box; } .doc-line { height: 35px; line-height:35px; } .doc-divider { height: 1px; background: #e8e8e8; border-bottom: 1px solid #e8e8e8; } .doc-title { font-weight: 600; font-size: 18px; margin-top: 15px; border-left: 3px solid #00ab6d; } .doc-api { margin-top: 10px; margin-bottom: 20px; } .doc-content { margin-top: 10px; max-height: 30px; } .doc-code-editor { border: #ccc 1px solid; border-left-width: 4px; background-color: #fefefe; box-shadow: 0 0 4px #eee; word-break: break-all; word-wrap: break-word; color: #444; } .doc-code-editor .string { color: green; } /*字符串的样式*/ .doc-code-editor .number { color: darkorange; } /*数字的样式*/ .doc-code-editor .boolean { color: blue; } /*布尔型数据的样式*/ .doc-code-editor .null { color: magenta; } /*null值的样式*/ .doc-code-editor .key { color: red; } /*key值的样式*/ .doc-method { font-size: 14px; font-weight: 600; margin-right: 10px; text-align: center; border-radius: 3px; text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); } .doc-table { width: 120%; border: 1px solid #c7c4c4; border-collapse: collapse; } .doc-table tr { border: 1px solid #c7c4c4; height: 40px; } .doc-table th { border: 1px solid #c7c4c4; background-color: #dfdada; } .doc-table td { border: 1px solid #c7c4c4; } </style> </head> <body> <div class="doc-body">` wordContent.push(wordHeader) } /** * 生成Word结尾 * @param content * @return {string} */ function createWordFooter(wordContent) { wordContent.push('</div></body></html>') } /** * 遍历tags分组信息 * @param {*} instance 当前分组实例对象 * @param {*} wordContent markdown文本集合对象 */ function createApiInfo(apiContent, wordContent) { if (apiContent !== undefined && apiContent != null) { wordContent.push('\n') wordContent.push('<h1>1.接口列表</h1>') if(Array.isArray(apiContent) && apiContent.length) { apiContent.forEach((api, index) => { // let docIndex = parseInt(index) + 1 // let docParent = '2.' + docIndex // let tagTitle = docParent + // ('<h2>' + tagTitle + '</h2>'); wordLines(wordContent) createWordApiInfo(api, wordContent) }) } } } /** * 主动换行 * @param {*} wordContent */ function wordLines(wordContent) { wordContent.push('\n') } /** * 遍历接口详情 * @param {*} apiInfo 接口实例 * @param {*} wordContent markdown文本集合对象 */ function createWordApiInfo(apiInfo, wordContent) { // 二级标题 wordLines(wordContent) wordContent.push('<div class="doc-api">') wordContent.push('<div class="doc-title">接口名称</div>') wordContent.push('<div class="doc-content">' + apiInfo.name + '</div>'); wordContent.push('<div class="doc-title">接口地址</div>') wordContent.push('<div class="doc-content"><span class="doc-method">' + 'POST' + '</span>&nbsp;&nbsp;<code>' + apiInfo.url + '</code></div>'); wordContent.push('<div class="doc-title">接口描述</div>') wordContent.push('<div class="doc-content">' + apiInfo.remark + '</div>') // ('<div class="doc-title">请求数据类型</div>') // ('<div class="doc-content"><code>' + apiInfo + '</code></div>') // // ('<div class="doc-title">响应数据类型</div>') // ('<div class="doc-content"><code>' + apiInfo + '</code></div>') // 请求参数 if(apiInfo.model) { createWordApiRequestParameters(apiInfo, wordContent) } wordContent.push('</div>'); } /** * 请求参数 * @param {*} apiInfo * @param {*} wordContent */ function createWordApiRequestParameters(apiInfo, wordContent) { let reqParameters = apiInfo.model.fields wordLines(wordContent) wordContent.push('<div class="doc-title">请求参数</div><br/>') wordContent.push('<div class="doc-content">') wordContent.push('<table class="doc-table">') // 表头 wordContent.push('<thead><tr><th>参数名称</th><th>参数说明</th><th>请求类型</th><th>必须</th><th>数据类型</th><th>schema</th></tr></thead>') wordContent.push('<tbody>') // 判断是否拥有请求参数 if (reqParameters.length > 0) { // if ( > 0) { // 级联表格,在表格需要最佳空格缩进符号 createParameterTable(reqParameters, wordContent, 1) } else { // 无参数 wordContent.push('<tr><td colspan="6">暂无</td></tr>') } wordContent.push('</tbody>') wordContent.push('</table>') wordContent.push('</div>') } /** * 递归循环遍历参数得到markdown表格 * @param {*} parameters * @param {*} wordContent */ function createParameterTable(parameters, wordContent) { if (parameters != null && parameters != undefined && parameters.length > 0) { parameters.forEach((param, index) => { wordContent.push('<tr>') wordContent.push('<td>' + param.name + '</td>') wordContent.push('<td>' + param.label + '</td>') wordContent.push('<td>' + '</td>') wordContent.push('<td>' + '</td>') // ('<td>' + + '</td>') wordContent.push('<td>' + param.clazz + '</td>') wordContent.push('<td>' + '</td>') wordContent.push('</tr>') }) } } /** * 下载Word文档 * @param fileName * @param content */ function download(fileName, content) { content = createWord(content) let a = document.createElement('a') const url = window.URL.createObjectURL( new Blob([content], { type: 'application/msword;charset=utf-8' }) ) a.href = url a.download = fileName a.click() window.URL.revokeObjectURL(url) } var data = [ { "interfaceId": "blockStockBox", "interfaceName": "冻结或解冻箱库存", "interfaceType": "relative", "url": "/3c/box/blockStockBox", "option": "{\"recordFlag\":true,\"limitFlag\":false,\"limitRate\":5,\"headers\":[]}", "example": "", "flowId": "blockOrUnBlockStockBoxes", "status": 1, "persist": 0, "remark": "", "createTime": "2024-05-10 21:16:10", "createUser": "", "updateTime": null, "updateUser": null, "flowName": null, "tags": null, "realUrl": "/api/flow/3c/box/blockStockBox", "absolute": false }, { "interfaceId": "getIntoTraceDetail", "interfaceName": "按跟踪号获取箱入库单信息", "interfaceType": "relative", "url": "/3c/getIntoTraceDetail", "option": "{\"recordFlag\":true,\"limitFlag\":false,\"limitRate\":5,\"headers\":[]}", "example": "", "flowId": "getIntoTraceDetail", "status": 1, "persist": 0, "remark": "", "createTime": "2024-04-28 16:40:20", "createUser": "", "updateTime": null, "updateUser": null, "flowName": null, "tags": null, "realUrl": "/api/flow/3c/getIntoTraceDetail", "absolute": false } ]