upload.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>Word模板替换</title>
  7. <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  8. <style>
  9. /* 全局样式 */
  10. body {
  11. font-family: Arial, sans-serif;
  12. max-width: 800px;
  13. margin: 0 auto;
  14. padding: 20px;
  15. background-color: #f5f5f5;
  16. }
  17. .container {
  18. background-color: white;
  19. padding: 20px;
  20. border-radius: 8px;
  21. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  22. }
  23. h1 {
  24. color: #333;
  25. text-align: center;
  26. }
  27. /* 表单样式 */
  28. .form {
  29. margin-top: 20px;
  30. }
  31. .form-group {
  32. margin-bottom: 15px;
  33. }
  34. label {
  35. display: block;
  36. margin-bottom: 5px;
  37. font-weight: bold;
  38. }
  39. .text-input {
  40. width: 100%;
  41. padding: 8px 10px;
  42. border: 1px solid #ddd;
  43. border-radius: 4px;
  44. box-sizing: border-box;
  45. }
  46. textarea.text-input {
  47. resize: vertical;
  48. min-height: 60px;
  49. font-family: Arial, sans-serif;
  50. }
  51. /* 按钮样式 */
  52. .btn {
  53. background-color: #4caf50;
  54. color: white;
  55. padding: 12px 20px;
  56. border: none;
  57. border-radius: 4px;
  58. cursor: pointer;
  59. font-size: 16px;
  60. display: block;
  61. width: 100%;
  62. margin-top: 20px;
  63. }
  64. .btn:hover {
  65. background-color: #45a049;
  66. }
  67. .btn:disabled {
  68. background-color: #cccccc;
  69. cursor: not-allowed;
  70. }
  71. /* 状态消息样式 */
  72. .status {
  73. margin-top: 20px;
  74. padding: 15px;
  75. border-radius: 4px;
  76. display: none;
  77. }
  78. .success {
  79. background-color: #dff0d8;
  80. color: #3c763d;
  81. border: 1px solid #d6e9c6;
  82. }
  83. .error {
  84. background-color: #f2dede;
  85. color: #a94442;
  86. border: 1px solid #ebccd1;
  87. }
  88. /* 下载链接样式 */
  89. .download-link {
  90. display: inline-block;
  91. margin-top: 15px;
  92. padding: 8px 15px;
  93. background-color: #337ab7;
  94. color: white;
  95. text-decoration: none;
  96. border-radius: 4px;
  97. }
  98. .download-link:hover {
  99. background-color: #286090;
  100. }
  101. /* 字段操作样式 */
  102. .field-actions {
  103. margin-top: 20px;
  104. text-align: center;
  105. }
  106. .add-field-btn {
  107. background-color: #5bc0de;
  108. color: white;
  109. padding: 8px 15px;
  110. border: none;
  111. border-radius: 4px;
  112. cursor: pointer;
  113. margin-right: 10px;
  114. }
  115. .add-field-btn:hover {
  116. background-color: #46b8da;
  117. }
  118. .field-row {
  119. display: flex;
  120. margin-bottom: 10px;
  121. align-items: flex-start;
  122. }
  123. .field-key {
  124. flex: 1;
  125. margin-right: 10px;
  126. }
  127. .field-value {
  128. flex: 2;
  129. margin-right: 10px;
  130. }
  131. .field-label {
  132. width: 100px;
  133. text-align: left;
  134. color: #666;
  135. font-size: 14px;
  136. }
  137. .remove-field-btn {
  138. background-color: #d9534f;
  139. color: white;
  140. border: none;
  141. border-radius: 4px;
  142. cursor: pointer;
  143. padding: 5px 10px;
  144. }
  145. .remove-field-btn:hover {
  146. background-color: #c9302c;
  147. }
  148. </style>
  149. </head>
  150. <body>
  151. <div class="container">
  152. <h1>Word模板替换系统</h1>
  153. <div class="form">
  154. <h3>输入模板变量</h3>
  155. <p>系统将使用固定模板,根据下方输入的字段自动替换模板中的变量。</p>
  156. <p>
  157. 请填写以下字段,系统将自动替换模板中对应的变量(如{name}、{address}等)。
  158. </p>
  159. <div id="fieldsContainer">
  160. <!-- 动态字段将在这里添加 -->
  161. <div class="field-row">
  162. <input
  163. type="text"
  164. class="text-input field-key"
  165. placeholder="字段名"
  166. value="person1"
  167. readonly
  168. />
  169. <input
  170. type="text"
  171. class="text-input field-value"
  172. placeholder="甲方"
  173. value="杭州遁地科技"
  174. />
  175. <span class="field-label">甲方</span>
  176. <button
  177. class="remove-field-btn"
  178. onclick="removeField(this)"
  179. style="visibility: hidden"
  180. >
  181. 删除
  182. </button>
  183. </div>
  184. <div class="field-row">
  185. <input
  186. type="text"
  187. class="text-input field-key"
  188. placeholder="字段名"
  189. value="person2"
  190. readonly
  191. />
  192. <input
  193. type="text"
  194. class="text-input field-value"
  195. placeholder="乙方"
  196. value="杭州飞天科技"
  197. />
  198. <span class="field-label">乙方</span>
  199. <button
  200. class="remove-field-btn"
  201. onclick="removeField(this)"
  202. style="visibility: hidden"
  203. >
  204. 删除
  205. </button>
  206. </div>
  207. <div class="field-row">
  208. <input
  209. type="text"
  210. class="text-input field-key"
  211. placeholder="字段名"
  212. value="name"
  213. readonly
  214. />
  215. <input
  216. type="text"
  217. class="text-input field-value"
  218. placeholder="货物名称"
  219. />
  220. <span class="field-label">货物名称</span>
  221. <button
  222. class="remove-field-btn"
  223. onclick="removeField(this)"
  224. style="visibility: hidden"
  225. >
  226. 删除
  227. </button>
  228. </div>
  229. <div class="field-row">
  230. <input
  231. type="text"
  232. class="text-input field-key"
  233. placeholder="字段名"
  234. value="address"
  235. readonly
  236. />
  237. <input
  238. type="text"
  239. class="text-input field-value"
  240. placeholder="请输入原产地"
  241. />
  242. <span class="field-label">原产地</span>
  243. <button
  244. class="remove-field-btn"
  245. onclick="removeField(this)"
  246. style="visibility: hidden"
  247. >
  248. 删除
  249. </button>
  250. </div>
  251. <div class="field-row">
  252. <input
  253. type="text"
  254. class="text-input field-key"
  255. placeholder="字段名"
  256. value="address1"
  257. readonly
  258. />
  259. <input
  260. type="text"
  261. class="text-input field-value"
  262. placeholder="请输入目的地口岸"
  263. />
  264. <span class="field-label">目的地口岸</span>
  265. <button
  266. class="remove-field-btn"
  267. onclick="removeField(this)"
  268. style="visibility: hidden"
  269. >
  270. 删除
  271. </button>
  272. </div>
  273. <div class="field-row">
  274. <input
  275. type="text"
  276. class="text-input field-key"
  277. placeholder="字段名"
  278. value="addType"
  279. readonly
  280. />
  281. <input
  282. type="text"
  283. class="text-input field-value"
  284. placeholder="请输入交货方式"
  285. />
  286. <span class="field-label">交货方式</span>
  287. <button
  288. class="remove-field-btn"
  289. onclick="removeField(this)"
  290. style="visibility: hidden"
  291. >
  292. 删除
  293. </button>
  294. </div>
  295. <div class="field-row" style="height: 300px">
  296. <input
  297. type="text"
  298. class="text-input field-key"
  299. placeholder="字段名"
  300. value="productGuide"
  301. readonly
  302. />
  303. <textarea
  304. class="text-input field-value"
  305. placeholder="请输入产品规格"
  306. rows="15"
  307. >
  308. 我是一瓶番茄酱+沙拉酱
  309. 我是一瓶番茄酱+沙拉酱
  310. 我是一瓶番茄酱+沙拉酱
  311. 我是一瓶番茄酱+沙拉酱
  312. 我是一瓶番茄酱+沙拉酱
  313. 我是一瓶番茄酱+沙拉酱
  314. 我是一瓶番茄酱+沙拉酱
  315. 我是一瓶番茄酱+沙拉酱
  316. 我是一瓶番茄酱+沙拉酱
  317. 我是一瓶番茄酱+沙拉酱
  318. 我是一瓶番茄酱+沙拉酱
  319. 我是一瓶番茄酱+沙拉酱
  320. 我是一瓶番茄酱+沙拉酱
  321. 我是一瓶番茄酱+沙拉酱
  322. 我是一瓶番茄酱+沙拉酱
  323. </textarea
  324. >
  325. <span class="field-label">产品规格</span>
  326. <button
  327. class="remove-field-btn"
  328. onclick="removeField(this)"
  329. style="visibility: hidden"
  330. >
  331. 删除
  332. </button>
  333. </div>
  334. </div>
  335. <div class="field-actions">
  336. <!-- 移除添加字段按钮 -->
  337. </div>
  338. <button id="generateBtn" class="btn">生成文档</button>
  339. </div>
  340. <!-- 状态消息区域 -->
  341. <div id="statusMessage" class="status"></div>
  342. <!-- 下载区域 -->
  343. <div id="downloadSection" style="display: none; margin-top: 20px">
  344. <p>文档已成功生成,点击下面的链接下载:</p>
  345. <a id="downloadLink" href="#" class="download-link" download
  346. >下载文档</a
  347. >
  348. </div>
  349. </div>
  350. <script>
  351. // DOM元素引用
  352. const generateBtn = document.getElementById("generateBtn");
  353. const statusMessage = document.getElementById("statusMessage");
  354. const downloadSection = document.getElementById("downloadSection");
  355. const downloadLink = document.getElementById("downloadLink");
  356. const fieldsContainer = document.getElementById("fieldsContainer");
  357. // 获取当前页面的主机名和端口,用于API请求
  358. const apiBaseUrl = `${window.location.protocol}//${window.location.hostname}:5000`;
  359. // 收集所有字段
  360. function collectFields() {
  361. const data = {};
  362. const fieldRows = fieldsContainer.querySelectorAll(".field-row");
  363. fieldRows.forEach((row) => {
  364. const key = row.querySelector(".field-key").value.trim();
  365. const value = row.querySelector(".field-value").value.trim();
  366. if (key) {
  367. data[key] = value;
  368. }
  369. });
  370. return data;
  371. }
  372. // 生成文档
  373. generateBtn.addEventListener("click", function (e) {
  374. e.preventDefault();
  375. // 收集字段数据
  376. const data = collectFields();
  377. // 更新UI状态为处理中
  378. generateBtn.disabled = true;
  379. generateBtn.textContent = "处理中...";
  380. statusMessage.className = "status";
  381. statusMessage.style.display = "none";
  382. // 发送请求到Flask后端
  383. axios
  384. .post(`${apiBaseUrl}/process_file`, data, {
  385. headers: {
  386. "Content-Type": "application/json",
  387. },
  388. })
  389. .then((response) => {
  390. // 处理成功响应
  391. statusMessage.className = "status success";
  392. statusMessage.style.display = "block";
  393. statusMessage.textContent = `成功: ${response.data.message}`;
  394. console.log("成功:", response.data);
  395. // 更新下载链接
  396. downloadLink.href = `${apiBaseUrl}/download/${response.data.output_filename}`;
  397. // 显示下载部分
  398. downloadSection.style.display = "block";
  399. })
  400. .catch((error) => {
  401. // 处理错误响应
  402. statusMessage.className = "status error";
  403. statusMessage.style.display = "block";
  404. if (error.response) {
  405. statusMessage.textContent = `错误: ${
  406. error.response.data.error || "处理失败"
  407. }`;
  408. } else {
  409. statusMessage.textContent = "错误: 服务器连接失败";
  410. }
  411. console.error("处理错误:", error);
  412. })
  413. .finally(() => {
  414. // 恢复按钮状态
  415. generateBtn.disabled = false;
  416. generateBtn.textContent = "生成文档";
  417. });
  418. });
  419. </script>
  420. </body>
  421. </html>