国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

225 Zeilen
11KB

  1. <?php
  2. /**
  3. * 小德AI助手对话框
  4. *
  5. * @version $id:ai_dialog.php 2025 tianya $
  6. * @package DedeBIZ.Dialog
  7. * @copyright Copyright (c) 2022 DedeBIZ.COM
  8. * @license GNU GPL v2 (https://www.dedebiz.com/license)
  9. * @link https://www.dedebiz.com
  10. */
  11. require_once(dirname(__FILE__) . "/config.php");
  12. if (empty($f)) {
  13. $f = 'form1.enclosure';
  14. }
  15. if (empty($comeback)) {
  16. $comeback = '';
  17. }
  18. $addparm = '';
  19. if (!empty($CKEditor)) {
  20. $addparm = '&CKEditor=' . $CKEditor;
  21. }
  22. if (!empty($CKEditorFuncNum)) {
  23. $addparm .= '&CKEditorFuncNum=' . $CKEditorFuncNum;
  24. }
  25. if (!empty($noeditor)) {
  26. $addparm .= '&noeditor=yes';
  27. }
  28. ?>
  29. <!DOCTYPE html>
  30. <html>
  31. <head>
  32. <meta charset="utf-8">
  33. <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
  34. <title>小德AI助手对话框</title>
  35. <link rel="stylesheet" href="/static/web/css/font-awesome.min.css">
  36. <link rel="stylesheet" href="/static/web/css/bootstrap.min.css">
  37. <link rel="stylesheet" href="/static/web/css/admin.css">
  38. <script src="/static/web/js/jquery.min.js"></script>
  39. <script src="/static/web/js/bootstrap.min.js"></script>
  40. <script src="/static/web/js/admin.main.js"></script>
  41. </head>
  42. <body class="p-3">
  43. <div class="card shadow-sm">
  44. <div class="card-header">小德AI助手:内容处理</div>
  45. <div class="card-body">
  46. <div class="form-group">
  47. <div class="alert alert-warning mb-0" role="alert">
  48. <span>处理过程中请勿关闭当前对话框,否则富文本处理将终止</span>
  49. </div>
  50. </div>
  51. <div class="form-group">
  52. <textarea id="prompt" class="form-control" style="height:160px" placeholder="请输入内容处理要求,例如:我需要将内容润色下,希望更专业"></textarea>
  53. </div>
  54. <div class="form-group">
  55. <label for="modelid" class="form-label">选择模型</label>
  56. <select id="modelid" class="form-control">
  57. <?php
  58. $dsql->SetQuery("SELECT AM.*,A.title as aititle FROM `#@__ai_model` AM LEFT JOIN `#@__ai` A ON A.id = AM.aiid ORDER BY AM.sortrank ASC,AM.id DESC");
  59. $dsql->Execute();
  60. while ($row = $dsql->GetObject()) {
  61. ?>
  62. <option value="<?php echo $row->id; ?>" <?php echo $row->isdefault == 1 ? ' selected' : ''; ?>><?php echo $row->model; ?> <?php echo $row->aititle; ?></option>
  63. <?php
  64. }
  65. ?>
  66. </select>
  67. </div>
  68. <div class="form-group">
  69. <button type="button" id="btnAIAction" class="btn btn-success btn-sm">确定</button>
  70. </div>
  71. </div>
  72. </div>
  73. <script>
  74. $("#btnAIAction").click(async function() {
  75. let body = window.opener.CKEDITOR.instances["<?php echo $f ?>"].getData();
  76. let prompt = document.getElementById("prompt").value;
  77. let modelid = document.getElementById("modelid").value;
  78. let req = await fetch(`api.php?action=get_ai_server&pname=body_edit&modelid=${modelid}&prompt=${prompt}`);
  79. let resp = await req.json();
  80. if (resp.code !== 0) {
  81. ShowMsg("获取服务器地址失败");
  82. return
  83. }
  84. let req2 = await fetch(`api.php?action=get_setbody_url`);
  85. let resp2 = await req2.json();
  86. if (resp2.code !== 0) {
  87. ShowMsg("获取服务器地址失败");
  88. return
  89. }
  90. let req3 = await fetch(resp2.data, {
  91. method: 'POST',
  92. headers: {
  93. 'Content-Type': 'application/x-www-form-urlencoded'
  94. },
  95. body: new URLSearchParams({
  96. body: body
  97. })
  98. });
  99. let resp3 = await req3.json();
  100. if (resp3.code !== 0) {
  101. ShowMsg("提交原始内容失败");
  102. return
  103. }
  104. let eventSource = new EventSource(resp.data);
  105. //新增状态跟踪变量
  106. let currentKey = null;
  107. let tagBuffer = "";
  108. let isClosingTag = false;
  109. $("#mdlAI").modal('hide');
  110. window.opener.CKEDITOR.instances["<?php echo $f ?>"].getCommand('openDedeBIZAi').disable();
  111. $("#btnAIAction").attr("disabled", "disabled");
  112. $("#prompt").attr("disabled", "disabled");
  113. $("#modelid").attr("disabled", "disabled");
  114. prompt = "";
  115. let bodyHtml = "";
  116. let lastChar = "";
  117. eventSource.onmessage = (event) => {
  118. const chars = event.data.split('');
  119. chars.forEach(char => {
  120. if (lastChar === '\\' && char === 'r') {
  121. char = '<br>'; //替换为br标签
  122. lastChar = ""; //清空追踪字符
  123. } else {
  124. lastChar = char; //记录当前字符
  125. }
  126. if (char === '\\') {
  127. return; //如果是反斜杠,跳过处理
  128. }
  129. if (currentKey) {
  130. if (char === '{') {
  131. isClosingTag = true;
  132. tagBuffer = '{';
  133. return;
  134. }
  135. if (isClosingTag) {
  136. tagBuffer += char;
  137. if (tagBuffer === `{/${currentKey}}`) {
  138. if (currentKey == "content") {
  139. window.opener.CKEDITOR.instances["<?php echo $f ?>"].setReadOnly(false);
  140. bodyHtml = "";
  141. } else {
  142. const input = document.querySelector(`[name="${currentKey}"]`);
  143. if (input) $(input).prop("disabled", false).removeClass("disabled"); //恢复输入状态
  144. }
  145. currentKey = null;
  146. isClosingTag = false;
  147. tagBuffer = "";
  148. return;
  149. }
  150. if (!`{/${currentKey}}`.startsWith(tagBuffer)) {
  151. if (currentKey == "content") {
  152. bodyHtml += tagBuffer;
  153. console.log(bodyHtml);
  154. window.opener.CKEDITOR.instances["<?php echo $f ?>"].setData(bodyHtml)
  155. } else {
  156. const input = document.querySelector(`[name="${currentKey}"]`);
  157. if (input) input.value += tagBuffer;
  158. }
  159. isClosingTag = false;
  160. tagBuffer = "";
  161. }
  162. } else {
  163. if (currentKey == "content") {
  164. bodyHtml += char;
  165. window.opener.CKEDITOR.instances["<?php echo $f ?>"].setData(bodyHtml)
  166. } else {
  167. const input = document.querySelector(`[name="${currentKey}"]`);
  168. if (input) {
  169. input.value += char;
  170. input.scrollTop = input.scrollHeight; //滚动到底部
  171. }
  172. }
  173. }
  174. } else {
  175. if (char === '{') {
  176. tagBuffer = '{';
  177. } else if (tagBuffer.startsWith('{')) {
  178. tagBuffer += char;
  179. if (char === '}') {
  180. const match = tagBuffer.match(/{([^>]+)}/);
  181. if (match) {
  182. currentKey = match[1];
  183. if (currentKey == "content") {
  184. window.opener.CKEDITOR.instances["<?php echo $f ?>"].setReadOnly(true);
  185. } else {
  186. const input = document.querySelector(`[name="${currentKey}"]`);
  187. if (input) {
  188. $(input).prop("disabled", true).addClass("disabled"); //仅禁用当前输入框
  189. input.value = "";
  190. }
  191. }
  192. }
  193. tagBuffer = "";
  194. }
  195. }
  196. }
  197. });
  198. };
  199. eventSource.onerror = (error) => {
  200. if (error.target.readyState === EventSource.CONNECTING) {
  201. ShowMsg("连接失败,请确保您已开启并正确配置了DedeBIZ小德AI助手。 <a class='text-success' href='https://www.dedebiz.com/ai?from=dedebiz' target='_blank'>如何配置?</a>");
  202. } else if (typeof error.data !== "undefined" && error.data !== "" && error.target.readyState !== EventSource.CLOSED) {
  203. ShowMsg(error.data);
  204. }
  205. window.opener.CKEDITOR.instances["<?php echo $f ?>"].getCommand('openDedeBIZAi').enable();
  206. $("#btnAI").prop("disabled", false);
  207. $("#btnAIAction").prop("disabled", false);
  208. $("#prompt").prop("disabled", false);
  209. $("#modelid").prop("disabled", false);
  210. eventSource.close();
  211. };
  212. //监听特定事件close
  213. eventSource.addEventListener('close', (event) => {
  214. console.log('SSE connection closed:', event.data);
  215. window.opener.CKEDITOR.instances["<?php echo $f ?>"].getCommand('openDedeBIZAi').enable();
  216. $("#btnAIAction").prop("disabled", false);
  217. $("#prompt").prop("disabled", false);
  218. $("#modelid").prop("disabled", false);
  219. eventSource.close(); //关闭连接
  220. window.opener.CKEDITOR.instances["<?php echo $f ?>"].setReadOnly(false);
  221. });
  222. });
  223. </script>
  224. </body>
  225. </html>