text_to_image.html 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>生成模板 - 文生图</title>
  8. <!-- 引入Font Awesome图标 -->
  9. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  10. <!-- 引入自定义CSS -->
  11. <link rel="shortcut icon" href="__CDN__/assets/img/favicon.ico"/>
  12. <style>
  13. /* 自定义提示框样式 */
  14. .custom-alert {
  15. position: fixed;
  16. top: 10%;
  17. left: 50%;
  18. transform: translate(-50%, -50%);
  19. padding: 15px 25px;
  20. border-radius: 8px;
  21. color: white;
  22. font-size: 14px;
  23. font-weight: 500;
  24. z-index: 10000;
  25. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  26. opacity: 0;
  27. visibility: hidden;
  28. transition: all 0.3s ease;
  29. max-width: 80%;
  30. text-align: center;
  31. }
  32. .custom-alert.show {
  33. opacity: 1;
  34. visibility: visible;
  35. }
  36. .custom-alert.error {
  37. background-color: #e74c3c;
  38. }
  39. .custom-alert.success {
  40. background-color: #28a745;
  41. }
  42. .custom-alert.warning {
  43. background-color: #ffc107;
  44. color: #333;
  45. }
  46. .custom-alert.info {
  47. background-color: #17a2b8;
  48. }
  49. * {
  50. margin: 0;
  51. padding: 0;
  52. box-sizing: border-box;
  53. }
  54. /* 标题样式 */
  55. .page-title {
  56. font-size: 24px;
  57. font-weight: bold;
  58. margin-bottom: 25px;
  59. color: #333;
  60. }
  61. /* 内容区域 */
  62. .content-area {
  63. display: grid;
  64. grid-template-columns: 1fr 1fr;
  65. gap: 30px;
  66. }
  67. /* 左侧输入区域 */
  68. .input-section {
  69. background-color: #fff;
  70. border-radius: 8px;
  71. padding: 20px;
  72. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
  73. }
  74. /* 右侧预览区域 */
  75. .preview-section {
  76. background-color: #fff;
  77. border-radius: 8px;
  78. padding: 20px;
  79. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
  80. }
  81. /* 表单组样式 */
  82. .form-group {
  83. margin-bottom: 20px;
  84. }
  85. .form-group label {
  86. display: block;
  87. font-size: 14px;
  88. font-weight: bold;
  89. color: #333;
  90. margin-bottom: 8px;
  91. }
  92. /* 文本输入区域 */
  93. .prompt-textarea {
  94. width: 100%;
  95. height: 150px;
  96. padding: 12px;
  97. border: 1px solid #ddd;
  98. border-radius: 8px;
  99. resize: vertical;
  100. font-size: 14px;
  101. line-height: 1.5;
  102. }
  103. /* 参数设置区域 */
  104. .params-grid {
  105. display: grid;
  106. grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  107. gap: 15px;
  108. }
  109. .param-item {
  110. margin-bottom: 15px;
  111. }
  112. .param-item label {
  113. display: block;
  114. font-size: 13px;
  115. font-weight: bold;
  116. color: #333;
  117. margin-bottom: 5px;
  118. }
  119. .param-item select, .param-item input[type="number"] {
  120. width: 100%;
  121. padding: 8px 12px;
  122. border: 1px solid #ddd;
  123. border-radius: 4px;
  124. font-size: 14px;
  125. }
  126. /* 提示词示例 */
  127. .prompt-examples {
  128. background-color: #f8f9fa;
  129. border-radius: 8px;
  130. padding: 15px;
  131. margin-bottom: 20px;
  132. }
  133. .prompt-examples h4 {
  134. font-size: 14px;
  135. font-weight: bold;
  136. margin-bottom: 10px;
  137. color: #333;
  138. }
  139. .example-list {
  140. display: flex;
  141. flex-wrap: wrap;
  142. gap: 8px;
  143. }
  144. .example-tag {
  145. font-size: 12px;
  146. background-color: #e9ecef;
  147. color: #666;
  148. padding: 4px 10px;
  149. border-radius: 4px;
  150. cursor: pointer;
  151. transition: background-color 0.2s;
  152. }
  153. .example-tag:hover {
  154. background-color: #dee2e6;
  155. }
  156. /* 按钮样式 */
  157. .button-group {
  158. display: flex;
  159. gap: 10px;
  160. }
  161. .btn {
  162. padding: 12px 24px;
  163. border: none;
  164. border-radius: 8px;
  165. font-size: 14px;
  166. cursor: pointer;
  167. transition: background-color 0.2s;
  168. }
  169. .btn-primary {
  170. background-color: #007bff;
  171. color: #fff;
  172. }
  173. .btn-primary:hover {
  174. background-color: #0056b3;
  175. }
  176. .btn-secondary {
  177. background-color: #6c757d;
  178. color: #fff;
  179. }
  180. .btn-secondary:hover {
  181. background-color: #545b62;
  182. }
  183. /* 预览区域 */
  184. .preview-container {
  185. width: 100%;
  186. min-height: 300px;
  187. background-color: #f8f9fa;
  188. border-radius: 8px;
  189. display: flex;
  190. align-items: center;
  191. justify-content: center;
  192. margin-bottom: 20px;
  193. overflow: hidden;
  194. }
  195. .preview-image {
  196. max-width: 100%;
  197. max-height: 100%;
  198. object-fit: contain;
  199. }
  200. .preview-placeholder {
  201. font-size: 14px;
  202. color: #666;
  203. text-align: center;
  204. }
  205. /* 模板信息 */
  206. .template-info {
  207. margin-bottom: 20px;
  208. }
  209. .template-info h4 {
  210. font-size: 14px;
  211. font-weight: bold;
  212. margin-bottom: 10px;
  213. color: #333;
  214. }
  215. .template-form input {
  216. width: 100%;
  217. padding: 10px 12px;
  218. border: 1px solid #ddd;
  219. border-radius: 8px;
  220. font-size: 14px;
  221. margin-bottom: 10px;
  222. }
  223. /* 响应式设计 */
  224. @media (max-width: 768px) {
  225. .content-area {
  226. grid-template-columns: 1fr;
  227. }
  228. .clear-btn, .optimize-btn, .arrow-btn {
  229. flex: 1;
  230. }
  231. }
  232. .optimize-btn {
  233. background-color: #ffffff;
  234. color: #4b5563;
  235. padding: 10px 18px;
  236. border: 1px solid #d1d5db;
  237. border-radius: 8px;
  238. font-size: 14px;
  239. font-weight: 500;
  240. cursor: pointer;
  241. transition: all 0.3s ease;
  242. display: flex;
  243. align-items: center;
  244. gap: 6px;
  245. }
  246. .optimize-btn:hover {
  247. background-color: #f9fafb;
  248. border-color: #9ca3af;
  249. transform: translateY(-1px);
  250. }
  251. .clear-btn {
  252. background-color: #ffffff;
  253. color: #dc3545;
  254. border: 1px solid #f87171;
  255. border-radius: 8px;
  256. font-size: 14px;
  257. font-weight: 500;
  258. cursor: pointer;
  259. transition: all 0.3s ease;
  260. display: flex;
  261. align-items: center;
  262. gap: 6px;
  263. }
  264. .clear-btn:hover {
  265. background-color: #fee2e2;
  266. border-color: #ef4444;
  267. transform: translateY(-1px);
  268. }
  269. /* 操作按钮 */
  270. .prompt-actions {
  271. gap: 8px;
  272. }
  273. .clear-btn, .optimize-btn {
  274. padding: 8px 12px;
  275. font-size: 13px;
  276. }
  277. /* 菜单样式 */
  278. .menu-container {
  279. background-color: #f5f7fa;
  280. border-radius: 8px;
  281. padding: 10px;
  282. margin-bottom: 20px;
  283. display: flex;
  284. gap: 10px;
  285. }
  286. .menu-item {
  287. flex: 1;
  288. }
  289. .menu-item a {
  290. display: block;
  291. padding: 12px;
  292. background-color: white;
  293. border: 1px solid #e1e8ed;
  294. border-radius: 6px;
  295. text-align: center;
  296. text-decoration: none;
  297. color: #657786;
  298. font-size: 14px;
  299. font-weight: 500;
  300. transition: all 0.3s ease;
  301. }
  302. .menu-item a:hover {
  303. background-color: #e8f0fe;
  304. border-color: #1da1f2;
  305. color: #1da1f2;
  306. }
  307. .menu-item.active a {
  308. background-color: #1da1f2;
  309. border-color: #1da1f2;
  310. color: white;
  311. }
  312. .menu-item i {
  313. margin-right: 6px;
  314. font-size: 16px;
  315. }
  316. </style>
  317. </head>
  318. <body>
  319. <div class="container">
  320. <!-- 菜单功能区 -->
  321. <div class="menu-container">
  322. <div class="menu-item active">
  323. <a href="{:url('user/index')}">
  324. <i class="fas fa-image"></i>
  325. 文生图
  326. </a>
  327. </div>
  328. <div class="menu-item">
  329. <a href="{:url('user/text_to_video')}">
  330. <i class="fas fa-video"></i>
  331. 文生视频
  332. </a>
  333. </div>
  334. </div>
  335. <div class="content-area">
  336. <!-- 左侧输入区域 -->
  337. <div class="input-section">
  338. <h3 style="font-size: 18px; font-weight: bold; margin-bottom: 15px; color: #333;">文生图生成参数设置</h3>
  339. <!-- 提示词示例 -->
  340. <div class="prompt-examples">
  341. <label for="prompt">提示词</label>
  342. <textarea id="prompt" class="prompt-textarea" placeholder="请输入您想要生成的图像描述,越详细越好..."></textarea>
  343. </div>
  344. <!-- 生成参数 -->
  345. <div class="form-group">
  346. <label>生成参数</label>
  347. <div class="params-grid">
  348. <div class="param-item">
  349. <label for="style">风格</label>
  350. <select id="style">
  351. <option value="">默认</option>
  352. <option value="anime">动漫</option>
  353. <option value="oil">油画</option>
  354. <option value="landscape">风景</option>
  355. <option value="portrait">人像</option>
  356. </select>
  357. </div>
  358. <div class="param-item">
  359. <label for="imageSize">尺寸</label>
  360. <select id="imageSize">
  361. <option value="1:1">1:1</option>
  362. <option value="4:3">4:3</option>
  363. <option value="3:4">3:4</option>
  364. <option value="16:9">16:9</option>
  365. <option value="9:16">9:16</option>
  366. </select>
  367. </div>
  368. </div>
  369. </div>
  370. <div class="button-group">
  371. <button class="clear-btn" onclick="clearPrompt()">
  372. <i class="fas fa-trash"></i>
  373. 清空
  374. </button>
  375. <button class="optimize-btn" onclick="optimizePrompt()">
  376. <i class="fas fa-magic"></i>
  377. 一键优化
  378. </button>
  379. <button class="btn btn-primary" id="generateBtn" onclick="generateImage()">
  380. <i class="fas fa-arrow-up"></i>
  381. 生成图像
  382. </button>
  383. </div>
  384. </div>
  385. <!-- 右侧预览区域 -->
  386. <div class="preview-section">
  387. <h3 style="font-size: 18px; font-weight: bold; margin-bottom: 15px; color: #333;">图像预览</h3>
  388. <!-- 预览容器 -->
  389. <div id="imageResult" class="preview-container">
  390. <div class="preview-placeholder">
  391. <p>点击"生成图像"按钮开始创建您的模板</p>
  392. <p style="font-size: 12px; margin-top: 10px; color: #999;">生成时间可能需要几秒到几十秒不等</p>
  393. </div>
  394. </div>
  395. <!-- 模板信息 -->
  396. <div class="template-info">
  397. <h4>模板信息</h4>
  398. <div class="template-form">
  399. <input type="text" id="templateName" placeholder="请输入模板名称">
  400. </div>
  401. </div>
  402. <!-- 保存按钮 -->
  403. <div class="button-group">
  404. <button class="btn btn-primary" id="saveBtn" disabled onclick="saveTemplate()">保存为模板</button>
  405. <button class="btn btn-secondary" id="downloadBtn" disabled onclick="downloadImage()">下载图像</button>
  406. </div>
  407. </div>
  408. </div>
  409. </div>
  410. <script>
  411. // 自定义提示框函数
  412. function showAlert(message, type = 'info', duration = 3000) {
  413. // 检查是否已存在提示框容器,如果不存在则创建
  414. let alertElement = document.getElementById('customAlert');
  415. if (!alertElement) {
  416. alertElement = document.createElement('div');
  417. alertElement.id = 'customAlert';
  418. alertElement.className = 'custom-alert';
  419. document.body.appendChild(alertElement);
  420. }
  421. alertElement.textContent = message;
  422. alertElement.className = `custom-alert ${type}`;
  423. // 显示提示框
  424. alertElement.classList.add('show');
  425. // 自动隐藏
  426. setTimeout(() => {
  427. alertElement.classList.remove('show');
  428. }, duration);
  429. }
  430. // 生成图片函数
  431. function generateImage() {
  432. const promptText = document.querySelector('.prompt-textarea').value.trim();
  433. const imageStyle = document.getElementById('style').value;
  434. const imageSize = document.getElementById('imageSize').value;
  435. const imageResultDiv = document.getElementById('imageResult');
  436. // 检查是否有提示词
  437. if (!promptText) {
  438. showAlert('请先输入图片描述', 'warning');
  439. return;
  440. }
  441. // 显示加载状态
  442. imageResultDiv.innerHTML = `
  443. <div class="image-loading">
  444. <i class="fas fa-spinner fa-spin"></i>
  445. <p>正在生成图片,请稍候...</p>
  446. <p style="font-size: 12px; margin-top: 10px; color: #999;">生成时间可能需要几秒到几十秒不等</p>
  447. </div>
  448. `;
  449. // 拼接风格和尺寸到提示词末尾
  450. let fullPrompt = promptText;
  451. if (imageStyle) {
  452. fullPrompt += '风格:' + imageStyle;
  453. }
  454. if (imageSize) {
  455. fullPrompt += '尺寸比例:' + imageSize;
  456. }
  457. // 发送请求到文生图接口
  458. $.ajax({
  459. url: '/index.php/api/work_order/GetTxtToImg',
  460. type: 'POST',
  461. dataType: 'json',
  462. data: {
  463. status_val: '文生图',
  464. prompt: fullPrompt,
  465. model: 'gemini-3-pro-image-preview',
  466. style: imageStyle,
  467. size: imageSize
  468. },
  469. success: function(response) {
  470. // 处理成功响应
  471. if (response.code === 0 && response.data && response.data.url) {
  472. // 显示生成的图片
  473. imageResultDiv.innerHTML = `
  474. <div class="image-container">
  475. <img src="${response.data.url}" alt="生成的图片" class="generated-image" id="previewImage" style="max-width: 100%; height: auto; max-height: 600px; cursor: pointer;">
  476. </div>
  477. `;
  478. // 启用下载和保存按钮
  479. document.getElementById('downloadBtn').disabled = false;
  480. document.getElementById('saveBtn').disabled = false;
  481. // 添加图片放大模态框(如果还不存在)
  482. if (!document.getElementById('imageModal')) {
  483. const modal = document.createElement('div');
  484. modal.id = 'imageModal';
  485. modal.style.cssText = `
  486. display: none;
  487. position: fixed;
  488. z-index: 9999;
  489. left: 0;
  490. top: 0;
  491. width: 100%;
  492. height: 100%;
  493. overflow: auto;
  494. background-color: rgba(0, 0, 0, 0.9);
  495. justify-content: center;
  496. align-items: center;
  497. `;
  498. modal.style.display = 'flex';
  499. modal.style.display = 'none';
  500. const modalContent = document.createElement('img');
  501. modalContent.id = 'modalImage';
  502. modalContent.style.cssText = `
  503. max-width: 90%;
  504. max-height: 90%;
  505. margin: auto;
  506. `;
  507. const closeBtn = document.createElement('span');
  508. closeBtn.innerHTML = '&times;';
  509. closeBtn.style.cssText = `
  510. position: absolute;
  511. top: 20px;
  512. right: 35px;
  513. color: #f1f1f1;
  514. font-size: 40px;
  515. font-weight: bold;
  516. transition: 0.3s;
  517. cursor: pointer;
  518. `;
  519. closeBtn.onclick = function() {
  520. modal.style.display = 'none';
  521. };
  522. modal.appendChild(closeBtn);
  523. modal.appendChild(modalContent);
  524. document.body.appendChild(modal);
  525. // 点击模态框背景关闭
  526. modal.onclick = function(event) {
  527. if (event.target.id === 'imageModal') {
  528. this.style.display = 'none';
  529. }
  530. };
  531. }
  532. // 为生成的图片添加点击事件
  533. const generatedImage = imageResultDiv.querySelector('.generated-image');
  534. generatedImage.onclick = function() {
  535. const modal = document.getElementById('imageModal');
  536. const modalImage = document.getElementById('modalImage');
  537. modalImage.src = this.src;
  538. modal.style.display = 'flex';
  539. };
  540. // 键盘ESC键关闭
  541. document.addEventListener('keydown', function(event) {
  542. if (event.key === 'Escape') {
  543. const modal = document.getElementById('imageModal');
  544. if (modal && modal.style.display === 'flex') {
  545. modal.style.display = 'none';
  546. }
  547. }
  548. });
  549. } else {
  550. // 显示错误信息
  551. imageResultDiv.innerHTML = `
  552. <div class="image-error">
  553. <i class="fas fa-exclamation-triangle"></i>
  554. <p>图片生成失败:${response.msg || '未知错误'}</p>
  555. </div>
  556. `;
  557. }
  558. },
  559. error: function(xhr, status, error) {
  560. // 处理网络错误
  561. imageResultDiv.innerHTML = `
  562. <div class="image-error">
  563. <i class="fas fa-exclamation-triangle"></i>
  564. <p>图像生成失败</p>
  565. </div>
  566. `;
  567. }
  568. });
  569. }
  570. // 一键优化提示词功能
  571. function optimizePrompt() {
  572. const textarea = document.querySelector('.prompt-textarea');
  573. const optimizeBtn = document.querySelector('.optimize-btn');
  574. if (textarea && textarea.value.trim() !== '') {
  575. // 显示加载状态
  576. const originalBtnText = optimizeBtn.innerHTML;
  577. optimizeBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 优化中...';
  578. optimizeBtn.disabled = true;
  579. // 构造请求参数
  580. const params = {
  581. status_val: '文生文',
  582. prompt: textarea.value,
  583. model: 'gemini-2.0-flash'
  584. };
  585. // 发送AJAX请求
  586. $.ajax({
  587. url: '/index.php/api/work_order/GetTxtToTxt',
  588. type: 'POST',
  589. data: params,
  590. dataType: 'json',
  591. success: function(data) {
  592. console.log(data);
  593. // 恢复按钮状态
  594. optimizeBtn.innerHTML = originalBtnText;
  595. optimizeBtn.disabled = false;
  596. // 优化成功,更新文本框内容
  597. textarea.value = data.content;
  598. textarea.scrollTop = textarea.scrollHeight;
  599. updateCharCount();
  600. // 显示优化成功提示
  601. const alert = document.createElement('div');
  602. alert.className = 'alert alert-success';
  603. alert.innerHTML = '提示词已优化!';
  604. alert.style.position = 'fixed';
  605. alert.style.top = '20px';
  606. alert.style.right = '20px';
  607. alert.style.zIndex = '9999';
  608. document.body.appendChild(alert);
  609. // 3秒后移除提示
  610. setTimeout(() => {
  611. alert.remove();
  612. }, 3000);
  613. }
  614. });
  615. } else {
  616. showAlert('请先输入提示词!', 'warning');
  617. }
  618. }
  619. // 清空提示词功能
  620. function clearPrompt() {
  621. const textarea = document.querySelector('.prompt-textarea');
  622. if (textarea) {
  623. textarea.value = '';
  624. textarea.focus();
  625. }
  626. }
  627. // 保存模板函数
  628. function saveTemplate() {
  629. // 获取所有需要的参数
  630. const templateName = document.getElementById('templateName').value;
  631. const prompt = document.getElementById('prompt').value.trim();
  632. const style = document.getElementById('style').value;
  633. const imageSize = document.getElementById('imageSize').value;
  634. const previewImage = document.getElementById('previewImage');
  635. // 验证必填项
  636. if (!templateName.trim()) {
  637. showAlert('请输入模板名称', 'error');
  638. return;
  639. }
  640. if (!prompt) {
  641. showAlert('请输入提示词', 'error');
  642. return;
  643. }
  644. if (!previewImage || !previewImage.src) {
  645. showAlert('请先生成图片', 'error');
  646. return;
  647. }
  648. // 准备请求参数
  649. // 将完整URL转换为相对路径
  650. let imageUrl = previewImage.src;
  651. try {
  652. const url = new URL(imageUrl);
  653. imageUrl = url.pathname;
  654. } catch (e) {
  655. // 如果已经是相对路径,直接使用
  656. }
  657. const params = {
  658. chinese_description: prompt,
  659. template_image_url: imageUrl,
  660. template_name: templateName,
  661. style: style,
  662. size: imageSize,
  663. type: '文生图' // 固定为文生图类型
  664. };
  665. // 显示加载状态
  666. const saveBtn = document.getElementById('saveBtn');
  667. const originalText = saveBtn.innerHTML;
  668. saveBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 保存中...';
  669. saveBtn.disabled = true;
  670. // 发送AJAX请求
  671. $.ajax({
  672. url: '/index.php/api/work_order/Add_Product_Template',
  673. type: 'POST',
  674. dataType: 'json',
  675. data: params,
  676. success: function(response) {
  677. if (response.code === 0) {
  678. showAlert('模板保存成功!', 'success');
  679. // 清空模板名称输入框
  680. document.getElementById('templateName').value = '';
  681. } else {
  682. showAlert('模板保存失败:' + (response.msg || '未知错误'), 'error');
  683. }
  684. },
  685. error: function(xhr, status, error) {
  686. console.error('AJAX请求失败:', error);
  687. showAlert('网络错误,模板保存失败', 'error');
  688. },
  689. complete: function() {
  690. // 恢复按钮状态
  691. saveBtn.innerHTML = originalText;
  692. saveBtn.disabled = false;
  693. }
  694. });
  695. }
  696. // 下载图像函数
  697. function downloadImage() {
  698. const previewImage = document.getElementById('previewImage');
  699. if (previewImage && previewImage.src) {
  700. // 创建临时链接下载图片
  701. const link = document.createElement('a');
  702. link.href = previewImage.src;
  703. // 生成更有意义的文件名
  704. const timestamp = new Date().getTime();
  705. const promptText = document.querySelector('.prompt-textarea').value.trim();
  706. // 从提示词中提取前20个字符作为文件名的一部分
  707. const promptPart = promptText.substring(0, 20).replace(/[^\w\u4e00-\u9fa5]/g, '') || 'image';
  708. // 组合文件名:提示词部分_时间戳.jpg
  709. const fileName = `${promptPart}_${timestamp}.jpg`;
  710. link.download = fileName;
  711. link.click();
  712. }
  713. }
  714. </script>
  715. </body>
  716. </html>