国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

405 line
16KB

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
  6. <title>批量添加栏目</title>
  7. <link rel="stylesheet" href="/static/web/css/font-awesome.min.css">
  8. <link rel="stylesheet" href="/static/web/css/bootstrap.min.css">
  9. <link rel="stylesheet" href="/static/web/css/admin.css">
  10. <script src="/static/web/js/jquery.min.js"></script>
  11. <script src="/static/web/js/bootstrap.min.js"></script>
  12. <script src="/static/web/js/admin.main.js"></script>
  13. </head>
  14. <body>
  15. <div class="container-fluid">
  16. <ol class="breadcrumb">
  17. <li class="breadcrumb-item"><a href="index_body.php">后台面板</a></li>
  18. <li class="breadcrumb-item"><a href="catalog_main.php">网站栏目管理</a></li>
  19. <li class="breadcrumb-item active">批量添加栏目</li>
  20. </ol>
  21. <div class="card shadow-sm">
  22. <div class="card-header d-flex justify-content-between align-items-center"><span>批量添加栏目</span><?php if ($cfg_ai_enabled == 'Y'){;?><button type="button" id="btnAI" onclick="showAI();" class="btn btn-success btn-sm">小德AI助手</button><?php };?></div>
  23. <div class="card-body">
  24. <form name="form1" action="catalog_add.php" method="post">
  25. <input type="hidden" name="dopost" value="savequick">
  26. <input type="hidden" name="savetype" id="savetype">
  27. <div class="table-responsive">
  28. <table class="table table-borderless">
  29. <tbody>
  30. <tr>
  31. <td width="10%">是否支持投稿</td>
  32. <td width="40%">
  33. <label><input type="radio" name="issend" value="1" checked> 支持</label>
  34. <label><input type="radio" name="issend" value="0"> 不支持</label>
  35. </td>
  36. <td width="10%">目录保存位置</td>
  37. <td width="40%">
  38. <label><input type="radio" name="referpath" value="parent" checked> 默认网页目录(
  39. <?php
  40. $pardir = '{cmspath}'.$cfg_arcdir;
  41. if (!empty($typedir)) $pardir = $typedir.'/';
  42. $pardir = preg_replace("#\/{1,}#", '/', $pardir);
  43. echo $pardir;
  44. ?>)</label>
  45. <label><input type="radio" name="referpath" value="cmspath"> 系统根目录</label>
  46. <input type="hidden" name="nextdir" id="nextdir" value="<?php echo $pardir;?>">
  47. <span id="pathtype" style="display:none"><input type="radio" name="referpath" id="truepath3" value="typepath">所属栏目所属目录</span>
  48. </td>
  49. </tr>
  50. <tr>
  51. <td>所属栏目</td>
  52. <td>
  53. <select name="reid" onchange="showSeltype(this);" class="admin-input-sm">
  54. <option value="0">选择所属栏目</option>
  55. <?php echo $typeOptions;?>
  56. </select>
  57. <span>(默认为顶级栏目)</span>
  58. </td>
  59. <td>文档模型</td>
  60. <td>
  61. <select name="channeltype" id="channeltype" onChange="ParTemplet(this);" class="admin-input-sm">
  62. <?php
  63. foreach($channelArray as $k=>$arr)
  64. {
  65. if ($k==$channelid) echo "<option value='{$k}' selected>{$arr['typename']} {$arr['nid']}</option>";
  66. else echo "<option value='{$k}'>{$arr['typename']} {$arr['nid']}</option>";
  67. }
  68. ?>
  69. </select>
  70. </td>
  71. </tr>
  72. <tr>
  73. <td>栏目列表选项</td>
  74. <td>
  75. <label><input type="radio" name="isdefault" value="1" checked> 静态浏览</label>
  76. <label><input type="radio" name="isdefault" value="-1"> 动态浏览</label>
  77. <label><input type="radio" name="isdefault" value="0"> 列表第一页浏览</label>
  78. </td>
  79. <td>列表命名规则</td>
  80. <td>
  81. <input type="text" name="namerule2" id="namerule2" value="{typedir}/{tid}-{page}.html" class="admin-input-lg">
  82. <a href="javascript:ShowHide('helpvar1');" class="btn btn-success btn-sm">说明</a>
  83. <div id="helpvar1" class="helpinfo my-2" style="display:none">
  84. <p>静态规则</p>
  85. <p>{tid} 栏目id</p>
  86. <p>{page} 栏目页码数</p>
  87. <p>伪静态规则(Nginx)</p>
  88. <p>rewrite ^/list/([0-9]+)$ /apps/list.php?tid=$1;</p>
  89. <p>rewrite ^/list/([0-9]+)-([0-9]+)$ /apps/list.php?tid=$1&PageNo=$2;</p>
  90. </div>
  91. </td>
  92. </tr>
  93. <tr>
  94. <td>文档命名规则</td>
  95. <td>
  96. <input type="text" name="namerule" id="namerule" value="{typedir}/{aid}.html" class="admin-input-lg">
  97. <a href="javascript:ShowHide('helpvar2');" class="btn btn-success btn-sm">说明</a>
  98. <div id="helpvar2" class="helpinfo my-2" style="display:none">
  99. <p>静态规则</p>
  100. <p>{Y}{M}{D} 年月日</p>
  101. <p>{timestamp} INT类型的UNIX时间戳</p>
  102. <p>{aid} 文档id</p>
  103. <p>{pinyin} 拼音加文档id</p>
  104. <p>{py} 拼音部首加文档id</p>
  105. <p>{typedir} 栏目保存目录</p>
  106. <p>{cc} 日期加混编id后用转换为适合字母</p>
  107. <p>伪静态规则(Nginx)</p>
  108. <p>rewrite ^/article/([0-9]+).html$ /apps/view.php?aid=$1;</p>
  109. <p>rewrite ^/article/([0-9]+)-([0-9]+).html$ /apps/view.php?aid=$1&PageNo=$2;</p>
  110. </div>
  111. </td>
  112. <td>默认页的名称</td>
  113. <td><input type="text" name="defaultname" value="index.html" class="admin-input-lg"></td>
  114. </tr>
  115. <tr>
  116. <td colspan="4">
  117. <table id="addQuick" class="table">
  118. <thead>
  119. <tr>
  120. <td scope="col">排序</td>
  121. <td scope="col">顶级栏目名称</td>
  122. <td scope="col">子栏目名称(英文逗号隔开,例:栏目一,栏目二)</td>
  123. <td scope="col"><button type="button" class="btn btn-success btn-sm add">添加</button></td>
  124. </tr>
  125. </thead>
  126. <tbody>
  127. <tr>
  128. <td class="rank">
  129. <input type="hidden" name="posttype" class="pubinputs">
  130. <input type="text" name="rank" value="1" class="pubinputs admin-input-sm">
  131. </td>
  132. <td><input type="text" name="toptype" class="pubinputs admin-input-lg"></td>
  133. <td><input type="text" name="sontype" class="pubinputs w-100"></td>
  134. <td><button name="" type="button" class="btn btn-danger btn-sm del">删除</button></td>
  135. </tr>
  136. <?php for($i=2;$i<=10;$i++) {?>
  137. <tr class="repeat">
  138. <td class="rank">
  139. <input type="hidden" name="posttype<?php echo $i;?>" value="<?php echo $i;?>">
  140. <input type="text" name="rank<?php echo $i;?>" value="<?php echo $i;?>" class="pubinputs admin-input-sm">
  141. </td>
  142. <td><input type="text" name="toptype<?php echo $i;?>" class="pubinputs admin-input-lg"></td>
  143. <td><input type="text" name="sontype<?php echo $i;?>" class="pubinputs w-100"></td>
  144. <td><button name="" type="button" class="btn btn-danger btn-sm del">删除</button></td>
  145. </tr>
  146. <?php }?>
  147. </tbody>
  148. </table>
  149. <table id="addQuickRel" class="table" style="display:none">
  150. </thead>
  151. <tr>
  152. <td scope="col">排序</td>
  153. <td scope="col">栏目名称</td>
  154. <td scope="col"><button type="button" class="btn btn-success btn-sm addrel">添加</button></td>
  155. </tr>
  156. </thead>
  157. <tbody>
  158. <tr>
  159. <td class="rank">
  160. <input type="hidden" name="posttype" class="pubinputs">
  161. <input type="text" name="rank" value="1" class="pubinputs admin-input-sm">
  162. </td>
  163. <td><input type="text" name="reltype" class="pubinputs admin-input-lg"></td>
  164. <td><button name="" type="button" class="btn btn-danger btn-sm del">删除</button></td>
  165. </tr>
  166. <?php for($i=2;$i<=10;$i++) {?>
  167. <tr class="repeat">
  168. <td class="rank">
  169. <input type="hidden" name="posttype<?php echo $i;?>" value="<?php echo $i;?>">
  170. <input type="text" name="rank<?php echo $i;?>" value="<?php echo $i;?>" class="pubinputs admin-input-sm">
  171. </td>
  172. <td><input type="text" name="reltype<?php echo $i;?>" class="pubinputs admin-input-lg"></td>
  173. <td><button type="button" class="btn btn-danger btn-sm del">删除</button></td>
  174. </tr>
  175. <?php }?>
  176. </tbody>
  177. </table>
  178. </td>
  179. </tr>
  180. <tr>
  181. <td colspan="4" align="center">
  182. <button type="submit" class="btn btn-success btn-sm">保存</button>
  183. <a href="catalog_main.php" class="btn btn-outline-success btn-sm">返回</a>
  184. </td>
  185. </tr>
  186. </tbody>
  187. </table>
  188. </div>
  189. </form>
  190. </div>
  191. </div>
  192. </div>
  193. <div id="mdlAI" class="modal fade" tabindex="-1" aria-hidden="true">
  194. <div class="modal-dialog modal-xl">
  195. <div class="modal-content">
  196. <div class="modal-header">
  197. <h5 class="modal-title">小德AI助手:批量创建栏目</h5>
  198. <button type="button" class="update-close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times"></i></button>
  199. </div>
  200. <div class="modal-body">
  201. <form>
  202. <div class="form-group">
  203. <textarea id="prompt" class="form-control" style="height:160px" placeholder="请输入批量创建栏目要求,例:我需要创建一个企业信息展示类站点"></textarea>
  204. </div>
  205. <div class="form-group">
  206. <label for="modelid" class="form-label">选择模型</label>
  207. <select id="modelid" class="form-control">
  208. <?php
  209. $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");
  210. $dsql->Execute();
  211. while ($row = $dsql->GetObject()) {
  212. ?>
  213. <option value="<?php echo $row->id;?>" <?php echo $row->isdefault==1?' selected' : '';?>><?php echo $row->model;?> <?php echo $row->aititle;?></option>
  214. <?php
  215. }
  216. ?>
  217. </select>
  218. </div>
  219. </form>
  220. </div>
  221. <div class="modal-footer">
  222. <button id="btnAIAction" class="btn btn-success btn-sm">确定</button>
  223. </div>
  224. </div>
  225. </div>
  226. </div>
  227. <script>
  228. var $ = jQuery;
  229. function ShowHide(objname) {
  230. var obj = document.getElementById(objname);
  231. if (obj.style.display == "block")
  232. obj.style.display = "none";
  233. else
  234. obj.style.display = "block";
  235. };
  236. function ShowObj(objname) {
  237. var obj = document.getElementById(objname);
  238. obj.style.display = "block";
  239. };
  240. function HideObj(objname) {
  241. var obj = document.getElementById(objname);
  242. obj.style.display = "none";
  243. };
  244. function showSeltype(objname) {
  245. if (objname.value != 0) {
  246. $("#addQuickRel").show();
  247. $("#pathtype").show();
  248. $("#addQuick").hide();
  249. $("#savetype").val('rel');
  250. } else {
  251. $("#addQuickRel").hide();
  252. $("#addQuick").show();
  253. $("#pathtype").hide();
  254. $("#savetype").val('');
  255. }
  256. };
  257. $(function($) {
  258. //添加按钮事件
  259. $("#addQuick .add").click(function() {
  260. var id = $("#addQuick tr").prevAll("tr").length + 2;
  261. $("#addQuick tr:eq(1)").clone(true).addClass("repeat")
  262. .find(".rank input").attr("value", function() {
  263. return id;
  264. }).end().find(".pubinputs").attr("name", function() {
  265. return this.name + id;
  266. }).end().appendTo($("#addQuick"));
  267. });
  268. //删除按钮事件
  269. $("#addQuick .del").click(function() {
  270. $(this).parents(".repeat").remove();
  271. });
  272. //删除按钮事件
  273. $("#addQuickRel .del").click(function() {
  274. $(this).parents(".repeat").remove();
  275. });
  276. //添加按钮事件
  277. $("#addQuickRel .addrel").click(function() {
  278. var id = $("#addQuickRel tr").prevAll("tr").length + 1;
  279. $("#addQuickRel tr:eq(1)").clone(true).addClass("repeat").find(".rank input").attr("value", function() {
  280. return id;
  281. }).end().find(".pubinputs").attr("name", function() {
  282. return this.name + id;
  283. }).end().appendTo($("#addQuickRel"));
  284. });
  285. });
  286. function showAI() {
  287. $("#mdlAI").modal('show');
  288. }
  289. $("#btnAIAction").click(async function() {
  290. let prompt = document.getElementById("prompt").value;
  291. let modelid = document.getElementById("modelid").value;
  292. let req = await fetch(`api.php?action=get_ai_server&pname=catalog_add_quick&modelid=${modelid}&prompt=${prompt}`);
  293. let resp = await req.json();
  294. if (resp.code !== 0) {
  295. ShowMsg("获取服务器地址失败");
  296. return
  297. }
  298. let eventSource = new EventSource(resp.data);
  299. //新增状态跟踪变量
  300. let currentKey = null;
  301. let tagBuffer = "";
  302. let isClosingTag = false;
  303. $("#mdlAI").modal('hide');
  304. $("#btnAI").attr("disabled", "disabled");
  305. prompt = "";
  306. let lastChar = "";
  307. eventSource.onmessage = (event) => {
  308. const chars = event.data.split('');
  309. chars.forEach(char => {
  310. if (lastChar === '\\' && char === 'r') {
  311. char = '<br>'; //替换为br标签
  312. lastChar = ""; //清空追踪字符
  313. } else {
  314. lastChar = char; //记录当前字符
  315. }
  316. if (char === '\\') {
  317. return; //如果是反斜杠,跳过处理
  318. }
  319. if (currentKey) {
  320. if (char === '{') {
  321. isClosingTag = true;
  322. tagBuffer = '{';
  323. return;
  324. }
  325. if (isClosingTag) {
  326. tagBuffer += char;
  327. if (tagBuffer === `{/${currentKey}}`) {
  328. if (currentKey == "content") {
  329. //CKEDITOR.instances["content"].setReadOnly(false);
  330. } else {
  331. const input = document.querySelector(`[name="${currentKey}"]`);
  332. if (input) $(input).prop("disabled", false).removeClass("disabled"); //恢复输入状态
  333. }
  334. currentKey = null;
  335. isClosingTag = false;
  336. tagBuffer = "";
  337. return;
  338. }
  339. if (!`{/${currentKey}}`.startsWith(tagBuffer)) {
  340. if (currentKey == "content") {
  341. CKEDITOR.instances["content"].insertHtml(tagBuffer);
  342. } else {
  343. const input = document.querySelector(`[name="${currentKey}"]`);
  344. if (input) input.value += tagBuffer;
  345. }
  346. isClosingTag = false;
  347. tagBuffer = "";
  348. }
  349. } else {
  350. if (currentKey == "content") {
  351. CKEDITOR.instances["content"].insertHtml(char);
  352. } else {
  353. const input = document.querySelector(`[name="${currentKey}"]`);
  354. if (input) {
  355. input.value += char;
  356. input.scrollTop = input.scrollHeight; //滚动到底部
  357. }
  358. }
  359. }
  360. } else {
  361. if (char === '{') {
  362. tagBuffer = '{';
  363. } else if (tagBuffer.startsWith('{')) {
  364. tagBuffer += char;
  365. if (char === '}') {
  366. const match = tagBuffer.match(/{([^>]+)}/);
  367. if (match) {
  368. currentKey = match[1];
  369. if (currentKey == "content") {
  370. //CKEDITOR.instances["content"].setReadOnly(true);
  371. CKEDITOR.instances["content"].setData("")
  372. } else {
  373. const input = document.querySelector(`[name="${currentKey}"]`);
  374. if (input) {
  375. $(input).prop("disabled", true).addClass("disabled"); //仅禁用当前输入框
  376. input.value = "";
  377. }
  378. }
  379. }
  380. tagBuffer = "";
  381. }
  382. }
  383. }
  384. });
  385. };
  386. eventSource.onerror = (error) => {
  387. if (error.target.readyState === EventSource.CONNECTING) {
  388. ShowMsg("连接失败,请确保您已开启并正确配置了DedeBIZ小德AI助手。 <a class='text-success' href='https://www.dedebiz.com/ai?from=dedebiz' target='_blank'>如何配置?</a>");
  389. } else if (typeof error.data!=="undefined" && error.data !== "" && error.target.readyState !== EventSource.CLOSED) {
  390. ShowMsg(error.data);
  391. }
  392. $("#btnAI").prop("disabled", false);
  393. eventSource.close();
  394. };
  395. //监听特定事件close
  396. eventSource.addEventListener('close', (event) => {
  397. console.log('SSE connection closed:', event.data);
  398. $("#btnAI").prop("disabled", false);
  399. eventSource.close(); //关闭连接
  400. });
  401. });
  402. </script>
  403. </body>
  404. </html>